А вы никогда не задумывались, почему, с одной стороны, у нас появляются всё более крутые и мощные инструменты для разработки?
На бэкенде мы можем делать микросервисы, писать офигительные SPA-приложения — но при этом будто бы сама программа становится всё хуже и хуже.

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

Откуда берётся эта эрозия программного обеспечения?
Почему так выходит, что новые технологии не только не помогают, но иногда даже мешают нам писать качественные программы? Почему, когда мы стараемся делать хорошо — получается плохо?
И главное — что с этим делать?

Требования как роскошь

Как же круто, когда можно просто открыть требования и понять: вот как должна работать система, которую мы делаем.

Сколько времени это могло бы сэкономить — все эти бесконечные созвоны, обсуждения, встречи — ведь в них мы просто пытаемся докопаться до сути.

А вечные баги? Они часто происходят из-за того, что эта суть нигде не зафиксирована.

Но вести требования, держать их актуальными — невыносимо больно.

Наверное, поэтому многие команды так и не приходят к их управлению. Есть задача, более-менее понятно, что делать — и ладно.

Никто в здравом уме не хочет писать требования — но все хотят, чтобы они уже были.

Почему код с этим не справляется

Теоретически, эту задачу мог бы решать и код.

Но с ростом сложности проекта и числа команд оказывается, что одно бизнес-правило начинает дробиться: на разные отделы, на разные приложения.

Всё это приводит к тому, что мы уже не можем хранить требования в коде. Где-то посередине появляется API endpoint — как новая граница, и требования начинают дробиться.

И вот требования уже не в коде. Они где-то между.

Монолит как способ удержать смысл, но не панацея

В этом, кстати, одно из преимуществ монолитной архитектуры: у вас просто меньше точек разрыва бизнес-логики.

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

Когда у нас не было SPA и микросервисов (если вынести за скобки производительность и масштабируемость), мы могли довольно точно управлять бизнес-логикой: все контроллеры были на бэкенде, в одном месте.

Но даже тогда у нас были заметны швы — например, база данных. Она уже накладывает некоторые технические ограничения.

Банально: чтобы выразить связь «многие ко многим», в SQL требуется промежуточная таблица. А в реальном бизнесе такой сущности нет. Это технический компромисс.

Код — это формат компрессии требований с потерями, как JPEG

На тему хороших технических компромиссов могу рассказать одну историю:

Когда появилась задача хранить изображения так, чтобы они занимали меньше места, чем огромные BMP-файлы, инженеры задумались: а как вообще человек воспринимает картинку?

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

Наш код работает примерно так же.

У нас нет способа выразить бизнес-логику в точности один к одному. Мы сжимаем реальность до программных конструкций, стараемся сохранить главное, но часть контекста и нюансов всё равно искажаются.

Мы создаём иллюзию целостности, но это уже не оригинальная бизнес-идея — это её JPEG-версия. Сжатая. Удобная. С такими техническими компромиссами, которые, по нашему мнению, не должны мешать воспринимать суть происходящего.

Чем больше удобства — тем меньше целостности

С каждым новым уровнем удобства разработки — будь то фреймворки, микросервисы, масштабируемость — мы жертвуем целостностью мышления.

Алгоритмы становятся менее прозрачными, а требования — более размытыми.

И в какой-то момент неизбежно встаёт вопрос:

А кто вообще управляет требованиями ко всей системе?

К сожалению, до сих пор не существует идеального способа хранить требования, трассировать их до кода и обратно. А может, его и не может существовать вовсе.

Поэтому я иногда мечтаю о простом языке описания системных требований на базе Markdown — с минимальной валидацией, автокомплитом и всем прочим.

Представьте, как было бы круто хранить требования прямо в репозитории и при этом иметь систему, которая помогает проверять их на непротиворечивость, полноту и другие важные свойства.

Но в чём я уверен точно: Каждое упрощение разработки — это просто обмен одной сложности на другую.

Чем больше вы дробите систему на маленькие автономные части, тем больше вам нужно беспокоиться о согласованности требований.
Чтобы в какой-то момент не оказалось, что у вас есть много кусочков… но никто не знает, что в целом должна делать система.

И если не управлять этим процессом — вы в итоге получите набор фрагментов, из которых уже нельзя собрать целое.

По этой же причине подход DDD выглядит особенно привлекательно — границы сервисов проходят по границам предметной области, стараясь не разрезать одно бизнес-правило пополам.

Если вы думаете, что это проблема исключительно программирования — или вообще надуманная — просто посмотрите на компании.

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

И, думаю, каждый из вас на своей шкуре замечал, что кривая оргструктура может создавать куда более разрушительные последствия, чем плохо написанный код.

И в следующий раз, когда вы будете проводить границу — в коде или в структуре компании — задумайтесь:

А не разрезал ли я только что одно бизнес-правило на две части? И что можно сделать, чтобы этого не допустить.

Возможно XP, TDD, DDD, и не лучшие что есть на свете, но кажется эти ребята поняли что-то первыми, так почему бы у них не поучиться, они явно что-то знают, раз делают все не так как мы привыкли.

Комментарии (3)


  1. AuToMaton
    02.06.2025 07:28

    К сожалению, до сих пор не существует идеального способа хранить требования, трассировать их до кода и обратно. А может, его и не может существовать вовсе.

    Бинго. Конечно не может существовать. Сама идея что можно получить требования и по ним написать что-то полезное - абсурдна. Так можно написать только то, что уже было написано. А это и нейронка (с)может.

    Мне нравится старая классическая формулировка.

    Задача программиста состоит в исследовании предметной области и записи результатов в виде, доступном для понимания как человеку, так и машине.

    Какие требования если область не исследована и зачем требования когда она исследована?

    И, думаю, каждый из вас на своей шкуре замечал, что кривая оргструктура может создавать куда более разрушительные последствия, чем плохо написанный код.

    Естественно. А оргструктура выполняет какие либо функции окромя услаждения да ублажения слуг правящего класса?

    Это ровно та же сложность, с которой сталкивается любой бизнес

    И это верно. А что есть бизнес как не совокупность чего угодно имеющая одного владельца?

    чтобы всё это разнообразие продолжало работать как единое целое.

    Как пример того, кто так может, Человечество в целом. Хотя, скорее могло. Изменилась плотность взаимодействия элитных группировок, перерождение в бизнес пошло.

    Почему так выходит, что новые технологии не только не помогают, но иногда даже мешают нам писать качественные программы? Почему, когда мы стараемся делать хорошо — получается плохо?И главное — что с этим делать?

    Потому, что программы создаются для рынка, а рынок слишком быстро стал массовым и, согласно закону 80/20, стал принимать такое, какое ему сейчас скармливают.

    Прямо сейчас не нужно делать ничего, кроме как помнить. Потому что когда кризис неизбежен, его оттягивание, так называемые «добрые дела», уничтожает ресурсы для выхода. Идти вместе с потоком - решать задачу не как сделать хорошо, а как заработать больше.

    Вот когда задумаются - а что строить на руинах миропорядка будем, кто-то должен будет вспомнить, встать (взлететь? вынырнуть? сунуть жвалы в астрал?) и спросить - э, стоп, а код то как будем писать? И суметь убедительно ответить на аргумент что до этого ещё далеко.


  1. dimonier
    02.06.2025 07:28

    Поэтому я иногда мечтаю о простом языке описания системных требований на базе Markdown — с минимальной валидацией, автокомплитом и всем прочим.

    Не совсем голый маркдаун, а ещё немного магии Obsidian Dataview. Я примерно это сделал для своей продуктовой команды. В пике трекали 390 требований. Мапили на них истории, критерии приемки и версии продукта.

    https://github.com/dimonier/Obsidian-Requirements-Management


  1. Dhwtj
    02.06.2025 07:28

    Был такой продукт давно

    Rational requisite pro с требованиями, которые мапились друг с другом и с управлением изменениями в clear quest

    Что с ними стало?

    Управление изменениями переехало в Jira, управление кодом в git, но управление требованиями потерялось