🧩 Каждый программист в процессе работы сталкивается с проблемой выделения абстракций в коде. Насколько этот код будет переиспользоваться? В каких местах? Следует ли переиспользовать код именно в этом месте? Не нарушит ли это принцип единственной ответственности, в этом месте код может изменяться по другой причине?

🔄 Схожие вопросы приходится решать при унификации программных решений, разрабатываемых во всей компании. Много разного кода, который делает одно и то же - это проблема, поддерживать такие решения дорого.

🧰 В таком случае абстрагировать приходится целые службы и сервисы, и в этом нет ничего нового. У всех достаточно крупных компаний есть внутренние SDK, которые решают общие проблемы - логирование, работа с хранилищами, межпроцессный обмен.

🔗 Но иногда у сервисов общий не только вспомогательный код, но и бизнес-логика. Допустим, у вас в приложении есть коллекция бизнес-сущностей (например, модулей для ПЛК) и от версии к версии приложения они меняются (потому что выходят новые прошивки этих модулей). При этом вы понимаете, что описания этих модулей используются в нескольких продуктах компании.

📚 И тут рождается новый уровень абстракции. Бизнес-сущности (модули) описываются в стандартном формате, например, JSON или XML. Набор этих сущностей размещается в отдельном репозитории, из которого выпускается пакет.

📦 Пакет версионируется и может изменяться независимо от кода приложений. Вышел новый пакет и достаточно обновить версию зависимости во всех сборках продуктов. Появляется единый источник правды (Single Source of Truth, SSOT), и данные в разных системах могут рассогласоваться, только если используют разные версии пакета.

⚠️ Но недостаточно просто придумать название для каждого атрибута и написать для них правила валидации. Сам формат описания становится одним из контрактов приложения. И главные вопросы необходимости таких абстракций никуда не деваются. Цена такой абстракции - повышение связанности разных продуктов между собой и необходимость продумывать больше краевых случаев.

🔀 Добавляя новый атрибут, приходится помнить, что приложение тоже нужно доработать и добавить соответствующую бизнес-логику. Что делать, если пришел файл старой версии, который не содержит значение этого атрибута, а на него уже завязана бизнес-логика? А если этот атрибут нужен не всем сервисам, а только одному? Добавить его и тащить мертвым грузом во все остальные? Или выпускать из одного репозитория два пакета, с новым атрибутом и без него?

🔌 Важно фиксировать, какие приложения зависят от этого контракта, где он используется только в межпроцессном обмене, а где выходит наружу и используется для взаимодействия с внешними системами. Ведь в этом случае он становится еще и частью вашего публичного API. Теперь каждый раз, внося ломающее изменение, придется считать, сколько клиентов из-за этого пострадают.

🗝️ Вынести сущности в отдельный репозиторий несложно. Сложнее ответить, кто им владеет. Кто решает, где проходят границы согласованности? Когда новая информация должна стать частью контракта, а когда ее нужно вынести отдельно? У каждого контракта должен быть свой пакет, свои причины для изменения и свой владелец, который принимает окончательное решение. Так получается не всегда, но чем ближе система к такому устройству, тем проще сохранять ее непротиворечивой.

🧩 Каждый программист в процессе работы сталкивается с проблемой выделения абстракций в коде | Сетка — социальная сеть от hh.ru