As we know Software is a collection of instructions that tell a computer how to work. If the software works as expected, that doesn’t necessarily mean that it has a good design. As there is no precise answer of what good design reflects in software development, there are specific criteria that help identify a bad design.
Signs of Bad Design
- Rigidity: When you want to introduce a new feature, the code you write code has effects on other parts of code which results in maintaining it to work with new changes. It is called cascading code changes.
- Fragility: This is the sign of bad design in which fixing one problem leads to the rising of new bugs.
- Immobility: This design depicts the lack of code reusing due to tight coupling among components.
SOLID is an acronym for five fundamental object-oriented design principles that try to address these traits and they are:
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
These principles were founded by Robert C. Martin in the year 2000 in his paper Design Principles and Design Patterns. He is an American software engineer, instructor, and best-selling author also known by another name called “Uncle Bob”.
By adopting the SOLID design principles, we ensure that we build software systems that are understandable, maintainable, and flexible. These principles are applied to any object-oriented programming language.
SOLID Design Principles
Let’s discuss these concepts one by one.
Single Responsibility Principle(SRP)
SRP states that every module, class, or function should have responsibility over a single part of the functionality provided by the software and that responsibility should be entirely encapsulated by the module, class, or function. In other words, “A class should have only one reason to change.” GRASP(General Responsibility Assignment Software Principles) helps identify class responsibilities.
SRP makes code easier to understand, and helps in debugging and refactoring process. One change in the code doesn’t change the entire code structure.
OCP states that software entities(classes, modules, functions, etc.) should be open for extension, but closed for modification. Open to an extension means adding subclasses to the base class as needed. Closed to modification avoids “tweaking” the code to handle new situations.
OCP summarizes the goals of the other two principles of SOLID: The interface segregation principle(ISP) and the Liskov substitution principle(LSP).
ISP segregates the interfaces that keep a class closed to further modification.
LSP assures that subclasses are extensions of a superclass i.e creating classes that are open to extension.
Liskov Substitution Principle(LSP)
LSP states that functions that use pointers or references to base classes must be able to use objects of derived classes without altering any of the provable properties of that program, that is without breaking it.
This principle was initially introduced by Barbara Liskov in a 1988 conference keynote address titled Data Abstraction and Hierarchy. She originally called the idea Strong Behavioral Subtyping. The idea is that the behavior of a subclass should be as correct as of the behavior of the superclass.
LSP helps programmers design good polymorphism.
Interface Segregation Principle(ISP)
ISP states that no code should be forced to depend on methods it does not use. A code should depend on the smallest set of interface features i.e. the fewest methods and attributes.
A class needs to be designed so that collaborators have the narrowest interface. If the class has too many methods, the client code is then bound to methods it does not need.
ISP is the most useful principle that helps design good classes and write unit test cases. It also keeps the system decoupled that makes the refactoring, changing, and redeploying process easier.
Dependency Inversion Principle(DIP)
DIP states that:
- “High-level modules should not depend on low-level modules. Both should depend on abstractions.”
- “Abstractions should not depend on details. Details should depend on abstractions.”
DIP is the specific methodology for loosely coupling software modules. It is focused on packaging the code and direct dependency on a concrete class needs to be inverted.
That’s all the SOLID design principles we discuss in this tutorial. Overall these principles help build better software systems that are more flexible, robots, and reusable.
Summary of SOLID Principles
- The Single responsibility principle suggests making classes, functions responsibly for fulfilling one type of role.
- The Open/closed principle suggests adding new functionality to existing code without modifying existing code.
- The Liskov substitution principle suggests when a class inherits from another class, the program shouldn’t break and you shouldn’t need to hack anything to use the subclass.
- The Interface segregation principle suggests making interfaces more specific, rather than generic.
- The Dependency inversion principle suggests making classes depend on abstract classes rather than non-abstract classes.