Comments 20
Ниже проанализированы различные архитектуры кода — TDD (разработка через тестирование), OOP (объектно-ориентированное программирование, ООП), FP (функциональное программирование, ФП), MVC (модель-представление-контроллер), MVVM (модель-представление-модель представления), микросервисы, событийно-ориентированная архитектура, CQRS (раздельная обработка команд и запросов), гексагональная архитектура, разработка через поведение (BDD), предметно-ориентированное проектирование (DDD)
Как говорится, и эти люди запрещают мне ковыряться в носу. Типичный уровень ИИ-визионера. В голове каша такая, что ложка стоит, - зато профессор всех наук.
Ниже проанализированы различные архитектуры кода — TDD (разработка через тестирование), OOP (объектно-ориентированное программирование, ООП), FP (функциональное программирование, ФП), MVC (модель-представление-контроллер), MVVM (модель-представление-модель представления), микросервисы, событийно-ориентированная архитектура, CQRS (раздельная обработка команд и запросов), гексагональная архитектура, разработка через поведение (BDD), предметно-ориентированное проектирование (DDD). Они отсортированы по показателю прикладной полезности в условиях, когда программирует не человек, а агент.
Спасибо, что подвох сразу в начале статьи - сэкономили время (вижу, что перевод; но дальнейший текст всё ещё применим - почему-то же эта "статья" прошла ценз автора публикации).
TDD, DDD, OOP и MVC (например) - понятия из разных категорий и их спокойно можно использовать в одном проекте на одном участке кода.
Судя по тому, что про эти понятия продолжаются какие-либо сравнения (то есть прикладывают одну "линейку"), ценза качества (хоть сколько-то разобраться в вопросе, для начала) не было ни у автора-человека, ни у нейросети, которая это генерировала.
Короткая (необязательно точная) справка:
TDD - методология процесса разработки, при котором проверка качества реализации (и в целом "уже готово или ещё делать") производится автотестами сразу. Это добавляет некоторые бонусы в стиль кода: контракты функций становятся более специализированными (чтобы тесты не превращались в месиво), раньше всплывают признаки антипаттернов (god object, например, когда попарных тестов - несколько десятков на один объект). И как можно раньше обнаруживаются ошибки. Ещё и требования к программистам тоже выше, что в целом повышает культуру разработки и эффективность работы.
DDD - это о том, какую ментальную модель выбрать/сконструировать, чтобы было проще и реализовать в коде, и представить пользователям, и приоритизировать важность свойств, чтобы более критичным обеспечились более надёжные условия существования во времени. Это даже больше философия с практическими применениями, нежели что-то про непосредственно про код изначально.
Из бонусов: когда модель подобрана, на её основе можно сделать шаблоны и прописать строгие ограничения, которые и дадут те границы модулей, в рамках которых уже проще думать. Тут идея (как я понимаю) в том, чтобы максимально упростить (для понимания, но и сложность как таковую) контракт домена, чтобы уменьшить его сложность и уменьшить вероятность ошибок, особенно неявных/скрытых.
OOP - про полиморфизм и изоляцию реализации от потребителя (не перекладывать часть контракта/сложности на потребителя) на уровне объектов. Тоже для простоты работы с объектами/структурами/данными - "объект отвечает за себя сам". Поэтому их рекомендуют делать как можно более специфичными - чтобы не терять контроль за поведением, требуя от внешних условий (относительно объекта) подстраиваться под него. То есть это о том, что "если есть интерфейс на входе функции, то я могу послать туда любой подходящий объект и я буду знать как он работает и что сделает".
Хотя тут сложная тема. OOP очень обширен, чтобы вот так легко его было сократить удачно. Но это не архитектура (чертёж завода), а способ крепежа кирпичей и балок друг с другом. Что, несомненно, между собой соприкасается (влияет друг на друга), но это точно не одна категория понятий.
MVC - техника контроля фокуса внимания между объектами и, как следствие, сложности (трудоёмкости, с учётом переделок/доделок) реализации. Ну и полиморфизм там рядом тоже несложно встраивается.
Архитектура в любом случае будет какая-то. И задача подбора нужных практик в том, чтобы она давала наибольшие плюшки. И большинство из них, кмк, про контроль сложности (чтобы люди допускали меньше ошибок, меньше порог входа, шире набор людей, которые могут решить проблему; ну и производительность в простом коде тоже проще прибавить) во времени. Что достигается практиками в разных слоях и разных углах обзора. Но сравнивать их как одинаковые - нельзя.
Пример: и дорога влияет на качество жизни, и отопление. Но ставить вопрос "дорога лучше, чем отопление" - весьма сомнительно, хоть и "ну это же оба про качество жизни".
Реализовать что-то сложное и работающее в принципе - возможно и без особо умных техник. Но сделать это расширяемым, ремонтопригодным, надёжным и переиспользуемым - сложно. Но эта сложность - для людей; у которых ограничен контекст и фокус внимания. У машин он, по идее, больше, но сложность/многосоставность/многоконтекстуальность мыслей у них ниже/нулевая, из-за чего "ИИ" лишь подкидывают очередную "головоломку" (впихнуть в него цель "сделать читаемость для людей, но скорость реализации как у машины; а ещё под капотом будет обучаемая вероятностная модель, но требовать от неё будем реализации строгих правил; чтобы и результат был стабилен во времени), а не закрывают класс проблем.
Отсюда и рассуждения вида "что лучше подходит для написания инструкции к колбасе: амфибрахий или гипербола" - нелепы в своей изначальной идее и в попытке сравнивать несравниваемое (хоть и одинаково применимы к текстам и идее "ну это же всё про текст и про людей, а значит можно сранивать"). Да, и гиперборла, и MVC, и рифмы, и статистика встречаемости букв - это всё про тексты, понимаемость людьми, про усвоение информации. Но это же не значит, что их вот так уравнивать и сравнивать можно. У них у всех разные задачи (или нет?).
Ниже проанализированы различные архитектуры кода — TDD (разработка через тестирование), OOP (объектно-ориентированное программирование, ООП), FP (функциональное программирование, ФП), MVC (модель-представление-контроллер), MVVM (модель-представление-модель представления), микросервисы, событийно-ориентированная архитектура, CQRS (раздельная обработка команд и запросов), гексагональная архитектура, разработка через поведение (BDD), предметно-ориентированное проектирование (DDD).
Точнее такое разделение, КМВ

Полгода в продакшене с Claude Code, и главная боль именно здесь. Агент понимает что написано, но зачем принято конкретное решение, не видит совсем. Тесты зелёные, код компилируется, а архитектурное намерение растворилось. Нас выручил CLAUDE.md на уровне каждого модуля, туда писали не документацию, а буквально запреты: вот это нельзя вынести наружу, вот это нельзя обобщить, потому что тут бизнес-инвариант. По TDD согласен, это реально единственная честная обратная связь для агента, красный или зелёный, без интерпретации. Ещё от себя: DDD с чёткими bounded contexts работает лучше чем ожидал, агент редко лезет за границы контекста если они явно прописаны.
Так и не понял, почему статья не размещена в хабе $mol.
Для товарища, со смертью мозга не выкупившего мета-иронию: https://habr.com/ru/articles/1033462/#comment_29952206
Ваша метаирония рассчитана на тех, кто читает хаб $mol. Ну, или на тех, кто читает статьи по поп-физике.
А я вот в их число не вхожу, поскольку я – задовик по специализации (т.е. $mol мне не интересен), а ещё – физик по образованию (и меня ещё в нашем физкультурном техникуме г.Долгопрудного МО научили, что сколько поле не квантуй, всё равно получишь поле). Потому метоирония ваша меня не затронула.
PS Минус к вашим комментариям, правда, я так и не поставил: за первый комментраий там не за что, а за второй, за смерть мозга - поленился: кто то уже успел до меня.
Этот хаб любят ставить нейрослоперы, так как он идёт самым первым в списке. $mol не ограничивается фронтендом, это изоморфный фреймворк. А вам не мешало бы выспаться, пока мозг совсем не потек.
Этот хаб любят ставить нейрослоперы, так как он идёт самым первым в списке
Я об этом не знал, не знаю и знать не хочу.
$mol не ограничивается фронтендом, это изоморфный фреймворк.
На задах он вообще не нужен. Вместе JS/TS.
PS И перестаньте, наконец, изображать из себя самого умного: у нас тут, в России, больно умных традиционно не любят, ценность у нас традиционная такая.
Зря вы гоните на DDD. Я конечно не эксперт, но тот самый "ритуальный" или "стереотипный" код позволяет неплохо экономить в будущем на том, что агент также начинает говорить с вами на одном языке и не лезет за границы доменов и контекстов.
Но управлять этим и направлять агента, особенно на ранних стадиях проектирования нужно безусловно самостоятельно, да. Потому что, как вы правильно сами заметили - агент не сделает анализ предметно области и часть работы из DDD за вас.
Но тактические паттерны определённо упрощают агентную разработку.
Отличная статья. Когда я еще писал руками, пришел к таким же выводам и перестроил свою работу в соответствии с ними. Теперь агенты пишут то, что я написал бы сам, но быстрее.
Есть еще похожая беда с dependency injection фреймворками. По коду невозможна навигация, так как зависимости модулей/объектов прописаны в каком-то другом месте, а не при инициализации.
Есть еще похожая беда с dependency injection фреймворками. По коду невозможна навигация, так как зависимости модулей/объектов прописаны в каком-то другом месте, а не при инициализации.
Не во всех. Вот, например, JS-код, который использует DI и вполне себе парсится VSCode через JSDocs.

Код писал Codex-агент под моим, не сильно чутким руководством. Поэтому он вот такой. Но я специально не правлю его руками. Работает - и славно.
Тем не менее, JSDoc + types.d.ts позволяют вполне себе сносно навигировать по коду и людям, и агентам (этим ещё и проще) даже с таким экзотическим подходом, как TeqFW DI. Можете открыть пакет flancer32/teq-web в VSCode и убедиться сами. Кстати, в правом верхнем углу видно, что валидация IDE работает. Красным выделены ошибки в коде с точки зрения VSCode.
Событийно-ориентированная архитектура устроена неявно — сначала публикуется событие, а затем где-то ещё какая-то другая сущность его обрабатывает. Единственный способ узнать, что это за сущность — прошерстить все файлы в поисках подписчиков. Агенты могут придерживаться явного потока управления как рецепта. При неявном потоке управления производительность агентов обычно снижается по той же причине, по которой неявный поток управления напрягает джунов: слишком велика доля важного поведения, остающаяся за пределами экрана
Вроде как нет. Надо просто идти в обратную сторону по времени/причине.
Сначала видим обработчик, который зависит от событий. Потом увидим кто публикует эти события. Ну да, это вам не в дебагере прыгать
Хотя задачи разные, да
Вперёд: что я этим сломаю?
Назад: чем это сломали?
у функции/интерфейса потребители находятся статически (IDE, компилятор) из-за того что продюсер знает потребителя, но это не гибко
Событийно ориентированная архитектура самая гибкая, потому что основана на слабых связях
То есть событийный подход хорош на границе между командами, доменами. Особенно когда нужна асинхронность / вызов, не блокирующий основной поток
Не успел подписаться - событие профукал.
Пришло второе событие, отменяющее первое - обрабатываем сперва зачем-то первое.
Пришло второе событие, меняющее состояние - при обработке первого используем уже устаревшие данные.
Сегодня два события пришли в одном порядке, завтра в другом - результат ХЗ.
Упал при обработке события - событие потерял.
Перезапустил обработчик на том же событии - сайд эффекты задублировались.
Охренеть как хорош, дайте две.
Ну, недостатков много, да. Всё решаемо, вопрос какой ценой и перевесят ли плюсы.
“не успел подписаться” - durable subscriptions, offset как в Kafka
порядок - партиционирование по ключу агрегата
устаревшие данные - версионирование, optimistic concurrency потеря при падении - at-least-once + ack после обработки
дубли - идемпотентность по message id
Цена: вся эта обвязка.
Внутри монолита почти всегда не перевешивает. Между сервисами/командами - часто да, потому что альтернатива (синхронные вызовы через сеть) приносит свои проблемы: каскадные падения, связанность по доступности
“не успел подписаться” - durable subscriptions, offset как в Kafka
И придётся хранить все события от начала времён, и накатывать их по очереди на каждого нового потребителя.
устаревшие данные - версионирование
Каким образом вам поможет версионирование, если событие изменения версии висит не обработанное в очереди?
порядок - партиционирование по ключу агрегата
Хз, о чём вы, похоже тоже не разобрались о чём вам говорят.
альтернатива (синхронные вызовы через сеть)
Альтернатива - не синхронная обработка событий, а работа с реактивным состоянием.
Я так понимаю этот ваш $mol?
Ориентирован на состояния, а не события
Дерево связей, где потребитель знает продюсера.
Ленивые вычисления / реактивность, продюсер ничего не сделает если его не спросят.
Композиция вычисления состояний (то есть промежуточные могут быть не вычислены если не нужны).
Мемоизация (кеш на каждом узле).
Какая-то транзитивнось связей узлов...
Да, вспомнил!
События могут быть важны сами по себе, для аудита. Так что для домена с аудитом это важно.
Ну и треш у вас... Может, пора переписать всё? Обычно таких проблем нет.
В агентскую эпоху не все архитектуры кода одинаково полезны