My Authors
Read all threads
A common mid-sized refactoring: "Replace Implementation Inheritance". The idea is to either eliminate concrete superclasses altogether or to halt their usage below a certain class in the chain.
The basic implementation intheritance (II) concept looks like this: You have an abstraction Interface. You have an implementor Super. You imagine a second implementor, Sub, that is "almost like" Super. So you derive Sub off of Super and override some of its methods.
The inheritance chain looks like Abstraction -> Super -> Sub. And of course, we can keep going, with Sub -> GrandSub -> GreatGrandSub, and so on. And all of these classes except Abstraction itself are concrete: they have functions with bodies.

That's implementation inheritance.
We've said before. traditional software pedagogy emphasizes greenfield designs. II is one of the techniques the greenfielders *adore*, so they teach the hell out of it, using it at every turn, in their POS system, or their Vacation Rentals, in whatever 1kloc toy they make.
The great and grand official merit of II is "code reuse". You only have to write the code that's in Super one time. The code that's in Sub overrides only a few pieces of the code in Super. GrandSub only overrides a few tiny pieces more, and so on.
Sadly, greenfield work is only a fraction of the life of a professional programmer. We make our daily bread in brownfield work: not by writing whole projects from start to finish and walking away, but by changing projects that are already shipping.

Brownfielders *hate* II.
I'll give you both a theoretical and a real-life explanation why II creates designs that make brownfield work harder.
Theory: II designs spread algorithms out over multiple permeable classes implicitly. Each of these three aspects -- the multiple spread, the permeability, and the implicitness -- add complexity any time we need to use them.
Now, a domain is likely to *require* one of those three aspects. But when we pile all three on at once, we virtually guarantee that our code has more pieces in play than a human can easily hold in her head at one time.
Designs that humans can't readily grok -- manipulate in mental space -- are the exact opposite of what is needed by most professional programmers most of the time.
Real-Life: Go look at JavaFx Node, here.

docs.oracle.com/javase/8/javaf…

It's a concrete class. It has 8 concrete subs. Drill down to Parent. It has 3 concrete subs. Drill down to Region. It has 3 concrete subs. Drill down to Pane. 11 subs.
For extra credit,
1) Go read the code of any sub of Pane and tell me what it does without reading the docs.

2) wonder where SplitPane is. I mean, you know you have one, where is it? (Spoiler: it's not a Pane, it's a Control.)
And here's the thing: JavaFx is comparatively sane. I'm not just picking on it: The old Microsoft Foundation Classes does this kinda stuff using 8 and 9 levels of II at a time.

*Every* II-centric library or framework or codebase eventually looks like this.
The price of having to change or alter any functionality in an II-centric design is based entirely on whether the greenfield designer, someone from years before that professional programmers don't usually even know, foresaw the need you currently have.
Every change boils down to these questions: 1) Did she leave a hook for that? 2) If so, where is it? 3) If not, how far up that II hierarchy do I have to go to put it in? 4) Was Mom actually right, that I woulda made a great and highly successful rodeo clown?
So the case for II is that it has code reuse, and the case against II is that it is anti-change.

The refactorings we're finally going to look at accept the "against" case. With vigor.
There are two possibilities to consider. Either you're about to commit II yourself, or you're about to use someone else's code that has committed II. We handle them differently.
If you are about to commit II yourself: don't.

This is more straightforward than it might seem, given the pedagogy. Let's take a quick look at it.
Abstraction <- Super <- Sub is your design because you Sub is only a little different from Super. This is expressed in code like this: Super has a method a() with multiple calls to other methods b(), c(), d(). Sub is "the same, but" as Super.
Sub wants to change one or more of those four methods while still using some of them. (If it doesn't want to still use some of them, it should just derive right off Abstraction.)
Let's say you wish c() was a little different. No problem: create a new abstraction CDelegate and give Super a member of that type. Now, change the body of c() in Super so that he tells his CDelegate to do that part.
Now implement two CDelegates OldCDelegate does it the old way, and NewCDelegate does it your "the same, but" way. You can do this for any number of those methods. You can put all the delegation in one interface Delegate, or you can use multiple interfaces.
What if you want to tweak a() to still use b(), c(), and d(), but also slightly rearrange the ordering and also call e(). The same technique works, but from the other point of view. Here *Super* becomes your delegate, and you create a new class whose a() calls its b, c, and d.
Okay, mentally, that's a helluva lot of abstract text I just wrote. Let's do this: I will stop describing this fix. Then, in the next muse, I'll show you some real code so you can see this one in action. I freely admit it's a lot to wrap your head around.
Let's call it a wrap. We hereby declare that today's topic is retroactively: We don't like Implementation Inheritance. We'll stop, for now, with the case. In the next muse, I'll give you a concrete example of a place where we're tempted to use II, and how we can avoid it.
Meanwhile, if you like my content, you might want to make sure you actually *get* it. Most of my threads wind up as both blogs and podcasts, and you can subscribe. It's free, it's spam-free, and it supports my content work.

Subscribe now!

geepawhill.org
Missing some Tweet in this thread? You can try to force a refresh.

Enjoying this thread?

Keep Current with GeePaw Hill

Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!