Комментарии 6
Разделение на 4 активности - то, чего жанру обычно не хватает: все застревают на археологии, а "обеспечение соответствия" и "проектирование изменения" сливают в один туман. Спасибо, что растащили.
Тезис "глубина переписывания зависит от уровня знания, а не от смелости команды" - это ровно мой опыт. Тащил миграцию edtech-платформы с Rails на .NET, 10 месяцев. Где у нас был доступ к верхнему уровню - к людям, которые помнили почему фича сделана именно так - получался настоящий реинжиниринг. Где доступа не было - честный lift-and-shift через адаптер, который стыдно показывать, но он работал и не врал.
И мой главный косяк ровно в вашу тему: за все 10 месяцев мы провели одну Event Storming-сессию. Одну. То есть систематически недоинвестировали в тот самый верхний уровень, а потом гадали по коду - путь в никуда, как вы и пишете. Хуже того: команда искренне считала, что замысел уже восстановлен, хотя восстановлена была от силы половина. Вот эта переоценка собственного знания - по-моему, главная ловушка, и метрики у неё нет.
Как вы для себя ловите момент "знаю достаточно, чтобы лезть глубже lift-and-shift"?
За части 3-4 и за реальные кейсы - голосую двумя руками. Их в жанре и не хватает: про археологию пишут все, а про развилку "нашли баг посреди миграции - чинить сейчас или тащить дальше как есть" почти никто. У меня была ровно эта вилка, и решали мы её, честно, наугад. Будете раскрывать - расскажу свой кейс в комментах.
Спасибо за проявленный интерес
реальные кейсы
Это тяжело: кусочек тут, акцент там... Статья начнёт распадаться.
Ну в двух словах расскажу.
Есть 15 летняя лапша в госах. Пхп, много следов от пхп 5, версия поднята, но хлам остался. Переделки полной с нуля не будет никогда, слишком много хлопот организационных, риски миграции, обучение, привычки, процессы...
Но 4 года назад программе повезло наконец то встретиться с сильной командой из 2 человек)
Я пришёл в проект из более современного стека, поставив условие что на рефакторинг будет выделяться треть ресурсов, а моя работа больше архитектором чем баги править. Карма позволяла ставить условия). И наглость.
В первый год изучали, тушили пожары, потом начали переписывать.
Сложные случаи:
Первая попытка сконцентрировать разбросанную логику в домене, валидировать с экспертами короткий и понятный код домена и тем самым обеспечить надёжность - провалилась. Слишком широкий замах и незнакомый стек (включая фронт, который слишком сильно зависел от структур данных). Смешал несколько технологий и запутался в mutable shared state. Переоценил возможности LLM.
Пришлось признать поражение согласиться с руководством, милостиво выбросившим байку что всё отдадут другой компании и вкладываться не нужно. Это было моральное спасение. Я свернул scope до минимального, добавил нужные валидаторы и это жило ещё полгода в виде transaction script.
Потом стало больше времени (а руководство могло решить или перекинуть в другой проект или вообще "оптимизировать") и набравшись сил я всё-таки спроектировал DDD с элементами гексагональной архитектуры. Объём релиза 10.000 строк, мелкими кусками не получалось. Из-за рисков релиз готовился и проверялся полгода.
Новые грабли:
Адаптеры кривые, мусор остался в домене. Нашёл красивое нестандартное решение - адаптер в БД, через view.
Потом столкнулся с каскадными проблемами легаси, когда одно кривое решение было причиной другого, третьего... Post кидал данные с формы данные в нелепом виде, уродливый адаптер защищал домен, но хрупко... При попытке изменить структуру внезапно отвалился богом забытый JS, неявно подписанный на неё и на HTML теги. Сделал частично. Но понравилась идея, что agile spike помогает провести быструю разведку боем и посмотреть не стоит ли пробить ещё один уровень каскадно-кривых легаси контрактов и привести систему в порядок, убрав хрупкость адаптеров ценой увеличения объёма изменений.
Потом был интересный кейс, когда пробовал LLM агентов. Да, нашли все зависимости кода, предложили решение, но архитектурно хрупкое: кривая структура была в центре зависимостей. Когда хотел её исправить шла стрельба дробью. Потом ещё патч. В результате n² изменений. То есть антихрупкость, low coupling high cohesion - ну никак не дело LLM. Это дело архитектора определить часто меняющиеся участки и сгруппировать их в домен.
И грабли с тестированием command части CQRS - надо же смотреть изменения в БД. И в старой системе тоже, а там никаких слоев, тесты вставить некуда, только трудоемкие ручные. Сделал свой proxy + loger get/post + dbdiff. Хотя не сильно помогло, но отловил пару ошибок.
Ну вот, основные интересные кейсы, которые встретил. Если кратко.
Доменную экспертизу вырастили сами. Теперь мы знаем процессы лучше чем кто-то другой. Доменных экспертов тупо нет кроме нас.
знаю достаточно, чтобы лезть глубже lift-and-shift"
Пока что танцами по граблям. Просто приняли решение, что в первый год ничего не меняем, пока не разберемся
Спасибо, что развернули так подробно, это наверное тянет на отдельную статью ))
И ценно, что вы не спрятали провал первой попытки: почти все рассказывают про легаси как "пришёл и навёл порядок", а в реальности всегда что-то типа этого... слишком широкий замах, отступление до transaction script, и только со второго-третьего захода DDD. У меня на похожем проекте миграции было так же: первый замах оказался шире, чем стек и моё знание домена позволяли это, пришлось резать скоуп и отступить. Адаптер через view в БД - интересно, приём украду )
Сильнее всего зацепил вывод про LLM: когда кривая структура в центре зависимостей, правка идёт дробью на n² мест. Лучшей формулировки предела нейросетей в легаси я, пожалуй, не встречал, хаха. LLM оптимизирует, чтобы изменение заработало здесь и сейчас, у неё нет модели того, какие правки придут завтра - а шов архитектор вводит под будущие изменения, которых нейросеть не видит. Старый принцип information hiding: модуль прячет то, что вероятнее всего поменяется. Поэтому правка и расползается, вместо того чтобы локализоваться.
И раз вы сами вывели на то, что LLM провоцирует переоценку знания, накину еще с другой стороны...
Доменных экспертов тупо нет кроме нас.
Знание о домене теперь держится на двух людях. И тут мой любимый параноидальный вопрос: это знание лежит где-то кроме двух ваших голов? Ведь так и родилось легаси, которое вы разгребаете - кто-то всё понимал, ушёл и понимание ушло с ним. Пара абзацев ADR: почему адаптер через view, почему этот участок в домене, почему тогда срезали скоуп. То самое "почему", которого так не хватало вам в начале. Ведёте что-то подобное или пока некогда?
это знание лежит где-то кроме двух ваших голов?
нет, заказчик осознанно не хочет брать на себя это
да, если команда сменится, то все знание уйдет с командой (документация и код мало чем помогут)
для долгоживущих систем нужны долгоживущие core команды
Ведь так и родилось легаси, которое вы разгребаете - кто-то всё понимал, ушёл и понимание ушло с ним
ну да. ADR и прочее я пишу для будущего себя, но не надеюсь что кто-то еще поймет (я вообще мало знаю специалистов по DDD)
но на уровне кода стало значительно понятней всем - вот сегодня мой баг поправил другой разработчик в легкую
правка идёт дробью на n² мест.
правкИ. n правок на n мест
ну или n*k - просто показал масштаб
это наверное тянет на отдельную статью
Я люблю читать про чужой опыт (случаи, боль, шрамы), но про свой писать почему-то не люблю.
Сейчас хочется научиться отбивать проблемы в одно касание, не залипая на месяцы: просто найти баг, просто починить, прогнозируемо по срокам, без переделок, иногда переписывая старый код но тоже просто и прогнозируемо. И вообще работой заниматься часа по 2 в день...
Адаптер через view в БД - интересно, приём украду )
аналитика, пивот
десятки правил "если разрез такой, то данные взять отсюда, с таким фильтром, взять первые 2 символа из этого поля и сравнить с этим"
если домен пытаться сделать чистым (пивот не знает ничего про получение данных), то поставщик - адаптер становится слишком умным и уродливым, это уже целый новый сервис "поставщик", ETL
ну и если подумать, то всю эту логику можно засунуть в view, а пивот будет обращаться как к таблице и тестировать данные просто - смотришь глазами view и все
нестандартный подход, да - очень упростил тот кейс
последнее время много логики уходит в PL/SQL потому что так удобнее тестировать на реальных данных - вызываешь в dbeaver и смотришь глазами
нашли баг посреди миграции
Нет. Но откат релиза невозможен, какие-то кривые настройки Git и Jenkins. Было стрёмно.
В итоге, на тестирование ушло времени примерно сколько и на код. Несколько багов всё равно вылезло на прод на кейсе, который считали редким (смотрели в БД - считанные разы за год).
команда искренне считала, что замысел уже восстановлен, хотя восстановлена была от силы половина
Ну, что-то похожее было, да. Не вспомню уже что конкретно. Но проблем не возникло: спасло наличие времени и критическое мышление. Второпях не отловили бы. И это хорошее свойство запланированного заранее рефакторинга, а не когда нужно срочно что-то заменить, а перед этим надо Авгиевы конюшни разгрести.
переоценка собственного знания - по-моему, главная ловушка, и метрики у неё нет
Зато LLM очень провоцирует такую переоценку и уверенность что всё уже понятно. Такая вот психологическая ловушка
Я писал короткие тире (-) и обычные кавычки (").
Это у нас теперь Хабр сам делает статью подхожей на нейрогенерацию?

Рефакторинг и реинжиниринг легаси. Погружаемся глубже