Upskill tutorial to replace mixins (multiple inheritances) with composition

Hud Wahab
4 min readJul 30, 2023

--

Day 30: Dataclass. field. Property

Hi 👋 I am Hud, a postdoc for engineering data science at the AI Manufacturing Center in Laramie, Wyoming. My funding is running out (AaAaaA !), so while I am actively looking for a new job, instead of doing the 205th coding certificate to prove my worthiness — I thought I’d do design challenges and document how I spend my time upskilling so other engineers can do the same.

Nowadays, certificates are everywhere. Documenting small upskill projects that you can later show off is the best way to get recognition as a professional engineer.

This is final day of a 30-day design challenge. Follow along and let me know if you get stuck!

TL;DR tasks

Download the provided code for the challenge.

Task 1: Replace mixin classes with separate classes

  • Create separate classes for the different character types (e.g., Warrior, Mage, Archer) instead of using mixins.

Task 2: Implement composition for character behavior

  • Instead of inheriting behavior from the mixins, create separate classes for the character behavior (e.g., AttackBehavior, DefenseBehavior) and use composition to include these behaviors in the character classes.

Task 3: Refactor character methods

  • Modify the character methods to use the behavior classes through composition instead of relying on mixins.

Task 4: Update the main game logic

  • Modify the game logic to create instances of the character classes and use their behavior through composition.

Task 5: Test the refactored code

  • Ensure that the game still functions correctly after the refactor by running various scenarios and testing different character types and behaviors.

Task 6: Validate code readability and maintainability

  • Review the refactored code to ensure that it is cleaner and easier to read and maintain compared to the original version using mixins.

Task 7: Verify IDE autocompletion and suggestions

  • Confirm that IDE autocompletion and suggestions work properly with the refactored code and that there are no issues related to multiple inheritance.

Task 8: Consider trade-offs and benefits

  • Evaluate any trade-offs made during the refactor and compare the benefits of using composition over mixins in terms of code design and maintainability.

The problem

I don’t like mixins. But sometimes my graduate students try to convince me of its use cases and I will generally steer them away from it. Let’s have a look at how a mixin or multiple inheritance might look like:

Looking at the code, we can see that the Knight class is using multiple inheritance to inherit from both PowerUp and GameCharacter ; the same goes for the Wizard class, but with a Spell instead of PowerUp. While this is a valid use of multiple inheritance, it can lead to issues with code maintainability and complexity. In particular, it can be difficult to reason about the behavior of a class that uses multiple inheritance, and it can be hard to avoid code duplication. Additionally, multiple inheritance can lead to issues with method resolution order, which can cause unexpected behavior. Let’s see what else is important:

Essentially, we will have a Knight or a Wizard attack a Knight or a Wizard , and some attributes like damage, shield and mana cost (what mana cost, where? Exactly, it’s hidden in the open in theWizard class). But now we’re resorting to using isinstance to determine the game character type, etc — that screams for some serious refactoring. So what should we use instead?

Well hopefully after 30 days of challenges you recognize the bottomline — use composition over (multiple) inheritances!

The solution

What we are trying to achieve here is to avoid having to create a separate class for Knight or Wizard or whatever it is and replace that with just a GameCharacter. We will use composition to solve this — we’ve used composition throughout all the challenges so far, check those out to know more about it. Let’s see how we can use this again here:

We first separate those attributes that we will be using as separate objects. Now we can can update the GameCharacter class to include mana and a list of defenses — as you can see this is already more flexible than the mixins options as we can have multiple defenses. We calculate the defenses and damages as properties and refactor the logic for a more generalized attack (and removed pescy things like isinstance from before).

Finally, we can simply create an arbitrary character, weapon and spell types without having to create a separate class for each!

Conclusion

Congratulations! You finished the whole 30-day design challenge! I am very proud of you!

If you have reached this far, you know how to accomplish many software design problems and for this challenge you know how to:

  • Avoid mixins (multiple inheritances) by using composition

If you’ve followed along throughout and it was somewhat helpful to you — be sure to give it a clap, subscribe and not miss out on my next articles!

Also, you can access the full 30-day GitHub repository here.

💡 My goal here is to help engineering data scientists upskill in design. I’d like to hear from you! Was this helpful? Anything I can improve? Connect with me on LinkedIn | Medium

--

--

Hud Wahab

🤖 Senior ML Engineer | Helping machine learning engineers design and productionize ML systems. | Let's connect: https://rb.gy/vb6au