I mostly agree with the author and mixins/concerns create more confusion.
The only exception I would make is when you are writing a gem. For the external library it’s important to have simple interface when you have one object with all functionality. So in the gem you will have single empty class with 10 includes. I’ve seen that pattern used a lot in gems and seems to work well.
Do you think mixins/concerns are OO anti-pattern? How often do you use concerns yourself?
I think the main problem is that many believe they’re using composition when including a mixin to their classes. Including a mixin is actually inheritance; and if you think that way; it makes sense why the mixin can read private instance variables for example.
Inheritence creates an “is a” relationship, so it would be appropriate when the following makes sense: “MyClass is a MixedInClass” which is usually not the case. Usually you want a “has a” relationship which is what composition will bring you.
If you favour Composition over inheritance then you’ll use less mixins and simply create new classes, which the author aludes to at the end of the article. The decorator pattern uses composition to create a “has a” style relationship, which makes sense in the example given.
I usually go even further and think of mixins as copy-pasted code. What I observed on many teams is that people look at a huge class and think “wow, this is bad, let’s make it shorter” - split it up into a bunch of mixins, and “hey, now they’re all short and awesome”.
But they don’t solve a problem of bad OO design this way - just hide it by sweeping it under the rug of multiple files. If you look at a class as an entity, nothing changed in it after the split - it’s still the same huge ugly class.
I’ve been fortunate to work on a few long-term projects (over 5 years of constant development and maintenance), and mixins never worked out well, but just ended up bringing a mess. This is why the same patterns now popping up in JS land (such as stamps) do bug me a lot, as they look like the same bad idea repeated all over again.
The thing that did work, though, is what @mario says - identifying units of reuse or separate domain entities, and splitting a huge classes into many composed objects. The small ones are also much easier to test - less behaviour and edge cases to cover, smaller setup, faster tests overall, and then just an integration test over the whole feature to make sure everything plays nicely together.
As an aside, I recently came across a research paper on this very topic - Traits: A Mechanism for Fine-Grained Reuse, where authors argue against mixins and multiple inheritance, but it favour of traits, which are different from mixins as being stateless and only defining methods with explicit conflict resolution mechanisms. Scala comes to mind as an obvious example of this implemented in today’s world, but I haven’t done enough of it to really have an informed opinion - I’d be very interested to hear from someone with more experience here.