# Абстракции: чаще убрать, чем добавить

> Почему «не идёт» означает разошедшуюся модель предметной области и почему слой чаще нужно убрать, чем добавить

_Источник: https://sii.sergeivolchkov.ru/materials/architecture/abstractions_



Когда работа буксует — задача не декомпозируется, изменение тянет за
собой правки в пяти местах, никто не может объяснить, где живёт логика —
рефлекс обычно один: добавить слой. Ещё один менеджер, ещё один сервис,
ещё один интерфейс.

Почти всегда это лечение симптома. **«Не идёт» означает, что модель
предметной области разошлась с реальностью**, и правильное действие —
пере-абстрагировать: пересобрать границы так, чтобы они снова совпали с
тем, как устроена задача. Иногда для этого нужно добавить абстракцию.
Чаще — убрать или заменить.

## Признаки лишнего слоя [#признаки-лишнего-слоя]

Их видно глазами, без метрик:

* **Слой, который только прокидывает вызовы.** Метод принимает те же
  аргументы, что и вызываемый, и возвращает тот же результат. Единственное,
  что он добавляет, — ещё один файл в стектрейсе.
* **Интерфейс с единственной реализацией.** Заведён «на случай, если
  появится вторая». Второй за семестр так и не появится, а читать код
  через лишний прыжок будете все шестнадцать недель.
* **Абстракция названа по технологии, а не по смыслу.**
  `DatabaseManager`, `APIHandler`, `ServiceWrapper` — имя, которое
  ничего не говорит о предметной области, обычно означает, что за ним и
  нет никакой предметной области.
* **Правка в одном сценарии задевает три модуля.** Границы нарезаны не
  по линиям изменений, а по слоям технологии.

Два признака вместе — повод присмотреться. Три — почти диагноз.

## Что изменила агентная разработка [#что-изменила-агентная-разработка]

Раньше лишний слой стоил дорого: его надо было написать руками, и это
само по себе останавливало. Сейчас генерация дешёвая, и агент плодит
абстракции охотно — попросили «сделай красиво», получили фабрику фабрик.
Заодно он честно объяснит, зачем каждая нужна: модель хорошо
рационализирует уже написанное.

Отсюда правило: **слой появляется решением, а не по ходу генерации**. Тот
же принцип, что с новой зависимостью — сначала обсуждаем, потом
добавляем. Если абстракция возникла в диффе сама, её надо либо принять
осознанно, либо убрать.

Хорошая новость с той же стороны: **рефакторинг тоже стал дешёвым**.
Переразметить границы — работа на вечер, а не на спринт. Поэтому менять
модель предметной области можно и нужно смело: цена ошибки в разметке
упала, цена жизни с неправильной моделью — нет.

## Как это проверяет машина [#как-это-проверяет-машина]

Ощущение «стало запутанно» — не аргумент в споре. Аргумент — цифры
[aact analyze](/materials/architecture/aact):

* **cohesion** ниже единицы у границы означает, что внутренних связей
  меньше, чем внешних: компоненты внутри границы связаны друг с другом
  слабее, чем с тем, что снаружи. Граница проведена не там.
* **правило `commonReuse`** ловит модуль, который тянут ради половины
  содержимого, — кандидат на разделение.
* **`acyclic`** ловит цикл: A знает про B, B знает про A. Это всегда
  разошедшаяся модель, а не «так исторически сложилось».

Дальше работает обычный порядок: увидели цифру, поменяли границы,
зафиксировали [решение с ценой](/materials/architecture/c4-levels) в ADR.
Смена модели предметной области — ровно такое решение: у неё есть
стоимость (переписанные модули, устаревшие диаграммы) и есть причина.

## Когда абстракция действительно нужна [#когда-абстракция-действительно-нужна]

Чтобы не уехать в другую крайность — вот честные поводы завести слой:

* **Есть две реальных реализации.** Не «может появиться», а есть сейчас:
  две модели, два провайдера, две базы.
* **Граница с чужой системой.** Адаптер к внешнему API — тот самый
  [Anti-corruption Layer](/materials/architecture/aact): он не даёт чужой
  модели протечь в вашу.
* **Точка изменчивости, подтверждённая опытом.** Вы уже дважды меняли
  это место за семестр — третий раз дешевле сделать через абстракцию.

Во всех трёх случаях слой оплачен фактом, а не предчувствием. Всё
остальное — «на будущее», а будущее в студенческом проекте наступает
редко: семестр заканчивается раньше.
