Avoiding Dependencies Between Layers
As part of the S.O.L.I.D. design principles, the Dependency Inversion Principle (DIP) provides guidance for ensuring layers within the application avoid unnecessary dependencies from coupling. DIP ensures each layer’s modules remain independent of one another and should depend on abstractions instead of concrete details, increasing usability and flexibility to change.
In the following example, I demonstrate two classes for a workflow system where a process reacts to a team members, starting a workflow which sends a message.
You’ll notice the Workflow class via composition is tightly coupled to the Message class, representing a dependency and possible issue if that class is later change. Also, it increase difficulty when testing the Workflow class.
Instead of the Workflow class containing a Message object as a member, I’ll decouple a portion of the behavior to an interface, which the Message class will inherit.
Then, Workflow will be updated for its member points to an interface, which then is called by its Send() method, which it turn passes the call onto the interface, which is turn is handled by the Message class for implementation details.
To recap, my example began with a high-level module (Workflow) depending on a lower-level (Message) which limited its testability and flexibility to change.
I abstracted the dependency into an interface which the lower-level inherited, and the higher-level pointed to, removing the dependency.