SOLID простым языком


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

Если до этого момента вы не были знакомы с принципами SOLID, то после их изучения вы поймете, что и раньше их использовали, пускай не все, но часть из них, не понимая этого.

SRP: Single Responsibility Principle

Это первый принцип, он говорит о том, что класс или же интерфейс должен иметь одно назначение, то есть решать одну поставленную задачу.

Что даст вам этот принцип?

Вы получите то, что является золотым Граалем в программировании, а именно слабосвязанный код, так как каждый ваш класс будет отвечать за решение определенной задачи, и такое явление как модификация логики вашего класса не потянет за собой ряд других исправлений, изменений других классов.

Это достигается путем соблюдения SRP на протяжении всего жизненного цикла проекта.

Также важно помнить, что даже соблюдая SRP, создав класс или интерфейс, который был предназначен для решения одной конкретной задачи, со временем добавляя функциональность вы можете нарушить этот принцип.

Поэтому важно следить за всеми изменениями в коде и не допускать подобных проблем путем разделения бизнес-логики на два отдельных класса. И чтобы не упустить такие моменты на проекте должен присутствовать анализатор кода и код ревью.

OCP: Open/Closed Principle

Означает то, что вы должны давать возможность только расширять ваши классы, но не давать возможности модифицировать их существующее поведение.

Чаще всего нарушение этого принципа встречается при использовании наследования, где путем переопределения в наследнике можно модифицировать базовое поведение родительского класса.

Придерживаясь этого принципа конкретно в Java можно с помощью ключевого слова final, которое запретит дальнейшие модификации метода или же свойств класса.

LSP: Liskov Substitution Principle

Создавая наследников одного и того же интерфейса или абстрактного класса, вы не должны менять поведение базового класса. То есть имея две реализации B и C класса A мы можем с легкость менять реализации и получать одинаковое конечное поведение обеих реализаций.

Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом.

Очень круто это показывает изображение ниже:

Liskov Substitution Principle

Преимущества:

Соблюдая этот принцип, вы получаете вполне ожидаемое поведение всех нижестоящих классов, а именно наследников, которые расширяют предка.

Нарушение LSP

Как показывает изображение выше:

Выглядит как утка, квакает как утка, но нуждается в батарейках - что является прямым нарушением абстракции.

ISP: Interface Segregation Principle

Ориентирован на то, что вместо одного интерфейса, который бы решал обширное количество задач, лучше предоставить несколько изолированных интерфейсов, каждый из которых нацелен на решение одной конкретной задачи.

Преимущества:

Теперь, когда вам нужно предоставить решение клиенту, вам достаточно предоставить решение конкретного интерфейса, вместо использования одного общего. Это также делает более читабельным и понимаемым как и какую задачу решает интерфейс, тем самым сделав возможной легкую дальнейшую поддержку данного интерфейса не задевая другие.

DIP: Dependecy Inversion Principle

Основная идея принципа - это не способствовать предоставлению зависимостей самостоятельно, а получать их из какого-то контейнера. Ярким примером этого является DI (Dependency Inversion), также это может быть другой ресурс, предоставляющий вам эти зависимости.

Нарушение DIP:

Как только вы начинаете заботиться о предоставлении зависимостей внутри класса, это нарушает DIP, а также такой подход делает ваш код сильно связанным и со временем усложняет его поддержку.

Ссылки

Видео: Николай Алименков — Парадигмы ООП

Рекомендуемое:

Понимаем REST. Часть 1

Целью этого поста есть пояснение REST ограничений, которые стоит соблюдать чтобы достичь правильного архитектурного стиля REST.