SOLID Principles

This is what ChatGPT provided.

SOLID Principles Examples

Single Responsibility Principle (SRP)

This principle states that a class should have only one reason to change. In other words, it should have only one responsibility.

class Employee:
    def __init__(self, name: str, salary: float):
        self.name = name
        self.salary = salary
    
    def get_name(self):
        return self.name
    
    def get_salary(self):
        return self.salary

class SalaryCalculator:
    def calculate_salary(self, employee: Employee):
        # Calculate salary based on employee's position, experience, etc.
        pass

In the above example, Employee class has only one responsibility - to store information about an employee. SalaryCalculator class has only one responsibility - to calculate the salary of an employee based on their information.

Open/Closed Principle (OCP)

This principle states that a class should be open for extension but closed for modification.

In the above example, Shape class is open for extension as we can add new shapes by creating new subclasses of Shape. However, Shape class is closed for modification as we don't need to modify the draw method when we add a new shape.

Liskov Substitution Principle (LSP)

This principle states that a subclass should be able to substitute its superclass without any problems.

In the above example, we can substitute Dog and Bird for Animal without any problems as they both have implemented the move method.

Interface Segregation Principle (ISP)

This principle states that a client should not be forced to implement methods which it does not use.

In the above example, Editor class uses only the open and save methods of Document class. PrintableEditor class uses only the print method of PrintableDocument class. Therefore, we can split Document and PrintableDocument into two separate interfaces - Openable and Printable, respectively.

Dependency Inversion Principle (DIP)

This principle states that high-level modules should not depend on low-level modules. Instead, both should depend on abstractions.

Dependency Injection Principle (DIP)

This principle is a natural consequence of the Dependency Inversion Principle (DIP). It says that dependencies should be injected into an object from the outside, rather than created inside the object.

In the above example, MyService depends on MyDependency, but it is not responsible for creating it. Instead, MyDependency is injected from the outside, which makes MyService more flexible and easier to test.

Composition Over Inheritance Principle

This principle states that you should prefer composition over inheritance. In other words, you should use object composition to achieve code reuse, rather than inheriting from a base class.

In the above example, Car uses composition to reuse the functionality of Engine, rather than inheriting from it.

Don't Repeat Yourself Principle (DRY)

This principle states that you should not repeat yourself. In other words, you should avoid duplicating code, and instead, use abstraction and modularization to keep your code clean and maintainable.

In the above example, do_something and do_something_else both call my_dependency.do_something_else. Instead of duplicating the code, we can call do_something_else from do_something.

Last updated

Was this helpful?