Абстракции: чаще убрать, чем добавить
Почему «не идёт» означает разошедшуюся модель предметной области и почему слой чаще нужно убрать, чем добавить
Когда работа буксует — задача не декомпозируется, изменение тянет за собой правки в пяти местах, никто не может объяснить, где живёт логика — рефлекс обычно один: добавить слой. Ещё один менеджер, ещё один сервис, ещё один интерфейс.
Почти всегда это лечение симптома. «Не идёт» означает, что модель предметной области разошлась с реальностью, и правильное действие — пере-абстрагировать: пересобрать границы так, чтобы они снова совпали с тем, как устроена задача. Иногда для этого нужно добавить абстракцию. Чаще — убрать или заменить.
Признаки лишнего слоя
Их видно глазами, без метрик:
- Слой, который только прокидывает вызовы. Метод принимает те же аргументы, что и вызываемый, и возвращает тот же результат. Единственное, что он добавляет, — ещё один файл в стектрейсе.
- Интерфейс с единственной реализацией. Заведён «на случай, если появится вторая». Второй за семестр так и не появится, а читать код через лишний прыжок будете все шестнадцать недель.
- Абстракция названа по технологии, а не по смыслу.
DatabaseManager,APIHandler,ServiceWrapper— имя, которое ничего не говорит о предметной области, обычно означает, что за ним и нет никакой предметной области. - Правка в одном сценарии задевает три модуля. Границы нарезаны не по линиям изменений, а по слоям технологии.
Два признака вместе — повод присмотреться. Три — почти диагноз.
Что изменила агентная разработка
Раньше лишний слой стоил дорого: его надо было написать руками, и это само по себе останавливало. Сейчас генерация дешёвая, и агент плодит абстракции охотно — попросили «сделай красиво», получили фабрику фабрик. Заодно он честно объяснит, зачем каждая нужна: модель хорошо рационализирует уже написанное.
Отсюда правило: слой появляется решением, а не по ходу генерации. Тот же принцип, что с новой зависимостью — сначала обсуждаем, потом добавляем. Если абстракция возникла в диффе сама, её надо либо принять осознанно, либо убрать.
Хорошая новость с той же стороны: рефакторинг тоже стал дешёвым. Переразметить границы — работа на вечер, а не на спринт. Поэтому менять модель предметной области можно и нужно смело: цена ошибки в разметке упала, цена жизни с неправильной моделью — нет.
Как это проверяет машина
Ощущение «стало запутанно» — не аргумент в споре. Аргумент — цифры aact analyze:
- cohesion ниже единицы у границы означает, что внутренних связей меньше, чем внешних: компоненты внутри границы связаны друг с другом слабее, чем с тем, что снаружи. Граница проведена не там.
- правило
commonReuseловит модуль, который тянут ради половины содержимого, — кандидат на разделение. acyclicловит цикл: A знает про B, B знает про A. Это всегда разошедшаяся модель, а не «так исторически сложилось».
Дальше работает обычный порядок: увидели цифру, поменяли границы, зафиксировали решение с ценой в ADR. Смена модели предметной области — ровно такое решение: у неё есть стоимость (переписанные модули, устаревшие диаграммы) и есть причина.
Когда абстракция действительно нужна
Чтобы не уехать в другую крайность — вот честные поводы завести слой:
- Есть две реальных реализации. Не «может появиться», а есть сейчас: две модели, два провайдера, две базы.
- Граница с чужой системой. Адаптер к внешнему API — тот самый Anti-corruption Layer: он не даёт чужой модели протечь в вашу.
- Точка изменчивости, подтверждённая опытом. Вы уже дважды меняли это место за семестр — третий раз дешевле сделать через абстракцию.
Во всех трёх случаях слой оплачен фактом, а не предчувствием. Всё остальное — «на будущее», а будущее в студенческом проекте наступает редко: семестр заканчивается раньше.