Кто сформулировал принципы SOLID?

Ответ

Принципы SOLID были сформулированы и популяризированы американским инженером-программистом Робертом Мартином (широко известным как Uncle Bob).

Изначально он представил их в своей статье "Design Principles and Design Patterns" в 2000 году, а позже подробно описал в книге "Agile Software Development, Principles, Patterns, and Practices" (2002). Акроним SOLID был предложен позже Майклом Фезерсом.

Эти пять принципов объектно-ориентированного проектирования направлены на создание более понятных, гибких и поддерживаемых программных систем.

Расшифровка акронима SOLID:

  • S - Single Responsibility Principle (Принцип единственной ответственности): Класс должен иметь только одну причину для изменения.
  • O - Open/Closed Principle (Принцип открытости/закрытости): Программные сущности должны быть открыты для расширения, но закрыты для модификации.
  • L - Liskov Substitution Principle (Принцип подстановки Барбары Лисков): Объекты в программе должны быть заменяемы на экземпляры их подтипов без изменения правильности выполнения программы.
  • I - Interface Segregation Principle (Принцип разделения интерфейса): Клиенты не должны быть вынуждены зависеть от методов, которые они не используют.
  • D - Dependency Inversion Principle (Принцип инверсии зависимостей): Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба должны зависеть от абстракций.

Пример на Python (Single Responsibility Principle):

# Неправильно: класс делает две вещи - хранит данные и работает с БД
class BadUser:
    def __init__(self, name: str):
        self.name = name

    def save_to_db(self):
        print(f"Saving {self.name} to the database...")

# Правильно: обязанности разделены
class User:
    """Отвечает только за данные пользователя."""
    def __init__(self, name: str):
        self.name = name

class UserRepository:
    """Отвечает только за сохранение пользователя."""
    def save(self, user: User):
        print(f"Saving {user.name} to the database...")

# Использование
user = User("Alice")
repo = UserRepository()
repo.save(user)

Такое разделение упрощает тестирование, переиспользование и поддержку кода.

Ответ 18+ 🔞

А, ну вот, блядь, опять эти ваши SOLID-принципы! Слышал, да? Все как попугаи повторяют: "SOLID, SOLID, надо писать по SOLID". А кто их, сука, придумал-то, этот самый акроним? Думаешь, какой-нибудь древний мудрец с бородой по пояс? Хуй там!

Это всё один мужик, Роберт Мартин, он же Дядя Боб, ёпта! В 2000-м году, блядь, сел и написал статью, а потом ещё и книжку в 2002-м впердолил. А само слово SOLID, эту пиздатую аббревиатуру, уже потом другой чувак, Майкл Фезерс, подкинул. Вот так вот, на хуй, всё и начиналось. Просто один умный дядька решил, что писать код как попало — это пиздец, и сформулировал пять правил, чтобы мозги не вытекали при поддержке.

А правила-то, блядь, какие? Расшифровываю для распиздяев:

  • S (Single Responsibility) — Принцип единственной ответственности. Это значит, что твой класс должен делать что-то одно, блядь. Не пытайся впихнуть в него всё, от расчёта зарплаты до отправки смс бабушке. Одна причина для изменений — и всё, пиздец! Иначе он превращается в этого самого муда с ушами, которого потом ни починить, ни понять.
  • O (Open/Closed) — Принцип открытости/закрытости. Сущность должна быть открыта для расширения, но закрыта для модификации. То есть, ты должен иметь возможность добавить новую фичу, не перелопачивая старый, отлаженный код. А то начнёшь ковыряться — и накроется медным тазом вся система.
  • L (Liskov Substitution) — Принцип подстановки Лисков. Если у тебя есть класс-родитель и класс-ребёнок, то везде, где работает родитель, должен спокойно работать и ребёнок. Иначе это не ребёнок, а какой-то полупидор кривой, который всё ломает. Подставил — и программа не должна охуеть от этого.
  • I (Interface Segregation) — Принцип разделения интерфейса. Не заставляй клиента зависеть от того, что ему не нужно! Сделай интерфейсы маленькими и целевыми. А то получается один жирный интерфейс, от которого все зависят, а используют по кусочку. Пиздопроебибна, а не архитектура.
  • D (Dependency Inversion) — Принцип инверсии зависимостей. Модули верхнего уровня не должны пялиться на модули нижнего. Оба должны смотреть на абстракции. То есть, зависеть от договорённостей (интерфейсов), а не от конкретной реализации. Иначе связанность будет такая, что терпения ноль ебать.

Вот смотри, на примере первого принципа (S), как бывает:

# Вот это — пиздец, а не класс. Он и данные хранит, и в базу лезет. Две работы на одного.
class BadUser:
    def __init__(self, name: str):
        self.name = name

    def save_to_db(self):
        print(f"Saving {self.name} to the database...")

# А вот так — уже красота, блядь. Разделили ответственность.
class User:
    """Этот чувак отвечает ТОЛЬКО за данные пользователя. Ничего больше."""
    def __init__(self, name: str):
        self.name = name

class UserRepository:
    """А этот гад — ТОЛЬКО за то, чтобы тыкать данные в базу."""
    def save(self, user: User):
        print(f"Saving {user.name} to the database...")

# Используем
user = User("Алиса")  # Создали сущность
repo = UserRepository() # Создали инструмент для сохранения
repo.save(user) # Сохранили

Видишь разницу? В первом случае, если поменяется логика базы, придётся лезть в класс пользователя. А это чих-пых тебя в сраку, потому что ты можешь случайно сломать что-то ещё. А во втором — всё изолированно. Тестировать легко, менять — просто. Вот для этого всё и затевалось, понимаешь? Чтобы не было волнения ебать каждый раз, когда нужно что-то поменять.