Разбитие монолита по DDD

В параллель с этим [созданием сервиса аутентификации] я рисую доменную диаграмму. То есть домен готовится к разбиению на микросервисы. Вплотную работаю опять-таки с TeamMember V. В этот момент он уже числится как Technical Product Owner (TPO). И является непосредственным Product Owner-ом (PO) нашей тимы. То есть это не бизнес PO, а техникал, непосредственно он ставит нам задачи. Ну, скажем так, какие-то задачи он нам приносил, какие-то задачи рождались в процессе наших с ним 121-ов. Кстати его вполне можно было называть “архивариусом продукта”, потому что он в полной мере знал этот бизнес.
Плюс отдельно общаюсь с каждой тимой, с тимлидами, узнаю, какие сервисы они делали. Рисую список бизнес-термов для себя. То есть, появляется отдельная такая большая диаграмма, которая включает в себя сабдомены как части одного большого домена. Начинают появляться понятия core-сабдоменов, support-сабдоменов, generic-сабдоменов. В каждом из них расписаны бизнес-термы.

Ну, это в целом классический подход при использовании Decompose By Subdomain паттерна. Он хорошо расписан в Microsoft Documentation. То есть они прямо так и говорят, очертите Bounded Contexts, в них распишите основные бизнес-термы. И играйте с этим, к чему-нибудь вы придете.
Некоторые сервисы уже напрашивались. То есть этот проект был на, скажем так, “замороженном этапе” по разбиению на микросервисы. Этот этап был на OnHold-е. Ввиду, опять-таки, как я и говорил выше, шквала задач. Но в то же время в процессе составления доменной диаграммы, ну или может реверс-инжиниринга, если удобнее, получилось выделить гораздо большее количество сервисов, чем было на стадии OnHold-а, стали понятны их границы, а некоторые сервисы вообще пропали.

Что делать, если этап разбиения монолита замораживается из-за более приоритетных задач?

Я думаю здесь два варианта решения этой проблемы. Например на прошлом проекте мы немного хитрили на эстимации. То есть, на рефайнмент сессиях когда мы эстимировали user stories, мы накидывали пару story-поинтов под tech-debt. Вот и все.

И, допустим, если приходит новая фича/user story, мы видим, что неплохо бы в рамках нее уже начинать выделять новый сервис. Или, допустим, сервис уже существует, но у нас выбор, либо сделать быстро в старом коде и показать заказчику как мы быстро все делаем, либо чуть медленнее, на пару дней допустим, но с решением техдолга, и выносом логики в правильный сервис, то мы ее (user story) просто немного оверэстимейтим и закладываем туда работы по техдолгу. Это в условиях натиска бизнеса, вариант, где мы немного хитрим.
На самом деле бизнес тоже можно понять – на решении техдолга быстро денег не заработаешь, не каждый бизнес в полной мере думает на перспективу в вопросе саппорта своего продукта. Приходится тайком ему помогать в этом ;)
Второй вариант - это когда есть свободные руки. Как раз на этом проекте они появились в лице меня и команды. По правде говоря это не значит, что смогли закрыть все активности по решению задач техдолга. Какие-то задачи уходили в другие команды, однако то, что уходило в другие команды, было четко приоритизировано относительно всего tech-debt бэклога. Ну например конкретные сервисы все-таки делали команды, а не мы, нам нужно было показать как это делать, тем самым упростив командам жизнь. Ну, а команды уже в рамках своих спринтов использовали первый подход с оверэстимейтом. Вот такой вот гибрид у нас получился. В общем нам повезло, что на каком-то этапе существования проекта удалось сформировать какую-то структурную единицу, которая бы смогла двигать с мертвой точки техдолг.
Вот такие два варианта. Может есть еще и третий, например, где бизнес заставляет решать вопросы с техдолгом, или заставляет его (техдолг) не допускать ;) Но на моей практике только такие варианты были возможны.

Под лежачий камень вода не потечет. То есть тут надо действовать, надо чтобы были желание, амбиции, и элемент везения или случайности, когда тебя кто-то поддержит. Потому что если никто не поддержит, то можно биться об стену очень долго. Ну, либо все делать самому. Сколько времени на это уйдет - вопрос риторический. Если никто не поддерживает, если всем все равно, то возможно, вы не на своем месте, возможно надо менять компанию. И искать свое место. Ну или просто работать, что-то кодить, какие-то денежки получать. Можно, в принципе, и так. Каждый сам выбирает.

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

Продолжаем разбивать монолит

Возвращаюсь к рассказу о разбиении монолита ;) В общем, рисовалась эта большая диаграмма. Этот процесс был очень сложный. Недели три у меня на это ушло. Все эти три недели были бесконечные звонки, общение с тимлидами, Product Owners, некоторыми девелоперами – старожилами проекта. Бывали рабочие дни буквально полностью занятые звонками.

Когда необходимый минимум информации был собран и спроецирован на драфтовую версию диаграммы домена, я назначал отдельную серию митов для финализации всего этого. Звал туда нашего на тот момент TPO (TeamMember V), нашего DevOps (TeamMember S). У первого без преувеличения колоссальные знания проекта, его истории и планов на будущее, у второго опыт построения распределенных и разбиения монолитных систем.
Багаж знаний каждого их них очень помогли мне на тот момент. В общем, вот так, на троих мы шлифовали первичный артефакт. Разбили сервисы на три важные подгруппы: core, support, generic. Благодаря этому стали понятны связи/отношения между сервисами – самым страшным грехом теперь стало нарушение этих связей. Ну откровенно говоря, допускались нарушения в процессе разработки командами, но это должно было быть озвучено, зафиксировано и быть понятно, когда, в рамках какой UserStory, это будет исправлено. Т.е. прецедентов старались не допускать.
И, кстати, для лучшего мониторинга за этим мы позже по особому реализовали ServiceDiscovery, собственно где и была map всех зависимостей между сервисами. Как я и говорил выше, на проекте существовал в “замороженном” виде какой-то набросок разбиения системы. Но по итогу финальный артефакт от него очень сильно отличался. Какие-то сервисы пропали, вместо них появились абсолютно новые и т.д.

Кстати говоря, существует такой best practice:
Не спешите сплитать какой-то сервис на микросервисы, потому что еще больше времени уйдет на его обратное воссоединение.
Часто рекомендуют начинать именно с модульного монолита в рамках всего проекта. И если понадобится в будущем переходить на микросервисы, то с модульным монолитом на исходной точке это будет сделать проще. Ну плюсы и минусы микросервисов думаю опустим, вы их и так все знаете.

Придумали как разбить, а что дальше?

Потом эта схема домена была презентована всему проекту, был отдельный Tech Talk, и там я снова всем рассказывал, что вот с этого дня мы живем по новым правилам. Вот такие сервисы уже сделаны, вот такие планируются на ближайшую перспективу, вот такие чуть позже, вот эти будут разрабатываться параллельно несколькими командами.
И началась новая жизнь, новый этап жизни проекта ;) DevOps сыграл свою роль с точки зрения CI/CD. Я ему иногда помогал тоже. В принципе, это дело мне нравится иногда, “подевопсить” немножко, пописать какие-нибудь пайплайны. А мы с TPO, в свою очередь, работали в паре в рамках коммуникации с остальными командами.

Что это значит? Учитывая то, что я еще одновременно был и тимлидом System Team, т.е. приходилось менеджить свою команду, помогать им осваивать новые для них вещи, и в то же время в рамках нового этапа на проекте приходилось менторить другие команды по вопросам разбиения сервиса, то мне нужна была помощь TPO.
В чем выражалась помощь? В том, что он был на всех рефайнментах в других командах. И в случае, когда появлялось, что-то, что попадало на уровень коммуникации между сервисами, что-либо новое, что вроде как можно сделать в легаси коде, но у нас под это уже заготовлен сервис на диаграмме, или наоборот, что-то, чего мы не учли на диаграмме, то мы потом на отдельных митах уже это обсуждали и приходили к чему-либо.

Иногда у меня получалось тоже приходить на рефайнменты других команд и например в таких случаях похожие вопросы могли решаться на месте, но иногда и нет, и чтобы не задерживать команды, мы отдельно потом решали, что и как будем делать с тем-то и тем-то. Также иногда, он и сам принимал решение, ведь в целом высокоуровнево понимание того, что и как делать у него тоже естественно было.
Кстати говоря, рабочий способ разбиения на микросервисы в процессе большого объема задач от бизнеса это паттерн Strangler. Этот шаблон означает миграцию монолитного приложения на микросервисную архитектуру путем постепенного переноса существующих функций в микросервисы. Ну и вот так вот задача за задачей потихоньку логика перетекала в новые микросервисы.

И собственно тут уже начинается распараллеливание разработки всех сервисов.

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