G2Labs Grzegorz Grzęda
Applying SOLID principles in your everyday coding
March 29, 2023
Applying SOLID Principles in Your Everyday Coding
As a software developer, you are constantly faced with the challenge of writing maintainable, scalable, and efficient code. The SOLID principles, coined by Robert C. Martin, offer a set of guidelines to achieve these goals. In this blog post, we will explore how you can apply these principles in your everyday coding, with extensive examples in C and Python.
What are the SOLID principles?
The SOLID principles are a set of five design principles that help developers create software that is easy to understand, maintain, and extend. The acronym SOLID stands for:
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
Let’s delve into each of these principles and understand how they can be applied in code.
1. Single Responsibility Principle (SRP)
The Single Responsibility Principle states that a class should have only one reason to change. In other words, a class should only have one job or responsibility. Let’s consider a simple example in C:
This function violates SRP as it is responsible for both calculating the area and perimeter as well as printing the result. We can refactor it to adhere to SRP:
|
|
2. Open/Closed Principle (OCP)
The Open/Closed Principle states that a class should be open for extension but closed for modification. In other words, you should be able to extend the behavior of a class without modifying its source code. Let’s consider a Python example:
In the above example, if we want to add a new shape (e.g., Triangle), we would have to modify the Shape
class violating OCP. We can refactor it to adhere to OCP using Python’s abstract base classes (abc
module):
By using abstract base classes, we ensure that the Shape
class is closed for modification but open for extension.
3. Liskov Substitution Principle (LSP)
The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of its subclass without affecting the correctness of the program. Let’s consider an example in C:
|
|
In the above example, if we introduce a Square
subclass of Rectangle
and pass it to calculateArea
, it would violate LSP as a square is not substitutable for a rectangle. We can refactor it to adhere to LSP:
|
|
By treating Rectangle
and Square
as variants of a more general Shape
, we adhere to LSP.
4. Interface Segregation Principle (ISP)
The Interface Segregation Principle states that a client should not be forced to depend on methods it does not use. Let’s consider a Python example:
In the above example, a client using Printer
is forced to depend on the fax
method, violating ISP. We can refactor it to adhere to ISP:
By splitting the interface into separate, smaller interfaces, we adhere to ISP.
5. Dependency Inversion Principle (DIP)
The Dependency Inversion Principle states that high-level modules should not depend on low-level modules. Both should depend on abstractions. Let’s consider an example in Python:
In the above example, a high-level module directly depends on low-level modules violating DIP. We can refactor it to adhere to DIP using dependency injection:
|
|
By injecting the Connection
dependency into the DatabaseClient
, we adhere to DIP.
Conclusion
In this blog post, we have explored how the SOLID principles can be applied in everyday coding scenarios using extensive examples in C and Python. By following these principles, you can write code that is more maintainable, scalable, and efficient, leading to better software design and development. Remember, while these examples are in C and Python, the concepts of SOLID principles are applicable across various programming languages and paradigms.
Happy coding!