SOLID#
SOLID - мнемоническая аббревиатура, состоящая из пяти принципов, призванных сделать исходный код более понятным, гибким и поддерживаемым.
Принципы SOLID#
S Single Responsibility Principle [SRP] — принцип единственной ответственности.
O Open Closed Principle [OCP] — принцип открытости-закрытости.
L Liskov Substitution Principle [LSP] — принцип подстановки Барбары Лисков (Заменяемость объектов на экземпляры).
I Interface Segregation Principle [ISP] — принцип разделения интерфейса.
D Dependency Inversion Principle [DIP] — принцип инверсии зависимостей.

S, Принцип единственной отвественности [SRP]#
Single Responsibility Principle - Каждый класс должен отвечать только за одну зону ответственности (действий), чтобы его было проще дополнять и менять. Изменение должно минимально затрагивать код. Надо разделять функциональность большого класса на более мелкие части, отвечающие за конкретные задачи.
class Movement:
def move(self):
pass
class Speaker:
def speak(self):
pass
class Robot:
def __init__(self):
self._movement = Movement()
self._speaker = Speaker()
def move(self):
self._movement.move()
def speak(self):
self._speaker.speak()
O, Принцип Открытости-Закрытости [OCP]#
Open Closed Principle - Класс должен быть закрыт для изменения, но открыт для расширения. Пишем код так, чтобы другие могли легко расширить функционал, не меняя написанный (оттестированный, понравившийся твоему начальнику) код.
class Character(ABC):
@abstractmethod
def display_info(self):
pass
class Knight(Character):
def display_info(self):
print("Я Рыцарь")
class Wizard(Character):
def display_info(self):
print("Я Маг")
if __name__ == "__main__":
character = Knight()
character.display_info() # Я Рыцарь
character = Wizard()
character.display_info() # Я Маг
L, Принцип подстановки Барбары Лисков [LSP]#
Liskov Substitution Principle - Если в коде программы Базовый класс заменить на его Наследника, то программа должна работать, так как в Наследнике есть все операции, которые были в Базовом. В Базовый класс нужно выносить только общую логику, которую наследники будут реализовывать. Наследников создаем только тогда, когда они правильно реализуют логику Базового класса.
class Bird(ABC):
@abstractmethod
def move(self):
pass
class FlyingBird(Bird):
def move(self):
self.fly()
def fly(self):
print("Летаю!")
class Sparrow(FlyingBird):
def fly(self):
print("Воробей летит")
class Penguin(Bird):
def move(self):
self.swim()
def swim(self):
print("Пингвин плывёт")
def make_bird_move(bird: Bird):
bird.move()
I, Принцип Разделения Интерфейса [ISP]#
Interface Segregation Principle - Клиенты не должны зависеть от интерфейсов, которые они не используют. Большие интерфейсы следует разбивать на интерфейсы поменьше. Так клиенты смогут использовать только те интерфейсы, которые им нужны. Это делает менее связанный код, уменьшает зависимости между элементами системы, упрощает изменения в коде.
class Movable(ABC):
@abstractmethod
def move(self):
pass
class Speakable(ABC):
@abstractmethod
def speak(self):
pass
class Flyable(ABC):
@abstractmethod
def fly(self):
pass
class Robot(Movable, Speakable):
def move(self):
pass
def speak(self):
pass
class Drone(Flyable):
def fly(self):
pass
D, Принцип Инверсии Зависимостей [DIP]#
Dependency Inversion Principle - Зависьте от интерфейсов, а не от конкретных классов. Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций. Интерфейсы не должны зависеть от реализации, а вот реализация должна зависеть от интерфейсов.
class User:
pass
class IDatabase(ABC):
@abstractmethod
def save_data(self, user: User):
pass
class Database(IDatabase):
def save_data(self, user: User):
# Сохранение данных в БД
pass
class UserService:
def __init__(self, database: IDatabase):
self._database = database
def add_user(self, user: User):
self._database.save_data(user)
pass
Источники#
Подробнее на: Одноглазый змей - SOLID