Связанность, глобалы и запахи модульности
Связанность (coupling) и глобальные сущности — частые причины хрупкого кода. Теория cohesion/coupling — в конструировании ПО; здесь — симптомы в коде и направления исправления.
Опора — MAPPER: объект в коде не должен знать о половине системы, если в реальности у него одна ответственность.
Высокая связанность — что видно в diff
| Запах (Фаулер) | Признак | Направление |
|---|---|---|
| Shotgun Surgery | Одно изменение правит 10 файлов | Собрать логику в один модуль |
| Divergent Change | Один класс меняется по разным причинам | Разделить по ответственности |
| Feature Envy | Метод больше читает чужие поля | Move Method |
| Inappropriate Intimacy | Классы лезут во внутренности друг друга | Инкапсуляция, фасад |
| Middle Man | Класс только пересылает вызовы | Inline / убрать прослойку |
| Message Chains | a.getB().getC().getD() | Закон Деметры, статья 1 |
| God Object | «Всезнайка» на тысячи строк | Разбиение по поддоменам |
| Singleton | Глобальная точка доступа | DI, явная передача зависимости |
Полный указатель — 13.
Singleton и глобальное состояние
Singleton — не паттерн GoF «для красоты», а скрытая глобальная переменная. Тесты не изолированы; порядок инициализации непредсказуем; подмена реализации на мок болезненна.
// Плохо: скрытая зависимость
public class ReportService {
public void Run() {
var db = DatabaseSingleton.Instance;
}
}
// Лучше: зависимость явна
public class ReportService {
private readonly IDatabase _db;
public ReportService(IDatabase db) => _db = db;
}
Глобальные функции, статика, goto:
- обернуть доступ к
DateTime.Now, файловой системе, env в инъектируемый порт; - статические
Utilsс бизнес-логикой → экземплярные сервисы; gotoи необоснованныеbreak— переписать структурированно.
Скрытые предположения
Превратить скрытые допущения в явные. Магическое 9999 как «нет значения», неявный часовой пояс, аргументы по умолчанию в середине списка — всё это ломает быстрый провал.
# Скрыто: -1 значит «нет id»
if user_id == -1: ...
# Явно
if user_id is MissingUserId: ...
Группы данных и примитивы
Если одни и те же пять параметров ходят вместе (street, city, zip…) — это группа данных (Data Clump). Реифицируйте в Address (статья 6).
UI и домен
Бизнес-правила не живут в обработчиках кнопок. Presentation вызывает use case; валидация email — в Email, а не в onClick.
См. слои в конструировании, чистую архитектуру.
Иерархии
Глубокое наследование, «йо-йо» иерархии, подклассы ради одного if — тема ООП. Правило: поведение важнее «is-a»; композиция часто честнее наследования.
Кратко:
- не наследовать ради переиспользования кода;
- пустые классы и заглушки — удалить или заполнить смыслом;
- protected поля — последний resort.
На ревью
- Новый import из «соседнего» bounded context — зачем?
- Появился
staticс mutable state? - Тест требует «сначала вызови Global.init()»?
- Изменение одного поля затронуло 5+ модулей — нужен рефакторинг границ.
Дальше: YAGNI и техдолг, тесты, справочник тем.
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Именование, форматирование, комментарии, документация в коде и базовые принципы читаемости — практики, которые команда договаривается соблюдать каждый день. Цикломатическая сложность — одна из наиболее устойчиво применяемых метрик статического анализа программного кода, призванная количественно оценивать логическую структуру исполняемого модуля. Правило MAPPER (Model Abstract Partial Programmable Explaining Reality) — как сопоставлять реальность и код один к одному. Богатые объекты предметной области, value objects вместо string/int и антипаттерны DTO-оргии. const, иммутабельность, ленивая инициализация и побочные эффекты в читаемом коде. Разделение «что» и «как», итерации, магические числа, callback hell и явные ошибки. Меньше if и switch, отказ от null, быстрый провал и полиморфизм вместо флагов. Мёртвый код, лишние абстракции, отключённые предупреждения и отложенный рефакторинг. Приватные методы, flaky-тесты, assertTrue, моки и данные — качество тестового кода и связь с разделом тестирования. Пустые catch, исключения как goto, узкие try и сообщения для пользователя. Краткие итоги раздела "Культура кода". Вопросы перед отправкой кода в репозиторий — именование, принципы, тесты, ревью и безопасность. Ответы ищите в статьях раздела.Культура написания и поддержки кода
Цикломатическая сложность и читаемость кода
MAPPER — модель кода и предметная область
Анемичные модели и примитивная одержимость
Изменяемость, побочные эффекты и неизменяемые данные
Декларативный код — что и как
Условия, null и явные контракты
YAGNI, быстрый провал и техдолг в коде
Тесты как часть культуры кода
Исключения и обработка ошибок в читаемом коде
Итоги
Чек-лист самопроверки