kata academy

Принципы SOLID для начинающих



Время чтения: 4 минуты
Поэтому основную оплату в гибридном формате ты вносишь уже после трудоустройства
Важно, чтобы ты получил оффер от компании, в которую действительно хочешь
Когда начинаешь писать первые программы, думаешь только о том, чтобы код работал. Это нормально. Но потом проект растёт, появляются новые задачи и оказывается, что в старом коде разобраться почти невозможно. Приходится переписывать всё с нуля.

Принципы SOLID появились именно для этого. Это пять правил, которые помогают писать понятный, гибкий код — тот, который легко менять и не страшно передавать другим разработчикам. Разберём каждый принцип на простых примерах.
Что такое SOLID
Что такое SOLIDSOLID — аббревиатура из первых букв пяти принципов объектно-ориентированного программирования. Их сформулировал американский программист Роберт Мартин в начале 2000-х.

  • S — Single Responsibility (Согласованность ответственности)
  • O — Open/Closed (Открытость для расширения)
  • L — Liskov Substitution (Логика наследования)
  • I — Interface Segregation (Изолированность интерфейсов)
  • D — Dependency Inversion (инверсия зависимостей)
Принципы не привязаны к конкретному языку. Они работают в Java, Python, Go и других. Примеры ниже — на псевдокоде, чтобы было понятно вне зависимости от того, что ты изучаешь.
S — Один класс, одна задача
Single Responsibility Principle — у каждого класса должна быть только одна причина меняться.
Один класс решает одну задачу.

Представь класс User. Он хранит данные о пользователе, проверяет пароль и отправляет письмо на почту — три разные задачи в одном месте. Если завтра нужно поменять способ отправки писем, придётся залезать в класс, который отвечает за пользователей. Легко сломать то, что работало.

Плохо:
class User:
def save_to_database(): ...
def validate_password(): ...
def send_welcome_email(): ...

Хорошо:
class User:
def validate_password(): ...

class UserRepository:
def save_to_database(): ...

class EmailService:
def send_welcome_email(): ...

Теперь каждый класс делает своё дело. Изменения в одном не затрагивают другой.
O — Расширяй, но не ломай
Open/Closed Principle — класс должен быть открыт для расширения, но закрыт для изменения.
Нужна новая функция — добавляешь новый код, а не переписываешь старый. Допустим, ты пишешь систему скидок для магазина. Есть обычные клиенты и VIP-клиенты.

Плохо:
class Discount:
def calculate(user_type):
if user_type == "regular":
return 5%
if user_type == "vip":
return 20%

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

Хорошо:
class Discount:
def calculate(): ... # базовый интерфейс

class RegularDiscount(Discount):
def calculate(): return 5%

class VIPDiscount(Discount):
def calculate(): return 20%

class NewYearDiscount(Discount):
def calculate(): return 30%

Новый тип скидки = новый класс. Старый код трогать не нужно.
Узнай свою рыночную зарплату за 1 минуту!
IT-калькулятор зарплат
L — Замени родителя на потомка и ничего не сломается
Liskov Substitution Principle — если класс B является наследником класса A, то везде, где используется A, можно поставить B, и всё должно работать так же. На практике это значит одно: наследник не должен нарушать логику родителя.

Классический пример — птицы. Есть класс Bird с методом fly(). Ты создаёшь наследника Penguin. Пингвин — птица, но летать не умеет. Вызвал fly() — получил ошибку.

Плохо:
class Bird:
def fly(): ...

class Penguin(Bird):
def fly():
raise Exception("Пингвины не летают!")

Хорошо:
class Bird: ...

class FlyingBird(Bird):
def fly(): ...

class Penguin(Bird): ... # без метода fly

class Eagle(FlyingBird):
def fly(): ...

Пингвин — птица, но летающий класс отдельный. Никаких неожиданных ошибок.
I — Не заставляй реализовывать лишнее
Interface Segregation Principle — лучше несколько маленьких интерфейсов, чем один большой. Интерфейс — контракт: список методов, которые класс обязан реализовать. Если интерфейс раздут, классы вынуждены реализовывать методы, которые им не нужны.

Интерфейс — контракт: список методов, которые класс обязан реализовать. Если интерфейс раздут, классы вынуждены реализовывать методы, которые им не нужны.

Плохо:
interface Worker:
def work(): ...
def eat(): ...
def sleep(): ..

Класс Robot работает, но не ест и не спит. Всё равно придётся добавить пустые методы eat() и sleep() — мёртвый код, который только запутывает.

Хорошо:
interface Workable:
def work(): ...

interface Eatable:
def eat(): ...

class Human(Workable, Eatable):
def work(): ...
def eat(): ...

class Robot(Workable):
def work(): ...

Каждый класс реализует только то, что ему нужно.
Обучение с личным ментором, поддержкой
при поиске работы и оплатой на выбор: сразу или после трудоустройства
Обучение в IT с фокусом на трудоустройство
D — лучше абстракции, а не конкретика
Dependency Inversion Principle — модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций. Не привязывай код к конкретной реализации. Работай с абстракцией — тогда детали можно менять без последствий.

Есть класс OrderService, который отправляет уведомления. Внутри него жёстко создаётся EmailSender. Хочешь переключиться на SMS — придётся менять OrderService.

Плохо:
class OrderService:
def notify():
sender = EmailSender()
sender.send()

Хорошо:
interface Notifier:
def send(): ...

class EmailSender(Notifier):
def send(): ...

class SmsSender(Notifier):
def send(): ...

class OrderService:
def __init__(notifier: Notifier):
self.notifier = notifier

def notify():
self.notifier.send()

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

Когда каждый класс делает одно дело, в нём проще разобраться: и тебе самому через месяц, и коллегам. Код можно менять в одном месте, не боясь сломать остальное. SOLID — стандартная тема на собеседованиях для Junior-разработчиков, и умение объяснить принципы своими словами уже выделяет. Наконец, придя на работу, ты увидишь эти принципы в реальных проектах — лучше встретить их не впервые.
Выбирай обучение с гарантией трудоустройства. Пройти курс разработке можно за 9 месяцев. В этот срок входит обучение, подготовка к собеседованиям и трудоустройства.

  • Гарантия трудоустройства прописана в договоре на обучение
  • Обучение с личной поддержкой ментора: ревью, созвоны 1to1 и в группе, чат
  • Подготовка к собеседованиям с hr-консультантом, сопровождение до оффера
Как поступить?

Выбери курс на сайте и подай заявку на консультацию.

Статьи для старта в IT

Истории наших выпускников

Стань тем, кто задаёт тон в ИТ!
Подпишись на нашу рассылку и первым получай статьи по Java, JavaScript, Go и QA. Позволь себе быть экспертом!