Solid Principles Python
..
The SOLID principles can also be applied to Python to improve the design and maintainability of your code. Here's a breakdown of each principle with examples in Python:
1. Single Responsibility Principle (SRP)
Definition: A class should have only one reason to change, meaning it should have only one job or responsibility. Example in Python:
class
Book:
def
__init__(
self, title, author):
self.title = title
self.author = author
class
BookPrinter:
@staticmethod
def
print(
book):
print(
f"{book.title} by {book.author}")
book = Book(
"1984",
"George Orwell")
BookPrinter.
print(book)
In this example, the Book
class is responsible for storing book data, while the BookPrinter
class handles printing the book details, adhering to SRP.
2. Open/Closed Principle (OCP)
Definition: Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. Example in Python:
from abc
import ABC, abstractmethod
class
Shape(
ABC):
@abstractmethod
def
draw(
self):
pass
class
Circle(
Shape):
def
draw(
self):
print(
"Drawing a Circle")
class
Square(
Shape):
def
draw(
self):
print(
"Drawing a Square")
def
draw_shape(
shape):
shape.draw()
circle = Circle()
square = Square()
draw_shape(circle)
draw_shape(square)
In this example, new shapes can be added by extending the Shape
class without modifying the existing code.
3. Liskov Substitution Principle (LSP)
Definition: Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. Example in Python:
class
Bird:
def
fly(
self):
print(
"Flying")
class
Sparrow(
Bird):
pass
class
Ostrich(
Bird):
def
fly(
self):
raise NotImplementedError(
"Ostriches can't fly")
def
make_bird_fly(
bird):
bird.fly()
sparrow = Sparrow()
ostrich = Ostrich()
make_bird_fly(sparrow)
# Works fine
make_bird_fly(ostrich)
# Raises error, violates LSP
To adhere to LSP, you might need to redesign the hierarchy:
class
Bird:
pass
class
FlyingBird(
Bird):
def
fly(
self):
print(
"Flying")
class
Sparrow(
FlyingBird):
pass
class
Ostrich(
Bird):
pass
def
make_bird_fly(
bird):
if
isinstance(bird, FlyingBird):
bird.fly()
sparrow = Sparrow()
ostrich = Ostrich()
make_bird_fly(sparrow)
# Works fine
make_bird_fly(ostrich)
# Does nothing, adheres to LSP
4. Interface Segregation Principle (ISP)
Definition: Clients should not be forced to depend on interfaces they do not use. Example in Python:
class
Worker:
def
work(
self):
pass
def
eat(
self):
pass
class
HumanWorker(
Worker):
def
work(
self):
print(
"Working")
def
eat(
self):
print(
"Eating")
class
Robot(
Worker):
def
work(
self):
print(
"Working")
def
eat(
self):
raise NotImplementedError(
"Robots do not eat")
# Violates ISP
To adhere to ISP:
class
Workable:
def
work(
self):
pass
class
Eatable:
def
eat(
self):
pass
class
HumanWorker(Workable, Eatable):
def
work(
self):
print(
"Working")
def
eat(
self):
print(
"Eating")
class
Robot(
Workable):
def
work(
self):
print(
"Working")
5. Dependency Inversion Principle (DIP)
Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces). Abstractions should not depend on details. Details should depend on abstractions. Example in Python:
class
Light:
def
turn_on(
self):
print(
"Light is on")
def
turn_off(
self):
print(
"Light is off")
class
Switch:
def
__init__(
self, light):
self.light = light
def
operate(
self):
self.light.turn_on()
To adhere to DIP:
class
Switchable:
def
turn_on(
self):
pass
def
turn_off(
self):
pass
class
Light(
Switchable):
def
turn_on(
self):
print(
"Light is on")
def
turn_off(
self):
print(
"Light is off")
class
Switch:
def
__init__(
self, device: Switchable):
self.device = device
def
operate(
self):
self.device.turn_on()
By applying these principles in Python, you can create a system that is easier to maintain and extend, leading to better code quality and more robust applications.
Leave a comment