Software Engineering is a complex process, the results of which depend on several variables that are not always determined by the engineer working on that specific project. This is a set of guidelines that helps engineers to make a good system design. The key software design principles are as follows:
KISS (Keep it simple stupid)
This should be every engineer's ultimate motto because they tend to build complex systems which cause problems when it comes to their debugging and maintenance. Simplicity is the way to go whether it is applied to your code or problem-solving process.
Example - when creating an API we start with the CRUD functionality then build upon it as it grows.
DRY (Don't Repeat Yourself)
An effective engineer knows that code can be highly re-usable and that is a good thing, but that doesn't mean that this piece of code should be repeated in various places within a program. Instead of repeating yourself and your code see if there is a way to combine all snippets into a single task thus minimizing the time of effort you will spend if it is necessary to make corrections in the future.
Example – MVC framework works on this principle.
YAGNI(You aren't Gonna Need it)
A frequent temptation for engineers is the urge to take any future eventuality into account and proceed to write code that will solve said eventualities. However, hands-on experience has proven that this proactive way of working is a waste of effort, so focus on building the code that you need at the moment.
S.O.L.I.D
This is an acronym that contains five design principles of object-orientated programming.
S - Single Responsibility Principle(SRP)
This principle states that there should never be more than one reason for a class to change. This means that you should design your classes in such a way that each class should have a single purpose.
O - Open/Closed Principle(OCP)
Software entities should be open for extensions but closed for modification. The "closed" part of the rule states that once a module has been developed and tested, the code should only be changed to correct bugs. The "open" part says that you should be able to extend existing code in order to introduce new functionality.
L - Liskov Substitution Principle(LSP)
Objects in a program should be replaceable with instances of their subtypes without altering the correctness of the program.
Example - Assume that you have an inheritance hierarchy with User and Customer. Wherever you can use User, you should also be able to use a Customer, because Customer is a subclass of User.
I - Interface Segregation Principle (ISP)
Many client-specific interfaces are better than one general-purpose interface. This means the number of members in the interface that is visible to the dependent class should be minimized.
Example - The service interface that is exposed to the client should contain only client related methods not all.
D - Dependency Inversion Principle (DIP)
The Dependency Inversion Principle states that:
High-level modules should not depend upon low-level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
It helps us to develop loosely coupled code by ensuring that high-level modules depend on abstractions rather than concrete implementations of lower-level modules. The Dependency Injection pattern is an implementation of this principle
Example - The Dependency Injection pattern is an implementation of this principle