Inheritance & The Dependency Inversion Principle
Inheritance & The Dependency Inversion Principle
At its heart, the Dependency Inversion Principle (DIP) is about separating stable and unstable code.
In statically-typed languages like Java and C#, OO Inheritance creates a rigid relationship between classes. When it comes to inheritance, the DIP has a couple of extra recommendations:
Don’t derive from frequently changing concrete classes.
Parent class volatility will also plague child classes. Every time the parent changes, child classes need to be recompiled. Unless explicitly overridden, a change in parent behaviour flows through to the child. That might be what we want; however, at times, we need to preserve the operation of some children. The opposite is also true—overridden concrete methods block the modified base class behaviour even though we now want it to percolate through subclasses. An appropriate segway to the next DIP recommendation:
Don’t override concrete methods.
Overriding concrete methods can prove problematic. As mentioned in the previous point, base class modifications may or may not flow through to child class methods. Furthermore, source code dependencies in a base class method do not disappear when overridden in a subclass. Any such dependencies are retained even when not needed.
Let me illustrate with an example.
Say, we have a BasePaymentGateway
parent class representing a PayPal default payment gateway implementation. BasePaymentGateway
depends on the PayPal SDK. A child class, StripePaymentGateway
, overrides the virtual Pay() method on BasePaymentGateway
. Unfortunately, StripePaymentGateway
retains the original dependency on the PayPal SDK, which it does not need!
A more flexible approach is to keep overridable methods abstract and provide different child implementations: PaypalPaymentGateway
, StripePaymentGateway
, and so on.
We probably would have been better off using an IPaymentGateway
interface rather than a base class. Even a pure abstract base class with only abstract public methods is not as stable as an interface. Why? Because such a base class would still contain shared behaviour in protected methods available to all the children.
Avoid deriving from volatile classes and overriding concrete methods.
Please be cautious when using inheritance. You may inadvertently violate the Dependency Inversion Principle.
Leave a Reply
Want to join the discussion?Feel free to contribute!