3

I'm refactoring some code which isn't very reusable and has quite a bit of duplicate code. The code has two classes A and B which extend the abstract class I. But there are subclasses of A and B to support concepts X and Y so the result is concrete classes AX, AY, BX, BY with concepts X and Y copy and pasted into each.

So I know I can use composition here to delegate support for features X and Y but this also requires code that builds these objects etc which is why I started reading about mixins, so I'm wondering if my code is a good solution

class I(ABC):
    @abstractmethod
    def doSomething():
        pass

class ICommon(ABC):
    @abstractmethod
    def doSomethingCommon():
        pass

class A(I, ICommon): 
    # the interface(s) illustrates what mixins are supported 
    # class B could be similar, but not necessarily with the same interfaces
    def doSomething():
        self.doSomethingCommon()
        ...

class XCommonMixin(object): 
    # feature X shared possibly in A and B
    # I have also split features X into much smaller concise parts, 
    # so the could be a few of these mixins to implement the different 
    # features of X
    def doSomethingCommon():
        return 42

class AX(XCommonMixin, A):
    pass 
    # init can be defined to construct A and bases if any as appropriate
stovfl
  • 14,998
  • 7
  • 24
  • 51
ovg
  • 1,486
  • 1
  • 18
  • 30
  • in 6 months, someone will need to read the code (even a future you)... will they understand it? if you think they will, go ahead and implement your sophisticated solution. then come back in 6 months to see if you were right. – Aprillion Sep 23 '18 at 19:20
  • I am currently facing the exact same situation whit the same motivation: Code deduplication. What was your experience? Did you have problems that others understand the "complexity" of that approach? – maggie Feb 06 '23 at 14:11

1 Answers1

2

Yes, this is exactly what mixins (or, more generally, classes) exist for. A class is supposed to encapsulate all the features associated with a specific concept or purpose (like your A and B, but also like your X and Y).

I believe you're overthinking this. You probably know how to use classes, and mixins are really just classes that were given a fancy name because they require multiple inheritance in order to work. (Because mixins are not always complete classes capable of functioning by themselves; they're a collection of features that can be attached to other classes.) Classes are about separation of concerns. One concern - one class. Implement a class for each of the 4 concepts A, B, X and Y, and then combine them (with multiple inheritance) as you see fit.

I strongly suggest reading What is a mixin, and why are they useful?. The (current) highest rated answer does a good job explaining that mixins exist precisely for situations like this.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
  • I might be overthinking it but it's my first time using mixins (and coming across a reason to use them) but having been always told that multiple inheritance is evil I'm trying to make sure I do this right ;) I guess my question differs mostly from things I've read because I'm using the mixing to implement abstract hooks which are called from within the abstract class rather than adding a district feature with a 'public' method like in most example. Does this change anything? – ovg Sep 23 '18 at 19:57
  • @ovg Nope. Each of your classes implements a set of features. Whether or not those features were declared abstract in the parent class doesn't matter. Classes are a tool for code reuse. You're using them exactly as intended. – Aran-Fey Sep 23 '18 at 19:59