Ответ
SOLID — это пять ключевых принципов объектно-ориентированного проектирования, направленных на создание понятного, гибкого и поддерживаемого кода.
Принципы:
-
Принцип единственной ответственности (Single Responsibility Principle, SRP): Класс должен иметь одну и только одну причину для изменения. Это означает, что он должен решать одну конкретную задачу.
- Проблема: Класс
Report, который и вычисляет данные, и сохраняет их в файл. - Решение: Разделить на
ReportCalculatorиReportSaver.
- Проблема: Класс
-
Принцип открытости/закрытости (Open/Closed Principle, OCP): Классы должны быть открыты для расширения (через наследование, композицию) и закрыты для модификации. Новый функционал добавляется новыми классами, а не изменением существующих.
- Пример: Вместо добавления
if-elseв методcalculateDiscount()для каждого типа клиента, создать абстрактный классDiscountStrategyи конкретные реализацииRegularDiscount,PremiumDiscount.
- Пример: Вместо добавления
-
Принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP): Объекты базового класса должны быть заменяемы объектами его подклассов без нарушения корректности программы. Наследник не должен ужесточать предусловия или ослаблять постусловия родителя.
- Нарушение: Класс
Square, наследующий отRectangle. Если уRectangleесть сеттерыsetWidth()иsetHeight(), то дляSquareони нарушают инвариант (ширина всегда равна высоте).
- Нарушение: Класс
-
Принцип разделения интерфейса (Interface Segregation Principle, ISP): Много специализированных интерфейсов лучше одного общего. Клиент не должен зависеть от методов, которые он не использует.
- Пример: Вместо монолитного интерфейса
IMultifunctionPrinterс методамиprint(),scan(),fax(), создать отдельныеIPrinter,IScanner,IFaxMachine.
- Пример: Вместо монолитного интерфейса
-
Принцип инверсии зависимостей (Dependency Inversion Principle, DIP): Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей, детали должны зависеть от абстракций.
- Пример: Класс
OrderServiceдолжен зависеть от интерфейсаINotificationService, а не от конкретного классаEmailNotificationService. Это позволяет легко подменить реализацию наSmsNotificationService.
- Пример: Класс
Практическая польза: Следование SOLID облегчает рефакторинг, модульное тестирование и коллективную разработку, снижая связность кода и повышая его переиспользуемость.
Ответ 18+ 🔞
А, блядь, SOLID! Ну это же классика, ёпта, как борщ со сметаной. Пять принципов, которые должны сделать твой код не таким пиздецом, чтобы через полгода ты на него смотрел и не хотел впендюрить себе вилкой в глаз. Давай разберём, что это за хитрая жопа такая.
Во-первых, Принцип единственной ответственности (SRP).
Суть проще пареной репы: один класс — одна работа. Не надо делать из класса мартышлюшку, которая и на банане висит, и бубен бьёт, и в жопу даёт. Если твой класс Report и цифры считает, и в файл пишет, и ещё кофе варит — это пиздопроебибна архитектура. Он обязательно накроется медным тазом. Надо раздробить: пусть ReportCalculator только считает, а ReportSaver — только сохраняет. И каждый из них сосёт одну конкретную сосульку. Доверия к такому коду — ебать ноль, но после рефакторинга уже не так страшно.
Во-вторых, Принцип открытости/закрытости (OCP).
Звучит как заклинание, но смысл в том, что ты расширяешь функционал, не ковыряясь в старом, отлаженном коде. Представь, у тебя есть метод calculateDiscount(). И тут приходят новые типы клиентов: «премиум», «супер-пупер», «полупидор со стажем». Если ты начнёшь лепить в этот метод if (clientType == "premium") {...} else if (clientType == "superpuper")..., то через месяц этот метод будет похож на ёб твою мать, просто монстра. Вместо этого создаёшь абстрактную хрень DiscountStrategy, а от неё уже плодишь RegularDiscount, PremiumDiscount. Новый тип скидки? Новый класс, старый код не трогаешь. Красота.
В-третьих, Принцип подстановки Лисков (LSP).
Тут, чувак, нужно, чтобы наследник мог спокойно встать на место родителя, и ничего не сломалось. Классический пример — Square (квадрат), который наследуется от Rectangle (прямоугольник). Казалось бы, логично? Ан нет! У прямоугольника есть методы setWidth() и setHeight(), которые можно менять независимо. А у квадрата ширина всегда равна высоте. Подменишь в программе прямоугольник на квадрат, а там логика, которая меняет ширину отдельно от высоты — и всё, пиздец, инвариант нарушен, программа пошла по пизде. Наследник не должен делать хуже, чем родитель. Иначе это не наследник, а залупа конская.
В-четвёртых, Принцип разделения интерфейса (ISP).
Не надо делать интерфейс-монстра, от которого всем плохо. Вот смотри: есть у тебя интерфейс IMultifunctionPrinter с методами print(), scan(), fax(). А теперь приходит бедный класс SimplePrinter, который умеет только печатать. И что ему делать? Он вынужден реализовывать методы scan() и fax(), которые просто кидают исключение «NotImplemented». Это пиздец как некрасиво. Гораздо лучше наделать маленьких, целенаправленных интерфейсов: IPrinter, IScanner, IFaxMachine. И тогда каждый класс берёт только то, что ему нужно. Никакого насилия.
В-пятых, Принцип инверсии зависимостей (DIP).
Это про то, что высокоуровневые модули не должны цепляться за конкретные реализации низкоуровневых. Они должны зависеть от абстракций. Проще говоря, твой сервис заказов (OrderService) не должен впарывать в себя конкретный класс EmailNotificationService. Потому что завтра захочется слать смски, и придётся переписывать сервис заказов. Это волнение ебать какое. Вместо этого сервис должен зависеть от интерфейса INotificationService. А уже конкретную реализацию (EmailNotificationService или SmsNotificationService) ты подсовываешь ему извне (через конструктор, например). Теперь замена нотификации — это не апокалипсис, а пять минут работы.
А в целом, зачем это всё? А затем, чувак, чтобы твой код не превращался в лапшу, в которой через полгода разберётся только тот, кто её писал, да и то, если не забыл. SOLID повышает переиспользуемость, снижает связность (это когда изменение в одном месте вызывает взрыв бомбы в другом), и облегчает тестирование. В общем, не игнорируй это, а то будет вам хиросима и нигерсраки в одном флаконе.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶