Any developers can want to start building applications with good and concinnous designs using their knowledge and experience. But with time, the applications might develop bugs. An application design must be altered for every change request or new feature request. Through some time we might need to put in a lot of effort, even for simple tasks and it might require a full working knowledge of the entire system. Yet we can't blame change or new feature requests. Those are part of the software development. You cannot stop them and cannot even refuse them. So who is the culprit here? Of course, this is the design of the app.
The following are the design flaws that cause the damage in software, mostly.
- Taking more responsibility on them, putting more stress on the classes (A lot of functionality should not be related to a class.)
- Forcing the classes to depend on each other. If only classes are dependent on each other (in other words tightly coupled), then a change in one will affect the other.
- Into the spreading duplicate code in the system/application.
- Selecting the correct architecture (in other words MVC, 3-tier, Layered, MVP, MVVP and so on).
- Following Design Principles.
- Selecting correct Design Patterns to build the software based on it's specifications.
Now we go through the Design Principles first and will cover the rest soon.
Intro to SOLID principles
Whereas the SOLID principles are as design principles that enable us to manage with most of the software design problems. Sir Robert C. Martin compiled these principles in the 1990s. Those principles provide us ways to move from tightly coupled code and little encapsulation to the desired results of loosely coupled and encapsulated real needs of business properly. The SOLID is an acronym of the following.
- S: Single Responsibility Principle (SRP)
- O: Open Closed Principle (OSP)
- L: Liskov Substitution Principle (LSP)
- I: Interface Segregation Principle (ISP)
- D: Dependency Inversion Principle (DIP)
S: Single Responsibility Principle (SRP)
We can say according to SRP "Every software module should have only one reason to change". That means that every class, or similar structure, in your code should have only one job to do. Anything in that class should be related to a single purpose. Into your class should not be like a Swiss knife wherein if one of them needs to be changed then the entire tool needs to be altered. This does not mean that your classes should only contain one method or property. They may be many members as long as they relate to the single responsibility.
O: Open/Closed Principle
According to the open/closed Principle says "A software module/class is open for extension and closed for modification".
Where "For open extension" means, we need to design our class/module in such a way that the new functionality can be added only when new requirements are generated. And "The closed extension is used for modification" means you have already developed a class and it has gone through unit testing. You should then not alter it until we find bugs. As it has been said, one section should be open for the extension, we can use the legacy to do this.
L: Liskov Substitution Principle
The LSP(Liskov Substitution Principle) states that "you should be able to use any derived class instead of a parent class and have it behave in the same manner without modification". The ensures that a derived class does not affect the behavior of the parent class, in other words, that a derived class must be substitutable for its base class.
That principle is just an extension of the o/c (Open/Close) Principle and it means that we must ensure that new derived classes extend the base classes without changing their behavior.
I: Interface Segregation Principle (ISP)
Instead of a grease interface, several small interfaces are preferred on the basis of groups of methods, each serving a submodule."
D: Dependency Inversion Principle
The DIP (Dependency Inversion Principle) states that high-level classes/modules should not depend on low-level classes/modules. Each should depend upon abstractions. Other, abstractions should not depend upon details. Rather then details should depend upon abstractions.