Я дико люблю ковыряться в чужом коде. Это одна из моих любимых специализаций. То есть я просто беру чужой код, анализирую его, читаю. Как я читал его раньше: я переводил код в русский язык. Описывал, что происходит по флоу кода, и пытался понять, что там происходит. Эти записи я в дальнейшем использовал как для написания статей в Confluence, так и для общего понимания происходящего. С одной стороны, решение работающее. С другой, буквально через неделю-две я уже начинал сомневаться, достаточно точно ли я «перевел» с кода на русский язык? И тогда вспомнил про UML-диаграммы. И вместо того, чтобы записывать текст, стал визуализировать его и исписал неимоверное количество тетрадей.  Но в какой-то момент подумал, что хорошо бы перевести все это в электронный вид, чтобы какой-то инкремент оставался. Не фоткать же, например, для документации, свою тетрадь с каракулями. Так я нашел инструмент PlantUML — opensource-решение, которое использует графическую библиотеку graphviz, превращающее код в наглядные схемы. Давайте вспомним, что такое Unified Modeling Language. Чаще всего в университете UML используется для описания диаграммы классов. У человека есть паспорт, у дома есть стены. У класса «дерево» есть птицы, дерево умеет сбрасывать листья. Birds — это интерфейс, который реализует fly, и есть некий Raven, который его реализует. Чтобы написать код, который выдаст схему, мне потребовалось минуты две. Их я потратил на то, чтобы придумать, что нарисовать.  Можно даже взять PlantUML и запустить простой JSON. Получим красивую схему, которую будет не стыдно вставить в рабочую документацию. Во-первых, это анализ чужого кода. Я разработчик процессинга Qiwi Кошелька, и у нас есть код, который занимается OAUTH2  авторизацией. Я читал его уже раз восемь, но через пару недель все равно забываю, как он работает. При том, что код лаконичный, динамичный, он позволяет делать, что угодно. Но каждый раз, когда я открываю классы, и вижу OAuthCore класс, думаю: “е-мое”. Когда я нарисовал схему, мне и моим коллегам стало гораздо проще ковырять этот код. Во-вторых, для объяснения, как что-то работает. С наступлением пандемии, когда все ушли на удаленку, для описания задач и фичей мы использовали notepad, textedit, sublime - все, что попадало под руку, чтоб зафиксировать текст. Все это предсказуемо терялось, договоренности забывались. Преодолевать споры не помогали и письма в рабочую почту. Тогда я предложил своей команде использовать PlantUML для описания фичей, а именно стандартные Sequence и State диаграммы, которые позволяют сразу привести решение в порядок. В-третьих, никто не отменял разработку архитектурных и прочих фичей. Когда мы переделываем архитектуру, разбираемся, как все устроено, компонентные диаграммы очень сильно помогают. И, наконец, документация. Куда без нее. В PlantUML мы спокойно делаем инкремент, который можно вставить в любую систему документирования. Давайте посмотрим, как работает PlantUML на примере из продуктовой разработки. Допустим, мы создаем маркетплейс — продукт QMarket.  Каждый пользователь может завести деньги на счет в системе Каждый пользователь может выставлять товар в системе Система позволяет продавать, используя арбитраж Пользователи свободно могут выводить средства на карту В него можно заводить и выводить деньги, есть какой-то счет. В общем, стандартный пример, ничего нового. И есть команда, которая занимается процессингом платежей. Наша задача: подготовить флоу по отправке запросов на выплату. Вместо того, чтобы описывать задачу текстом, нарисуем диаграмму.  Участник — SPA (Single Page Application), в котором есть пользователи. SPA отправляет запрос. Блок онлайн процессинга создает Txn и отправляет ее в базу, база возвращает новую транзакцию в статусе Initial. В процессинге одна из самых частых проблем — как сделать так, чтобы один и тот же платеж не проводился дважды. Для этого используется идемпотентность. В запросе client payment request есть ключ идемпотентности. На схеме мы показываем, что если транзакция с таким Request ID уже есть, мы проверяем поля. Модуль онлайн процессинга проверяет идемпотентность. Если поля транзакции, которые должны совпадать, совпадают, то все хорошо, идем дальше. Если нет, выдаем ошибку, что запрос с таким Request ID существует. Затем мы спрашиваем у движка лимитов, можно ли провести транзакцию. Если лимиты превышены, мы должны зафиксировать это в статусе транзакции и выдать пользователю ошибку. При этом мы сохраняем транзакцию для дальнейшего разбора, когда, допустим, пользователь позвонит в клиентский сервис и решит разобраться с этой проблемой. Когда вопрос с лимитами разрешился, мы обновляем статус транзакции, отправляем One Time Password (OTP). SPA возвращает нам Confirmation ID, по которому рендерится форма ввода OTP. Мы обновляем статус на Waiting For SMS Confirmation и отправляем запрос.  На описание этой схемы я потратил больше времени, чем на ее непосредственную реализацию на PlantUML. С title все понятно, это заголовок диаграммы. Дальше идет описание участников. Actor spa это наш пользователь, participant — участник диаграммы — Market Database, Limits Service и SMS Service. Все остальное — отношения между этими сущностями.  Дальше — больше. Можно расписать статусы транзакций по флоу выплаты платежа. Для этого подойдет State диаграмма. Платеж уже создан, и есть два кейса: лимиты превышены или лимиты пройдены. Если лимиты превышены, мы идем в самый конец, в точку, где платеж не удалось выполнить. Если лимиты пройдены, то проверяем смс-подтверждение, получаем от пользователя OTP, и затем можно отправлять статус Ready To Sent в платежную систему. В платежной системе мы пытаемся создать платеж, и здесь тоже два кейса: платеж отклонен платежной системой или отправлен. После мы отправляем запрос в платежную систему о статусе, и ставим статус “платеж выплачен”.  Эту красивую диаграмму можно отдавать ребятам, занимающимся поддержкой кода, чтобы они могли создать SQL-запрос в базу и посмотреть, что да как с этим платежом. И еще пример разбора кода. Он менялся от ревью к ревью, и в него закралась ошибка.  Посмотрим на этот код в виде диаграммы. Офлайн-процессинг забирает из базы транзакции, ставит статус “отправлено в платежную систему” и только потом действительно отправляет. Если вдруг на втором шаге что-то случится с сервисом, который все это отправляет, транзакция зависнет. Мы будем считать, что транзакция отправлена в платежную систему, но на самом деле это не так. Ошибка, баг. Сложно было нарисовать схему? Нет, всего семь строчек. Параллельно с освоением PlantUML я наткнулся на архитектурную модель C4, включающую четыре уровня диаграмм. На первом уровне описывается система в целом, в масштабе ее взаимодействия с пользователями и другими системами. На втором уровне система разбивается на взаимосвязанные контейнеры. Контейнер — это исполняемая развернутая подсистема. На третьем уровне контейнеры разделяются на компоненты, отражаются связи между компонентами, контейнерами и другими системами. И, наконец, на четвертом уровне идут диаграммы кода — все те State и Sequence диаграммы, которые я только что показал. На что здесь обратить внимание? Пользователи, основные участники, основаны на абстракциях. Кроме названия, самого actor, есть еще описание, что он из себя представляет. Дальше видно, что контейнер “процессинг платежей” выделен синим. Появилась легенда: внешние системы, внешние пользователи, система. Эту диаграмму тоже можно отдавать в эксплуатацию. Берем набор шаблонов с Гитхаба. Можно использовать файлики, здесь ничего нового. Выбираем layout и legend. Обратите внимание, что если раньше мы использовали просто слова, здесь уже идут макросы, которые похожи на классы. Есть person, который мы назвали customer, и его описание. Система — processing. Внешние системы — это notifications, backoffice, paysystems и другие. После определения всех участников диаграммы мы продолжаем рассказывать про связи. Я решил заморочиться и нарисовать схему процессинга, который мы задумали в кейсе с маркетплейсом. Получилась большая динамическая диаграмма. В ней есть контейнер Online, который занимается онлайн приемом платежей, общается с пользователями. Контейнер Offline, который проводит сам платеж. Описывающая OLTP база данных и бэкофис, который занят реестрами, согласованиями, проверками. На этой диаграмме видны практически все потоки, вся архитектура. PlantUML это не только игрушка, позволяющая делать красивые диаграммы. Вы можете спокойно хранить свои диаграммы в CVS в каком-нибудь гите со спокойной совестью. Можете добавить ее в пайплайн, когда деплоите на прод. Если вы обновляете диаграмму у себя в документации, не нужно следить за тем, что документация устаревает. Если вы активно пользуетесь диаграммой и обновляете ее, новая версия тут же летит на сервер с документацией.  И наконец, PlantUML поддерживается почти всеми популярными IDE: JetBrains, Eclipse, VsCode, много их. И есть огромное количество плагинов.  https://github.com/fjfalcon/qsp6 - исходники статьи   https://plantuml.com/ - сайт с отличной документацией по PlantUML https://real-world-plantuml.com/ - сайт с примерами использования https://crashedmind.github.io/PlantUMLHitchhikersGuide/ - еще один хороший гайд про “как начать пользоваться” https://github.com/plantuml-stdlib/C4-PlantUML - использование plantuml и C4 model Для тех, кто любит формат видео — запись доклада. Разработчик