Programming principles (KISS, YAGNI, DRY). SOLID
SOLID stands for:
S - Single-responsibility Principle
O - Open-closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D - Dependency Inversion Principle
Single-responsibility Principle (SRP): a class should have one and only one reason to change, meaning that a class should have only one job.
Example: (Container/presentational components in React)
Open-closed Principle (S.R.P.): objects or entities should be open for extension but closed for modification.
You should strive to write code that doesn’t have to be changed every time the requirements change.
Example: (don't hardcode something in React components, just let it be configured by props), (use the composition of small components instead of monolith JSX).
Liskov Substitution Principle: every subclass or derived class should be substitutable for their base or parent class.
The Liskov Substitution Principle means that you can inherit from a base class as long as you conform to the standards that it sets, such as having the same method name and parameters, you do not specify any deeper conditions that must be fulfilled, you return the same type that the base method does and that any Exception that is thrown must match the ones thrown by the base method.
Using TypeScript, we can easily swap objects and functions that share the same contract, without breaking the functionality of the application.
Example: (let's say we have a set of Error classes inherited from the base Error class, and we have a logger that log these errors, to follow this principle we should have the same interface for all the Errors to give the ability to the logger log any types of errors).
Interface segregation principle: a client should never be forced to implement an interface that it doesn’t use, or clients shouldn’t be forced to depend on methods they do not use.
This means that the methods of a large interface can be broken up into groups of methods. If a client does not need a method then the client should not know about the method / should not have to implement it.
Example: (Pass to the child component only the props required in this component instead of passing a full object from the upper level)
Dependency inversion principle: entities must depend on abstractions, not on concretions. It states that the high-level module must not depend on the low-level module, but they should depend on abstractions.
Example: (Container component has fetching logic and depend on 'fetch' function, we should invert dependencies to follow this principle, move fetch logic to the separate service and pass this service as a prop to the container, so that our container become independent on concrete implementation of 'fetch')
DRY Principle
DRY stands for Don’t Repeat Yourself.
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
This means that you should not have duplicated code. It’s easier to maintain a code that is only in one place because if you need to change something in the code, you just need to change in one place. Besides that, if you have the same code in two or more places, the chance of this code become different during the time is high, and when this happens it will become an easy way to introduce bugs in your system. Duplicated code also makes the code more complex and unnecessarily larger.
You also should not write ambiguous code. Your classes, your variables, your functions, they should have a specific name, and their name must match their responsibility. If you have a function, you should know what the function does by just reading its name, without being needed to read the code inside of it.
DRY is also about having different code that does the same thing. Maybe you can have different code in two or more places, but they do the same thing in different ways, this also should be avoided.
But DRY principle is not a dogma. Sometimes is better to consider AHA principle.
KISS Principle
KISS is an acronym for Keep It Simple, Stupid. This principle says about to make your code simple. You should avoid unnecessary complexity. A simple code it’s easier to maintain and easier to understand.
You can apply this principle in the design and in the implementation of the code. You should eliminate duplicated code, should remove unnecessary features, don’t use unnecessary variables and methods, use names for variables and methods that makes sense and matches their responsibilities, and always when it’s possible, follow know standards of code development. You also should separate the responsibilities of your classes and the responsibilities from the layers of the project.
Sometimes you don’t need to implement something new to attend your needs, you can simply make use of the features of the programming language that you are using. For that, it’s good that you know the features of the programming language that you are working with.
If you are working in a code that it’s already implemented, and you see something that it’s not necessary or could be simpler, you should consider refactoring it.
YAGNI Principle
YAGNI stands for You Ain’t Gonna Need It. It’s a principle from software development methodology of Extreme Programming (XP). This principle says that you should not create features that it’s not really necessary.
This principle it’s similar to the KISS principle, once that both of them aim for a simpler solution. The difference between them it’s that YAGNI focus on removing unnecessary functionality and logic, and KISS focus on the complexity.
Ron Jeffries, one of the co-founders of the XP, once said:
Always implement things when you actually need them, never when you just foresee that you need them.
It means that you should not implement functionality just because you think that you may need it someday, but implement it just when you really need it. Doing that you will avoid spending time with implementations that were not even necessary, and maybe will never be used.
Last updated