3

We have a relatively big class. One of my colleagues thinks we must split this class into a base & child class to make it smaller and cleaner.

On the other hand, I believe when we know this parent will always have only just this one child, inheritance isn't an appropriate solution.

So imagine these classes:

public class Foo : Bar, IFoo
{    
    public Task DoSomething(SomeData someDate)
    {
    }
    // Some other public methods that are exposed in IFoo interface

}

public abstract class Bar
{
    protected readonly ISomeInjectedService _someInjectedService;
    public Bar(ISomeInjectedService someInjectedService)
    {
        _someInjectedService=someInjectedService;
    }
    // Some other private or protected methods
}

Or this class:

public class Foo : IFoo
{
    private readonly ISomeInjectedService _someInjectedService;
    public Foo(ISomeInjectedService someInjectedService)
    {
        _someInjectedService=someInjectedService;
    }
    // Some other private methods


    
    public Task DoSomething(SomeData someDate)
    {
    }
    // Some other public methods that are exposed in IFoo interface
}

The important point is, this new base class will never have another child. The question is: Is inheritance usage, justified here?

4
  • 2
    Does this answer your question? Why should I prefer composition over inheritance? – gnat Feb 6 at 8:35
  • 1
    It's not an absolute composition over inheritance. Because the base class has injected all services and made the data ready. The child class just implemented the exposing interface. If what I said, is still an example of composition over inheritance, then yes, this answers my question. If not, a more specific answer is welcomed. @gnat – FarhadGh Feb 6 at 8:43
  • 1
    You don't really show why Foo needs to inherit Bar, or even why it needs to know anything about Bar. I agree with gnat, that there should be a thought about why inheritance is needed. and whether composition can be used instead. – njzk2 Feb 6 at 23:08
  • 1
    Sorry but if you take the question title out of context... I just can't get over how weird it sounds. – candied_orange Feb 7 at 9:48
10

Splitting a big class into smaller classes is primarily about separation of concerns. When the independent concerns (some prefer to reflect in terms of “reason to change”) are well identified then only can you reasonably decide about inheritance vs. composition.

The core question is: didn’t we accidentally during the growth period put together too many independent things? and how can we make them independent again? Your question does not allow us to provide advice on this aspect.

But in any case, you should make Foo a subclass of Bar only if the concept of Foo is a specialization of Bar. If you cannot think of other specializations ever, even in other projects, then there are big chances that you are going to misuse inheritance. It may solve some issue on the short term, but sooner or later it will backfire (probably by hiding better ways to refactor).

8

Inheritance can be used as a tool to refactor out a new, smaller base class Bar from Foo, which can be tested, managed or used independently from its derivation. Moreover, it is a tool which allows to write more generalized code in terms of Bar, which is especially useful when there is more than one derived class (but which seems not to applicable to your situation).

Unfortunately, the goal mentioned in the title of the question, to make the child class Foo smaller, is not really reached by inheritance. Sure, the code in the class file gets smaller, but when it comes to debugging and testing Foo, inheritance does not make a good job of reducing the amount of code which has to be taken into account:

  • Foo still cannot be tested in isolation from the code which lives in Bar

  • When a method call to Foo shows up a bug, almost the same amount of code has to be analysed for finding the root cause (to be fair, there may be cases where you can write tests for Bar which excludes certain root causes for a bug in Foo).

Hence before using inheritance, one should definitely check if the goal of making the original class "smaller" is not better reached by using composition instead of inheritance. For example, this would allow Bar to be replaced by some MockBar for the purpose of testing Foo. The drawback is, it might require more refactoring effort, and more delegational code than inheritance. Another option might be not to refactor now, since the effort of introducing inheritance and the additional overhead in code might currently not be balanced by the questionable benefit of having two smaller code files of strongly coupled code instead of one.

So each of the possible choices has advantages and drawbacks - I hope my remarks above can help you to compare them against each other a little bit better.

-1

Subclassing in this case is kind of cheating. If there is functionality that you can extract into a separate useful class, that might be a better choice.

2
  • while I agree on principle, I think it coule be more useful to detail what you mean by "cheating" (I assume you mean something like hiding complexity by reducing the number of lines of code one sees in Foo, while actually leaving the exact same complexity in the class, and therefore in testing, debugging, and so on) – njzk2 Feb 6 at 23:11
  • 2
    This is a poor answer as you've not explained why you are correct. You very well could be correct, but all this answer is is dogma. – user368564 Feb 7 at 1:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.