Search code examples
design-patternssolid-principles

Identifying violations of the SOLID design principles


I'm trying to understand SOLID design patterns and design principles. Imagine creating a notification program, with a parent class that has one method called send notifications. Now the parent class has subclasses for different notification types like SMS, Call, and email. After creating the program I would like to extend its functionality by allowing it to combine more than one notification type so I create a subclass called SMS+Email to handle notifications relating to SMS and email I also create another subclass that handles notifications that combine call and email.

I know a good design strategy here would be a decorator strategy, instead of having to create a whole new subclass each time I want to combine the notification I could just create a wrapper class that does that.

But I'm a having problem identifying any design problem. Each class does a specific function so it can't be a single responsibility principle when I want to add a new function I could easily create a subclass that way I'm not modifying the code just extending it so I don't feel like it's violating the open-closed principle. The only principles that come to mind are the dependency inversion principle and the Interface Segregation Principle but I'm not too sure of those.

I feel like it violates a design principle since it could be implemented using a design strategy but I'm not so sure.


Solution

  • Not every problem is a SOLID violation, and it's possible to do a really bad job within SOLID's boundaries. In particular, much of software design consists of determining just what all the "single responsibilities" should be.

    Document the purpose of each class and fix the ones the ones you don't like.

    Why would you want to have a separate "SMS+EMail" class to maintain when you already have an SMS class and and EMail class? When you see that you should be afraid that you'll have to make a class for every possible combination, and that choosing combinations by configuration instead of coding will be difficult.

    It sounds like a better solution for your particular problem is to create a CompositeNotifier class. It would have a list of other notifiers and would distribute notifications to all of them. This is a SOLID solution:

    • S: Distributes notifications to multiple targets
    • O: Any types of target notifiers can be added to each instance after/during construction.
    • L: It adheres to the contract of the Notifier interface it implements
    • I: I presume your parent Notifier interface doesn't include any unrelated stuff
    • D: It depends only on the Notifier abstraction for targets. Specific types of targets are injected. (Dependency inversion is often the way to implement the Open/Closed principal).