Антипаттерны и code smells
↑ 8.1 Принципы и паттерны проектирования в C♯ · ← Предыдущая
Зачем это на собесе
«Что вам не нравится в этом коде?» — типичное ревью на собеседовании.
Объяснение
| Запах / антипаттерн | Признак | Лечение |
|---|---|---|
| God Object | класс делает всё | разделение по ответственностям |
| Long Method / Long Parameter List | метод на сотни строк, 8 параметров | Extract Method, Parameter Object |
| Anemic Domain Model | сущности — только данные, логика в сервисах | переносить поведение в домен |
| Feature Envy | метод чаще использует чужие данные | переместить метод |
| Shotgun Surgery | одно изменение → правки в десяти местах | собрать ответственность |
| Primitive Obsession | string email, decimal money везде | value objects |
| Magic numbers/strings | «42», «“paid”» | константы, enum |
| Copy-Paste | дублирование логики | вынести знание |
| Speculative Generality | абстракции «на будущее» | YAGNI |
| Service Locator | provider.GetService в коде | внедрение через конструктор |
| Singleton-абьюз, статические синглтоны | глобальное состояние | DI |
| Golden Hammer | один инструмент для всего | выбор по задаче |
| Leaky Abstraction | детали реализации в интерфейсе | пересмотр границ |
| Lava Flow | мёртвый код, «трогать страшно» | тесты и удаление |
Async: async void, .Result | см. Антипаттерны: async void, .Result, sync over async | await по цепочке |
Catch-all: catch (Exception) {} | проглоченные ошибки | обработка/логирование/проброс |
| Chatty API / N+1 | множество мелких запросов | батчинг, проекции |
| Distributed Monolith | сервисы связаны и деплоятся вместе | пересмотр границ |
| Big Ball of Mud | нет структуры | модульность, ADR, границы |
Рефакторинг: небольшими безопасными шагами, под защитой тестов (Extract Method, Introduce Parameter Object, Replace Conditional with Polymorphism, Move Method).
Нюансы и подводные камни
- Запах — это подсказка, а не приговор: оценивайте контекст и стоимость исправления.
- Рефакторинг без тестов — риск; начните с тестов на текущее поведение (characterization tests).
- «Переписать с нуля» редко оправдано: улучшайте постепенно (strangler fig).
- Не оптимизируйте эстетику вместо ценности для продукта.
Практика
- Проведите ревью модуля и составьте список запахов по приоритету.
- Выделите value object для email/денег.
- Уберите анемичность: перенесите правило из сервиса в сущность.
Вопросы с ответами
Что такое анемичная доменная модель?
Сущности содержат только данные, а вся логика находится в сервисах; теряется инкапсуляция и инварианты.
Как безопасно рефакторить legacy?
Сначала покрыть поведение тестами, затем малыми шагами улучшать структуру.