Что такое принципы SOLID и для чего они применяются в ООП

Ответ

SOLID — это акроним для пяти основных принципов объектно-ориентированного проектирования, которые помогают создавать гибкие, масштабируемые и поддерживаемые программные системы.

Цель применения: Уменьшить зависимости между компонентами системы, чтобы изменения в одной части кода не приводили к непредсказуемым сбоям в другой.

Принципы SOLID:

  1. S - Single Responsibility Principle (Принцип единственной ответственности)

    • Суть: Класс должен иметь только одну причину для изменения. Он должен отвечать за одну конкретную задачу.
  2. O - Open/Closed Principle (Принцип открытости/закрытости)

    • Суть: Программные сущности (классы, модули) должны быть открыты для расширения, но закрыты для модификации. Новая функциональность добавляется путем создания нового кода, а не изменения старого.
  3. L - Liskov Substitution Principle (Принцип подстановки Барбары Лисков)

    • Суть: Объекты производных классов должны иметь возможность заменять объекты базовых классов без изменения корректности программы.
  4. I - Interface Segregation Principle (Принцип разделения интерфейса)

    • Суть: Лучше иметь много специализированных интерфейсов, чем один универсальный. Клиенты не должны зависеть от методов, которые они не используют.
  5. D - Dependency Inversion Principle (Принцип инверсии зависимостей)

    • Суть: Модули верхних уровней не должны зависеть от модулей нижних уровней. И те, и другие должны зависеть от абстракций. Абстракции не должны зависеть от деталей.

Пример на Python (Принцип единственной ответственности):

# ПЛОХО: Класс нарушает SRP, так как отвечает и за данные, и за их сохранение
class Report:
    def __init__(self, title, content):
        self.title = title
        self.content = content

    def save_to_file(self, filename):
        with open(filename, 'w') as f:
            f.write(f"{self.title}n{self.content}")

# ХОРОШО: Обязанности разделены
class Report:
    """Отвечает только за хранение данных отчета."""
    def __init__(self, title, content):
        self.title = title
        self.content = content

class ReportSaver:
    """Отвечает только за сохранение отчета."""
    def save_to_file(self, report, filename):
        with open(filename, 'w') as f:
            f.write(f"{report.title}n{report.content}")

Ответ 18+ 🔞

А, вот это, блядь, SOLID, ёпта! Ну, это как свод правил для программистов, чтобы они не писали код, который потом развалится от одного чиха, как карточный домик, блядь. Цель — чтобы одна часть системы не зависела от другой, как пьяный от забора. Чтобы ты поменял одну хуйню, а всё остальное не накрылось медным тазом.

Слушай, смотри, какие принципы, блядь:

  1. S — Single Responsibility (Принцип единственной ответственности). Суть проще некуда, ёпта: один класс — одна работа. Не надо делать из класса швейцарский нож, который и пишет, и читает, и чай заваривает. Он должен делать что-то одно, и всё. Как тот чувак, который только подметает, блядь.

  2. O — Open/Closed (Принцип открытости/закрытости). Вот это, блядь, хитрая жопа. Суть в том, что твой код должен быть как хороший конструктор: ты можешь добавлять новые детали (расширять), но не должен ломать старые (модифицировать). Новую фичу пишешь новым кодом, а не лезешь в старый, который уже работает, и не ебешь там мозг.

  3. L — Liskov Substitution (Принцип подстановки Лисков). Ну, тут, блядь, логика простая. Если у тебя есть класс «Птица», и от него наследуется «Пингвин», то ты должен быть уверен, что везде, где используется «Птица», можно воткнуть «Пингвина», и ничего не сломается. А если пингвин не летает и программа падает, значит, ты мудак и наследование сделал неправильно, блядь.

  4. I — Interface Segregation (Принцип разделения интерфейса). Представь, блядь, что тебе дали пульт от всего на свете: от телевизора, стиралки, микроволновки и ещё, хуй знает, от чего. Ты будешь в шоке, да? Вот и тут так же. Не надо делать один жирный интерфейс на все случаи жизни. Лучше много маленьких и понятных. Чтобы класс зависел только от того, что ему реально нужно, а не от всей этой ебанины.

  5. D — Dependency Inversion (Принцип инверсии зависимостей). Это, блядь, чтобы высокоуровневые модули (которые «рулят» логикой) не зависели напрямую от низкоуровневых (которые «копаются в грязи», типа работы с базой данных). И те, и другие должны зависеть от абстракций — интерфейсов, договоров. Абстракция — это как план, а детали — это уже реализация. Так система становится гибкой, ёпта.

Вот тебе пример на Python, чтобы понятно было, про этот первый принцип (единственной ответственности):

# ПЛОХО: Класс нарушает SRP, так как отвечает и за данные, и за их сохранение
class Report:
    def __init__(self, title, content):
        self.title = title
        self.content = content

    def save_to_file(self, filename):
        with open(filename, 'w') as f:
            f.write(f"{self.title}n{self.content}")

# ХОРОШО: Обязанности разделены
class Report:
    """Отвечает только за хранение данных отчета."""
    def __init__(self, title, content):
        self.title = title
        self.content = content

class ReportSaver:
    """Отвечает только за сохранение отчета."""
    def save_to_file(self, report, filename):
        with open(filename, 'w') as f:
            f.write(f"{report.title}n{report.content}")

Видишь разницу, блядь? В первом случае класс Report — это и данные, и сохранение. Он как Герасим, который и двор метёт, и Муму топит. А во втором — всё по полочкам: один класс только данные держит, другой — только сохраняет. Красота, ёпта! Если нужно будет сохранять не в файл, а, допустим, в облако, ты меняешь только ReportSaver, а сам отчёт даже не узнает об этом. Вот оно, счастье!