Solid Dry Kiss Yagni
Get latest articles directly in your inbox
Confused? Well, this is no where related to actual real life kiss 😂
“Solid, DRY, KISS. YAGNI” are few of the software engineering principles we will be discussing today.
Preparing for Interviews? I highly recommend Mastering System Design course on Educative.
Why should I learn these?
These principles are set of guidelines which help you write better, robust and clean code. Once, you start applying them, you’ll start seeing the results on the overall process of developing products. Here are some advantages which will be visible in your code -
- Robustness
- Efficiency
- Clean Code
- Delivering high quality softwares
- Flexible, Easy to refactor
Writing code is easy but writing good and quality code is hard
In this post, I’ll be introducing a few I have learnt in my past year of professional software development career.
Principles
- KISS
- DRY
- YAGNI
- SOLID
- Tell, Don’t Ask!
Simplicity is prerequisite for reliability. — Edsger Dijkstra
KISS
KISS is an acronym for “Keep It Simple Stupid” This principle literally means to keep your code as simple code as possible.
You might think - “But, I always keep it simple only !?”
Well, that is not the case with a lot of engineers. You start with something basic but soon add unwanted complexity as the code grows.
Engineers like to complicate things!
The simpler the code, the easier it is to understand and maintain it.
A very basic example of this would be adding a complex sort function when simple library sort would cater your need! Don’t optimize unless there is an requirement.
Another common violation of KISS is using a new framework or adding a new npm module in your code which can be easily avoided. Eg. There is a npm package to convert string to camel case. Think, do you actually need this or a simple function would solve your task?
As soon as you add a new dependency, you are basically increasing the overall code complexity which will be problamatic in future.
Key to following this principle is learn to break your problem into as simple and small steps as possible, then write minimal code to implement them.
DRY
DRY stands for “Don’t Repeat Yourself”
This principle focuses on applying reusuability and reducing repitition in code. This implies you should not require a change in logically unrelated components on changing a certain single element.
When you reuse components you basically are reducing code to be written. Less code results in better maintainibility!
As an engineer, Automate and Reuse whenever you can!
Most common example of these are functions! A general rule is if you are writing same logic more than thrice, it’s time to refactor the logic to a function and reuse!
Database normalization is one of the methods to reduce redundancy of data by eliminating columns. This is an example of DRY!
YAGNI
YAGNI is an acronym for “You aren’t gonna need it”
This principle states that you should not optimize and increase complexity thinking about future.
Do what is required now. Don’t optimize prematurely!
Also, you don’t know what new cases may arise ahead! Why waste additional time and effort on something which is not actually required! Although, you should design your systems in a way that minimal changes are required for a future predictable change.
It syncs with KISS principle on avoiding any additional complexity.
A simple example would be not not use databases when simple file system can work!
SOLID
This principle in acronym of acronyms 😛
- SRP - Single Responsibility Principle
- OCP - Open Closed Principle
- LSP - Liskov Substitution Principle
- ISP - Interface Segregation Principle
- DIP - Dependency Inversion Principle
Single Responsibility
Definition from Wikipedia is quite clear -
Every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class
Each method or class should be bounded to some functionality. It should not do anything less or more. There should be only a single reason for it to change!
Example - Login
package should deal with the user login code, It should not deal with user signup.
func showPosts(listOfPost []string) {
sort.Strings(strs) // Basically any code dealing with sorting
for _, post := range listOfPost {
fmt.Println(post)
}
}
The above code violates SRP, because there are reasons to change showPosts()
if our sorting logic changes. Correct way would be to call sort function and then pass sorted list to this method.
func showPosts(listOfPost []string) {
for _, post := range listOfPost {
fmt.Println(post)
}
}
// In some other function
listOfPost := []string{ "post1", "post2"} // Some array list
// sort the list
sort.Strings(listofPost)
// show the list
showPosts(listofPost)
Now, the showPosts
only changes when we want to show additional info about post. (Single reason to change)
Open/Closed Principle
Once you have written a piece of code and then some new features comes, now you have to go back to old code and change it again! Open/Closed principle exactly deals with this!
Write code in a way so that your classes/methods are -
Open for extension, but closed for modification
Liskov Substitution Principle
LSP advocates that the objects of your subclass should behave in the same way as the objects of your superclass.
class Vehicle
{
double speed;
double getSpeed() { ... }
void setSpeed(double d) { ... }
Engine engine;
Engine getEngine() { ... }
void setEngine(Engine e) { ... }
void startEngine() { ... }
}
class Car extends Vehicle
{
@Override
void startEngine() {
// start the car engine
}
}
class Bicycle extends Vehicle
{
@Override
void startEngine() {
// throw error - Bicycle has no engine
}
}
In the above example Car
and Bicycle
both extend the Vehicle
class. This fails LSP because the Bicycle object cannot replace Vehicle since its startEngine()
will return an error!
Interface Segregation Principle
Clients should not be forced to depend upon interfaces that they do not use. - Robert C. Martin
This implies you should keep your interfaces as small as possible. Don’t pollute your interfaces with methods that are not required.
interface Animals {
public void eat();
public void fly();
public void swim();
}
class Dogs implements Animals {
public void fly() {
// Throws error - dogs cannot fly
}
public void swim() {
// Throws error - dogs cannot swim
}
public void eat() {
System.out.println("Dogs eat!");
}
}
In this case, our interface is polluted with methods like swim and fly which doesn’t apply to Dog
class. We can fix this by breaking our interace into multiple interfaces like AnimalsWhoSwim
and AnimalsWhoFly
. Animals interface can contain function eat()
Dependency Inversion Principle
DIP basically suggests that the high level modules should not depend on low level modules, rather both should depend on abstractions. It implies you should use interfaces instead of concrete implementations wherever possible.
There is a good example on this, will guide you there in case you want to understand it better.
Tell, Don’t Ask
Tell, don’t ask principle suggests to avoid asking object about their state, rather tell them what to do based on decision i.e tell the object what to do!
Example
// isLoggedIn returns true/false
if user.isLoggedIn() { // Asking whether user is logged in
user.showProfile()
} else {
user.showLoginScreen()
}
Here, we are asking whether the user is logged in or not, and then asking for profile. We wanted to get the profile, we just tell the object to show us thr profile, the login check should be internally implemented in showProfile()
itself. The correct way should be -
user.showProfile() // Tell!
Resources
- KISS principle at Apache
- Good read on Tell, Don’t Ask by Martin Fowler
- On ISP
- Read Pragmatic Programmer
Do try and follow the principles you read here because -
You cannot swim without getting wet ― Vusi JCK Maseko
Show other useful principles you follow in comments 👇
Liked the article? Consider supporting me ☕️
I hope you learned something new. Feel free to suggest improvements ✔️
I share regular updates and resources on Twitter. Let’s connect!
Keep exploring 🔎 Keep learning 🚀
Liked the content? Do support :)