Принципы проектирования
Принципы проектирования помогают удерживать границы ответственности, локализовать изменения и выбирать простое решение под текущую задачу. Это не набор законов: каждый принцип полезен, пока снижает стоимость изменения и не создаёт абстракцию без потребителя.
Карта раздела
- Разделение ответственности — как выделять независимые причины изменения.
- Связность и зацепление — как оценивать границы модуля и стоимость зависимостей.
- Композиция вместо наследования — как собирать поведение из небольших компонентов в Go.
- SOLID на практике — как применять принципы без догматизма.
- DRY, KISS и YAGNI — как не дублировать знание и не строить преждевременную сложность.
- Инверсия и внедрение зависимостей — как направлять зависимости к стабильным контрактам.
- Инженерные trade-offs — как обосновывать выбор через требования и измерения.
Зачем это на интервью
На собеседовании важно не перечислить SOLID, а разобрать изменение: где пройдёт граница, что станет зависимостью, как это протестировать и какую сложность решение добавит. Сильный ответ называет контекст, альтернативу и критерий, по которому решение пересмотрят.
Минимум для E4
- Находить в задаче независимые причины изменения и отделять transport, прикладную логику и инфраструктуру.
- Объяснять разницу между высокой связностью модуля и сильным зацеплением модулей.
- Предпочитать явную композицию и маленькие интерфейсы реализации, когда это упрощает замену или тест.
- Не вводить общий слой до появления реального общего изменяемого знания.
Углубление для E5/Senior
- Проектировать границы по владению данными, консистентности, отказам и темпу изменений команд.
- Оценивать стоимость абстракции: API, миграции, наблюдаемость, обратная совместимость и когнитивная нагрузка.
- Подтверждать решение тестами, метриками и историей изменений, а не только чистотой диаграммы.
Ключевые понятия
- Ответственность — причина, по которой компонент должен измениться.
- Связность (cohesion) — насколько элементы модуля работают ради одной задачи.
- Зацепление (coupling) — насколько изменение одного модуля требует знания или изменения другого.
- Композиция — сборка поведения через поля, интерфейсы и делегирование.
- Абстракция — контракт, скрывающий вариативную деталь; она оправдана наличием вариативности.
Типовые вопросы
- Как понять, что класс или пакет делает слишком много?
- У него появляются независимые причины изменения, несвязанные зависимости и тесты, которые требуют множества разных сценариев настройки.
- Почему нельзя просто применить все SOLID-принципы?
- Каждый дополнительный слой имеет цену. Принцип направляет выбор при реальном изменении, но не заменяет требования.
- Что важнее: отсутствие дублирования или простота?
- Нужно устранять дублирование знания с общей причиной изменения; похожий код в разных доменах часто безопаснее преждевременной общей абстракции.
- Почему в Go интерфейс обычно объявляет потребитель?
- Потребитель формулирует минимальные нужные ему операции, поэтому контракт не превращается в широкий интерфейс поставщика.
- Как доказать, что новая граница лучше старой?
- Показать сценарий изменения, уменьшение затронутых модулей, изолированный тест и отсутствие лишней эксплуатационной сложности.
Практика
- Возьмите HTTP-handler с SQL и бизнес-правилами. Разделите parsing/validation, use case и repository; критерий: use case тестируется без
httptestи реальной БД. - Для двух похожих интеграций выпишите, что совпадает по смыслу, а что меняется независимо; критерий: решение об общем контракте содержит минимум два подтверждённых сценария вариации.
- Проведите review небольшого PR: назовите одну границу, одну лишнюю абстракцию и проверяемый критерий улучшения.
Частые ошибки и ловушки
- Делить код только по техническим слоям, не замечая границ домена и владения данными.
- Выносить общий helper для похожего синтаксиса, хотя правила и будущие изменения различаются.
- Создавать интерфейс на каждую структуру и получать косвенность без альтернативной реализации.
- Оценивать дизайн по числу паттернов вместо стоимости следующего изменения.
Связанные темы
База разработки и Computer Science · Разделение ответственности · Go · Проектирование Go-приложений · System Design · Тестирование
Источники
- Robert C. Martin, Clean Architecture и Agile Software Development: Principles, Patterns, and Practices.
- John Ousterhout, A Philosophy of Software Design.
- Документация Go: Effective Go и Code Review Comments.
- Eric Evans, Domain-Driven Design, главы о границах модели и модулей.