SOLID Principles#
Принципы SOLID - это набор руководящих принципов, разработанных Робертом Мартином, которые способствуют созданию гибкого, расширяемого и поддерживаемого программного кода. Эти принципы призваны улучшить структуру кода, сделать его более устойчивым к изменениям и обеспечить эффективное взаимодействие между различными компонентами системы.
Принципы SOLID составляют аббревиатуру, в которой каждая буква соответствует определенному принципу.
S - Single Responsibility Principle#
Каждый класс должен иметь только одну причину для изменения. Это означает, что класс должен быть ответственным только за одну функциональность.
class FileManager:
def read_file(self, file_path):
# Чтение файла
def write_file(self, file_path, content):
# Запись в файл
class EmailSender:
def send_email(self, to, subject, message):
# Отправка email
В данном случае классы FileManager и EmailSender имеют разные обязанности и могут меняться по разным причинам.
O - Open/Closed Principle#
Программные сущности (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации. Вместо изменения существующего кода, следует создавать новый код для добавления новой функциональности.
class Shape:
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
Здесь класс Shape оставлен открытым для расширения путем создания новых классов Circle и Square, но сам Shape не изменяется.
L - Liskov Substitution Principle#
Объекты базового класса должны быть заменяемы объектами его производных классов без изменения желаемых свойств программы.
class Bird:
def fly(self):
pass
class Sparrow(Bird):
def fly(self):
# Реализация полета для воробья
class Ostrich(Bird):
def fly(self):
raise Exception("Страус не умеет летать")
def make_bird_fly(bird):
bird.fly()
sparrow = Sparrow()
ostrich = Ostrich()
make_bird_fly(sparrow) # Работает
make_bird_fly(ostrich) # Вызовет исключение, нарушение LSP
I - Interface Segregation Principle#
Клиенты не должны зависеть от интерфейсов, которые они не используют. Лучше создавать несколько узких интерфейсов, чем один общий.
class Worker:
def work(self):
pass
class Manager:
def manage(self):
pass
class SuperWorker(Worker, Manager):
def work(self):
# Реализация работы
def manage(self):
# Реализация управления
class RegularWorker(Worker):
def work(self):
# Реализация работы
В данном примере SuperWorker нарушает принцип, так как он зависит от обоих интерфейсов, а RegularWorker следует принципу, завися только от необходимого интерфейса.
D - Dependency Inversion Principle#
Зависимости должны строиться на абстракциях, а не на конкретных реализациях. Модули верхнего уровня не должны зависеть от модулей нижнего уровня, оба должны зависеть от абстракций.
class LightBulb:
def turn_on(self):
pass
def turn_off(self):
pass
class Switch:
def __init__(self, bulb):
self.bulb = bulb
def operate(self):
if self.is_on:
self.bulb.turn_off()
else:
self.bulb.turn_on()
В данном примере класс Switch зависит от абстракции bulb, что позволяет легко заменять тип лампы без изменения класса Switch.