Представьте, что вы работаете в команде над крупным проектом какое-то время. Проект прошел начальный этап и уже работает в продакшн среде. Им пользуются люди, даже можно сказать, что им пользуются много людей и они рассчитывают на ваш продукт, он для них важен. С какого-то момента вдруг вами овладевает беспокойство, что что-то не так. Каждый спринт дается тяжело. Новые задачи вызывают проблемы с внедрением, а после релиза вы ловите один инцидент за другим. Каждый день вы со страхом смотрите в свой месенджер, боясь увидеть очередное сообщение с очередной проблемой, которую нужно срочно решать. Запросы к базе начинают тормозить, важная информация теряться, все валится из рук, контроль над ситуацией утекает как песок сквозь пальцы. Вы начинаете плохо спать, начинают снится кошмары о бесконечных сообщениях в очередях вашего брокера, которые воркеры не способны переварить. Вам снятся сервера, на которых заканчивается CPU и память, потому что сервисы безмерно потребляют ресурсы. Утилизация дисков на серверах с СУБД уже давно под 100%, ведь сервисы что-то постоянно с них читают или пишут. Ошибки, задержки, падения. Вы просыпаетесь.


Почему так произошло? Что пошло не так? Может мы плохо тестируем свой продукт? Может наше флоу не достаточно надежно и мы медленно/быстро (нужное подчеркнуть) катим изменения на прод? Может нам масштабировать количество серверов или распределить по другому ресурсы между ними? Или выбранная нами СУБД/брокер/язык/паттерн/алгоритм (нужное подчеркнуть) не подходит под наши задачи? Думаю, что что-то из этого или вообще все — точно не так. И дело не в том, что в моменте времени наши сервисы начинают плохо себя чувствовать, а в том, что мы не понимаем, почему. Не понимаем именно в критически важный момент. Нет места, где можно было бы это узнать или хотя бы начать искать. И хорошо, если на проекте еще есть люди, которые передают знания и опыт о проекте из уст в уста и в такой ситуации они действительно могут помочь. Ну, а если их нет? Вся описанная ситуация и называется "Архитектурой Шредингера".


Всем привет! Меня зовут Сергей и давайте по-подробнее разберемся, почему такое название и самое главное, что с этим делать?


Что такое "Архитектура Шредингера"?


Если вкратце — это тоже самое, что и кот Шредингера, только архитектура. Ну серьезно, я думаю все слышали о коте Шредингера. Дело в том, что в мысленном эксперименте Шредингера, не будем отвлекаться на физику, возникает суперпозиция живого и мертвого кота. Кот, как бы и жив и мертв одновременно. Звучит абсурдно, так ведь? С архитектурой Шредингера возникает таже история. Ведь посудите сами, когда у нас есть проект информационной системы (далее ИС), над которым мы работаем, который работает в продакшн среде, у него неминуемо есть какая-то архитектура. Он ведь как-то работает. Есть код, который ходит в СУБД, ИС обрабатываем запросы пользователей и даже что-то им отвечает. Делаем работу. Архитектура есть, но с другой стороны у нас нет никаких артефактов, описывающих архитектуру. Нет файлов, в которых было бы написано как что-либо работает. И я не говорю про документацию. Документация может ответить на вопрос, как ИС работает сейчас (есть даже вероятность, что это описание совпадает с реальностью), но она не может ответить на вопрос, почему так было сделано. А когда мы не знаем почему что-то было сделано, сложно понять, как те или иные изменения на проекте скажутся на нем. Что произойдет, если мы что-то поменяем? Получается, что архитектуры нет, ведь ее нельзя пощупать, полистать, почитать, понять или осознать мысли и идеи, заложенные в информационную систему создателем. Да и самого создателя получается нет. Некого спросить. Архитектуры нет.


Все, что имеет начало, имеет и конец, но это не точно.


Архитектура ИС существует независимо от того, занимается ли ей кто-то на проекте или нет. В современном мире разработки с такими методологиями как Agile и огромной кучей фреймворков, основанных на ней, команды разрабатывают короткими итерациями по факту не зная, что в конечном счете получат. Такой процесс гораздо более похож на процесс эволюции живого организма нежели, чем со строительством, скажем, здания или моста. В таком процессе разработки ИС развивается этапами, скачками и такой процесс отлично подходит под постоянно меняющийся внешний мир, меняющийся контекст развития ИС. Команда разработки быстро реагирует на изменения и вносит в систему необходимые правки, нужные, чтобы остаться на плаву. Зачем в таком процессе нам вообще думать об архитектуре, следовать каким-то принципам и шаблонам, да и еще следить за тем, чтобы они соблюдались? Может этот функционал и не потребуется в дальнейшем, возможно он и до продакшена не доберется или через пару итераций цикла разработки изменится до неузнаваемости. Конечно все так, НО (всегда есть "но", не правда ли?) к сожалению, есть один фактор, который все портит. Энтропия. Энтропия — это хаос, к которому стремится любой живой организм, к нему стремится и разрабатываемая информационная система. Каждый спринт, каждый новый функционал добавляет немного хаоса, а чем больше хаоса в проекте, тем ближе он к закрытию. Есть отличная цитата самого Эрвина Шрёдингера, вырванная из контекста его замечательной книжки "Что такое жизнь?", которая применима не только к живым организмам, но и к процессу разработки ИС.


Живой организм непрерывно повышает свою энтропию – или, можно сказать, производит положительную энтропию, – тем самым стремясь к опасному состоянию максимальной энтропии, то есть смерти…

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


Жизненный цикл.


У любого живого организма, а мы уже разобрались, что процесс разработки ИС схож с развитием или эволюцией живого организма, есть свой жизненный цикл. Жизнь зарождается, растет, проходит свой рассвет, затем начинает увядать и в конечном счете неминуемо умирает. Несмотря на схожесть, развитие ИС, в своем цикле, имеет значимое отличие. К слову, такое же значимое отличие имеет знаменитый жизненный цикл органазации, разработанный Ицхаком Адизесом аж в 1988 году. По Адизесу, организация проходит целых 10 этапов своего существования и на каждом этапе люди, управляющие организацией, должны не допустить ошибки или не попасть в определенные ловушки, которые могут привести организацию к закрытию.


Жизненный цикл по Адизесу


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


Важные этапы жизненного цикла ИС


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


Начальный этап


Это этап, на котором мы только начинаем проектировать, анализировать, разработывать. У нас еще нет реальных пользователей и боевой среды, но есть много этузиазма и соответственно хаоса. Нет фундамента, поскольку этот фундамент должны заложить именно на этом этапе. От принципов, которых мы будем придерживаться, до множества различных важных технических деталей, например, настройка ci/cd или выбора методологии ветвления на проекте. Банально от какой ветки мы будем создавать ветку с фичей и как и по каким правилам будем мержить? Все это очень важно с одной стороны и в этом огромное количество хаоса с другой. Крайне важный этап, на котором очень просто заруинить проект. На мой взгляд, тут нам следует сразу очертить определенные рамки для хаоса. Не убрать хаос, на данном этапе это невозможно, а очертить границы, за которые он не должен выходить. Задать рамки, в которых он будет существовать.


Постпродакшн


Введем немного киношной терминологии. Этот этап знаменует выход нашего проекта в реальную среду обитания с реальными пользователями, факапами, простоями и прочими "занимательными" вещами. Если продолжать киношную тему, то есть сравнивая этот этап с жанрами в кино, можно прийти к странной смеси ужасов и комедии. На этом этапе, как вы уже наверное догадались, начинается реальная эксплуатация разрабатываемой нами ИС. Хаос, который приходит на этом этапе, характерен финансовыми потерями. Каждый недовольный пользователь, который не смог оформить заказ или лежащий продакшн, не выдержавший нагрузки после рассылки, долгие ответы от api или покосившийся фронт после неосторожного ресайза окна браузера, все это — потеря денег. Этот этап покажет все ошибки предыдущего и все, что он покажет, придется исправлять, при этом не забывая добавлять новых фишек. Очень важно обуздать этот хаос, который получил дополнительную энергию от страха бизнеса, расстаться со своими деньгами. На этом этапе этот страх играет главенствующую роль.


Эндгейм


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


Жизненный цикл ИС


Для визуализации жизненного цикла ИС я нарисовал такую картинку, со стилизацией под flow-диаграмму. Знаки "?", на диаграмме, обозначают некую проверку на размер накопленной энтропии. Если накопленное количество энтропии выше определенного максимального значения (думаю для каждого проекта оно свое), мы просто не можем перейти на следующий этап и это ведет к остановке разработки ИС. При этом энтропия, очевидно, накапливается и никуда не сбрасывается.


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


Стадия 1. "Начальный этап"


Архитектура как код


Один из самых важных принципов, котрый сдерживает хаос первого и последующих этапов жизненного цикла разработки — это "Архитектура как код". В первую очередь, это означает, что мы храним архитектурные артефакты (описание взаимодействия сервисов, диаграммы и схемы) вместе с кодом. Точнее, даже можно сказать, что мы храним код в том-же месте, что и архитектуру решения и лучшее место для этого — репозиторий проекта. Почему это сдерживает хаос? По многим причинам. Самая простая — это то, что нам не нужна куча сторонних сервисов, чтобы рисовать диаграммы или хранить описание реализации. Каждый хочет использовать что-то свое. Давайте рисовать в lucidchart или в draw.io или в visio и хранить эти артефакты в своих учетках или вообще локально. Кто потом узнает, где все это лежит и как получить к этому доступ? Пройдет время и вы не найдете ничего. Это энтропия, разрушающая проект. Код — это имплементация архитектуры и лучшее место его хранения вместе с первоисточником. На данный момент у нас есть много инструментов для реализации этой идеи. Описывать работу сервисом можно с помощью markdown файлов. Markdown — это очень крутой и легковестный язык разметки. Диаграммы и схемы мы можем рисовать с помощью языка plantuml. PlantUML позволяет описывать большое количество различных схем и диаграмм текстом, а затем рендерить описание в визуальное представление. Для описания структур данных можно использовать JSON Schema, поскольку это отличный формат для валидации данных. Можно даже представить себе вариант переиспользования написанных схем данных в дальнейшем для непосредственной валидации данных, импортировав схему прямо из каталога архитектурных артефактов проекта! Фактически с помощью только трех этих инструментов можно организовать хранение всех артефактов архитектуры в репозитории с кодом, а значит ретранслировать все привычные процессы разработки и на архитектуру тоже. Очень удобно. Мы хотим реализовать новую фичу на проекте, делаем новыую фичу-ветку, описываем то, что хотим реализовать в markdown файлах, пишем несколько sequence-диаграмм, рисуем ER диаграмму, описываем структуры данных в json schem'ах, делаем пуш в ветки и кидаем МР на команду. По-моему, это сильно снижает энтропию. Для наших проектов структура такого каталога с артефактами выглядит так.


.
└── Your git repository/
    └── architecture/
        ├── docs/
        │   ├── index.md
        │   ├── *.md
        │   └── ...
        ├── decisions/
        │   ├── index.md
        │   ├── *.md
        │   └── ...
        ├── diagrams/
        │   ├── C4/
        │   │   ├── Components/
        │   │   │   ├── *.puml
        │   │   │   └── ...
        │   │   ├── context.puml
        │   │   └── container.puml
        │   ├── img/
        │   │   ├── *.png
        │   │   └── ...
        │   ├── *.puml
        │   └── ...
        └── schemas/
            ├── *.schema.json
            └── ...

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


Глоссарий


Это уже не принцип, а реальный артефакт, который, как мы выяснили из предвдущего инструмента, лучше хранить в репозитории в markdown файле. Глоссарий — это справочник, в который записываются основные термины в контексте проекта и даются однозначные определения. Крайне полезный артефакт, причем начинать вести глоссарий необходимо прямо в самом начале работы над проектом. Глоссарий нужен для того, чтобы составить словарь терминов, которые однозначно понимают все участники процесса разработки. Бизнес, программисты, аналитики, менеджеры, все. Если в ИС есть пользователи, то все должны однозначно понимать, что скрывается за этим термином. Глоссарий помогает с течением времени перейти всем участникам команды на единый язык общения, исключить путаницу в формулировках. Без этого единого языка можно провести часовой митинг, зафиксировать все решения по реализации и потом на выходе получить не то, что ожидалось только лишь потому, что каждый участник этого процесса понимал под термином "Пользователь", что-то свое. Например, на одном из наших проектов, в котором нет глоссария, термин "Таска" у разных людей может означать три разные и, можно сказать, противоположные сущности. Глоссарий поможет справится с этой разновидностью хаоса.


Модель C4


Это еще один артефакт, который стоит сразу начинать развивать с самых первых шагов на проекте. С4 модель — это простой набор диаграмм, помогающий рассмотреть архитектуру решения на 4 разных уровнях представления. Каждый уровень модели С4 представляет систему на определенном уровне приближения. И это очень удобно. На первом, контекстном уровне, мы видим систему, как что-то монолитное, как единый блок, а вокруг этого монолита изображены внешние системы, с которыми мы взаимодействуем, но на которые не можем на прямую воздействовать. Этот уровень помогает очертить границы разрабатываемой ИС. На втором уровне мы зумим систему и ИС разделяется на блоки, из которых она состоит. Эти блоки называются контейнерами, а сама диаграмма — контейнерной диаграммой. Эти контейнеры могут быть сервисами, СУБД или брокерами сообщений. Любые крупные элементы системы, которые взаимодействуют друг с другом. На этом уровне можно расписать все используемые технологии. В этом сервисе используется Node.js, а тут Golang, также вот тут есть PostgreSQL и это все связывает RabbitMQ. На этом уроне можно рассмотреть поближе, из чего состоит монолит, который был на контекстной диаграмме. Далее мы можем спуститься ниже и зазумить уже конкретный контейнер и перейти на уровень компонентной диаграммы, а затем приблизить компонент и перейти на уровень кода. Не будем вдаваться тут в подробности, думаю, основная идея этого артефакта понятна. Подробнее о С4 модели можно почитать на официальном сайт. Актуальная С4 модель проекта рассеивает хаос и сохраняет всем нервные клетки. Рисуем ее мы, естественно, с помощью PlantUML и храним вместе с кодом. В качестве примера, чтобы ощутить всю мощь сочетания инструментов по борьбе с хаосом, можно скопировать вот эту простенькую контекстную диаграмму и вставить ее в этот онлайн редактор.


@startuml C4_Context
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml

LAYOUT_WITH_LEGEND()

Person(employee, "Сотрудник", "Сотрудник")
Person(client, "Клиент", "Клиент")
Person(externalIS, "Внешняя ИС", "Внешняя ИС")

System(platform, "Наша ИС", "Набор сервисов")

System_Ext(erp, "Учетная система", "Учетная система")
System_Ext(ftp, "Файловый сервер", "FTP")

BiRel(platform, erp, "Используют", "Файлы")
Rel(platform, ftp, "Используют", "ftp")
Rel(employee, platform, "Используют", "http")
Rel(client, platform, "Используют", "http")
Rel(externalIS, platform, "Используют", "http")

@enduml

Бритва Оккама


Очень важный методологический принцип в начале проекта. Я не буду давать тут классических определений, для этого существует википедия. Этот принцип говорит о том, что мы не должны делать то, что не требуется. Должны фокусироваться на действительно важных вещах, которые требуется сделать на конкретном этапе разработки. В самом начале проекта важно фокусироваться на ядре будущей ИС, на том, что наделяет ее ценностью для бизнеса. Все остальное — лишнее и ненужное. Если мы делаем социальную сеть, для примера, то первые строчки кода должны реализовывать логику пользователя и его взаимодействия с другими пользователями посредством сообщений или постов. Совершенно не важно сейчас, как и где мы будем хранить этих пользователей, как рассылать уведомления или менять дизайн странички, нам нужно реализовать сам объект пользователя, дать ему возможность написать сообщение и добавить другого пользователя в друзья — это основной смысл социальной сети, все остальное не имеет смысла без ядра и поэтому отсекается бритвой Окамма. Отражение этого замечательного метода есть во многих принципах программирования, таких как KISS, YAGNI ну и самое знаменитое, это, конечно, "Преждевременная оптимизация — корень всех бед" Дональда Кнута.


Стадия 2. "Постпродакшн"


Если мы все еще на плаву после первой стадии разработки, мы неменуемо переходим во вторую и у нашей ИС появляются реальные пользователи. Мы начинаем обслуживать запросы и от того, как мы это делаем, зависит, сможет ли наша разработка выжить на стадии постпродакшна. Энтропия второй стадии отличается от хаоса первой стадии тем, что мы уже не можем так легко менять уже работающую логику. Мы должны поддерживать совместимость. Если мы ошиблись на первой стадии, то на второй мы должны крепко подумать прежде, чем что-то менять и при этом цена ошибки возрастает кратно. Чтобы остаться на плаву, мы должны исправить ошибки первой стадии, не поломать то, что работает и постоянно внедрять новый или расширять существующий функционал ИС под гнетом бизнеса. Чтобы не утонуть в этом бушующем море энтропии постпродакшена, нам определенно нужны инструменты для борьбы с ней. Приведу комплект нашего EDC-набора выживальщика на этой стадии.


Метрики и логи. SLI, SLO и немного процессов.


После появления реальных пользователей нам никак нельзя оставаться слепыми. Нужно видеть, что происходит с системой, как в реальном времени, так и в определенных временных окнах. Система мониторинга и логи дают возможность не только узнавать о проблемах постфактум, но и прогнозировать появление проблем в будущем, что открывает огромные возможности по привентивным действиям. Что нужно в первую очередь? В первую очередь нужен сбор логов по каждому запросу к API. Мы получили запрос от пользователя, отработали его, вернули ответ и записали в логи. Хороший вариант делать это с помощью Graylog. Грейлог использует под капотом ElasticSearch, а это заначит, что в дальнейшем можно легко делать различные агрегации по записанным логам. Интерфейс Graylog'a это позволяет, но можно подключить и Grafana. Минимальный набор полей для записи в лог — это:


  1. URI запроса
  2. Код ответа
  3. Время овтета на запрос

Зачем нам это нужно? Чтобы считать разные полезные SLI! SLI — это определенный индикатор уровня обслуживания клиентов ИС. Из всего 3х метрик по каждому запросу, можно получить следующие полезные индикаторы, например:


  1. Среднее время ответа по каждому маршурут API
  2. Процент ошибок, который вернул API относительно общего количества запрсоов
  3. Абсолютное количество ошибок по кодам ошибок
  4. Топ самых медленных маршрутов
  5. Топ маршрутов, у которых самый высокий процент ошибок
  6. Топ самых нагруженных маршрутов
  7. Количество запросов в секунду (RPS) в целом или по каждому маршруту
  8. Процент или по времени ответа в целом, или по каждому маршруту

Сбрасывая всего три метрики в логи, мы можем получать на их основе огромное количество различных индикаторов на разных временных окнах. И это только те индикаторы, которые потребуются в первую очередь, а можно собирать и немного больше метрик. Можно настроить оперативный дашборд на временном окне в последние 5 минут и быть в курсе, что происходит с ИС "вот прям сейчас". Узнавать о проблемах быстрее, чем в вашу службу поступит первый звонок разъяренного пользователя, а может и успеть устранить проблему, пока никто и не заметил. Конечно, это очень полезно и сдерживает хаос, открывает вам глаза, но можно сделать больше. Просто имея индикаторы, нельзя ставить цели, становиться лучше. Нужны конкретные цели, на которые можно ориентироваться, и у них есть название SLO. SLO — это цель для определенного SLI. Например, мы хотим, чтобы процент положительных ответов на маршрут получения пользователей за неделю был 99,995% а по итогам недели мы получили 99,98%. Это говорит о том, что маршурт получения пользователей выдавал ошибок больше, чем мы ожидали. Это плохо, нужно разбираться. Все это определенный процесс проверки работающей ИС, оценки ее качества. Осталась ли она в тех рамках после последних внедреннных функций или сползла в пучину хаоса? С помощью этого процесса мы сможем это увидеть и принять меры. Остается только еще одна проблема, более абстрактного характера. Как конкретно это должно происходить? Мы собрали логи и посчитали SLI, придумали SLO — что дальше? На мой взгляд, лучше всего собираться вместе с командой в одном митинге и обсуждать полученные индикаторы за недельное окно и сравнивать их с SLO. У нас эти митинги проходят по понедельникам и называются "Встреча по качеству". Это полезный процесс и его важно проводить. Можно выбирать разные временные окна, в которых будут считаться разные SLI, и выбирать разные SLO, приемлеммые для вас, проводить "Встречи по качеству" раз в месяц или каждый день. Все это можно гибко настраить под потребности любой команды. Собрать свой джедайский меч для борьбы с хаосом на стадии постпродакшена, как и делает любой уважающий себя джедай.


Post mortem


В любой ИС, а в особенности в той, которая находится на поспродакшене, будут сбои. Причем как мелкие, так и жуткие. По разным причинам. Думаю, это стоит просто принять. После глубокого вздоха и сразу после перехода в последнюю стадию "принятия", важно разобраться в причинах сбоя. В причинах каждого конкретного сбоя. Для этого и существует такой артефакт, как Post mortem. Вообще говоря, название этого артефакта пошло от достаточно жуткой штуки. Посмертной фотографии. Одно время было принято делать последний снимок уже умершего человека и затем конструировать целые альбомы из таких фотографий. Этим мы и займемся. Под термином Post motrtem в контексте ИC скрывается описание сбоя и причин этого сбоя. Этот документ составляется посфактум. Описывается в определенном формате и состоит из следующих разделов. Последовательность событий, приведшая к сбою, сам сбой, его последствия, решения команды, принятые для восстановления ИС и самое главное решение, принятое после сбоя, которое описывает шаги по недопущению подобных сбоев в будущем. Следуя принципу "Архитектура как код", писать Post mortem'ы необходимо в markdown файлах и хранить вместе с кодом в репозитории. Каждый участник команды, у которого есть доступ в репозиторий, сможет зайти и почитать, как команда мужественно сражалась с хаосом, который приносил с собой каждый сбой. Post mortem — это системный способ борьбы с инфидентами и средство распространения знаний о самой ИС, ее слабых местах. Когда следует писать Post mortem? Для нас это следующие триггеры:


  1. Был допущен Down time
  2. Потеряли данные
  3. Не вписались в SLO

Для себя мы выбрали следующий формат этого артефакта


# Title

## Issue Summary

## Timeline

## Root Cause

## Resolution and recovery

## Corrective and Preventative Measures

ADR


Еще один артефакт, привносящий порядок в противовес энтропии постпродакшена — это ADR. ADR расшифровывается как Architecture Decision Record. Простыми словами — это некий принятый командой формат, в котором будет описана проблема или новая функциональность вместе с описанием нескольких вариантов ее решения, если, конечно, есть несколько действительно хороших решений. Затем описывается принятое решение с пояснениями, почему именно оно было принято, и детально описываются изменения, которые мы вносим в нашу архитектуру. Крайне полезный артефакт, который отвечает на вопрос "Почему было так сделано?". Каждый ADR — это не только словесное описание доработок, которые нужно внести в ИС, но и схемы и структуры данных. По принципу "Архитектура как код" для схем используется PlantUML, а для описания структур данных — JSON schema. Для себя мы выбрали формат MADR. Этот шаблон как раз создан для разметки markdown. В этом формате описания внесения правок в архитектуру есть следующие разделы, каждый из которых является опциональным, что придает этому формату отличную гибкость.


## Context and Problem Statement

{...}

## Decision Drivers

## Considered Options

* {title of option 1}
* {title of option 2}
* {title of option 3}

## Decision Outcome

### Consequences

## Pros and Cons of the Options

### {title of option 1}

* Good, because {argument a}
* Good, because {argument b}
* Bad, because {argument d}

## Links

Подробнее про этот и многие другие шаблоны ADR, а также посмотреть примеры можно тут.


Рефакторинг. Начало.


Рефакторинг — это не просто рекомедованный инструмент, который следует применять, а самый что ни на есть обязательный. На данный момент методология Agile является де факто общепризнанным стандартом, применяемым при разработке программных продуктов. Но что было до Agile? Дело в том, что до Agile была такая методология, созданная Кентом Беком, как "Экстримальное программирование". Agile впитал в себя многое из эекстримального программирования. Одним из краеуголных принципов экстримального программирования, заложенных в его фундамент, был рефакторинг. Это справедливо и для Agile. Разработка по гибким методологиям способствует быстрому накоплению техничиеского долга, а технический долг, это ни что иное как энтропия. Тут у нас метод, который уже не используется, а тут мы делаем запрос в СУБД с помощью запроса, на который без слез не взглянешь, а вот в этом методе, как вишенка на торте, циклическая зависимость от другого метода. Хаос в чистом виде. Лекарство есть и это рефакторинг. Если на первой стадии необходимо было быстро разработать продукт и запустить его, то на стадии поспродакшена идет расплата за скорость накопленным техническим долгом. На второй стадии мы еще не можем полноценно приступить к переработке и оптимизации, просто нет на это времени, нужно внедрять новые фичи, но начать точно стоит. Первое, что нужно сделть, это начать готовить бизнес к необходимости рефакторинга, поскольку бизнес не любит и не хочет выделять время, а значит и деньги, на рефакторинг. Следует методично убеждать его в обратном и в конечном счете придумать процесс, по которому можно будет осуществлять рефакторинг в дальнейшем. Для нас — это стал бюджет на рефакторинг в каждом спринте на определенную сумму в абстрактных баллах. Например, на спринт выделенно 10 баллов на рефакторинг. В пуле задач на рефакторинг есть 5 задач разной стоимости в баллах. Сколько стоит каждая задача — оценивает разработчик. Чем сложнее задача, тем больше она займет времени и соответственно, тем дороже она будет оценена. Для нас градация выглядит так. 1 балл — легкая задача, 3 балла — средняя, 5 баллов — тяжелая. При бюджете в 10 баллов на спринт мы можем взять 2 легких задачи, одну среднюю и одну тяжелую. Сами задачи на рефакторинг добавляют в пул задач и оценивают по сложности сами разработчики. Бизнес только выделяет под это время в спринте. После внедрения этого процесса остается лишь правильно осваивать бюджеты.


Стадия 3. Эндгейм


Если вы добрались до этой стадии, вас можно только поздравить. Вы — молодцы! Но не стоит расслабляться, хаос этой стадии не похож на предыдущий и если сильно расслабиться, он быстро поглотит проект. Отличия хаоса этого этапа разработки от предыдущих, кроется в названии. Название "Эндгейм" позаимствовано у геймеров и обозначает оно игровой процесс, который начинается после того, как игра пройдена и главный босс повержен, если конечно сама игра к этому располагает. А чем занимается геймер, который прошел игру, но перестать в нее играть не хочет? Правильно, занимается разной ерундой. Пытается развлечь себя различными челенжами. Основная игра пройдена, финальные боссы повержены, основное напряжение спало, но самому геймеру хочется большего. На этой стадии заскучавшим разработчикам, так же, как и геймерам, прошедшим игру, хочется челенджей и если их нет от бизнеса, они начинают придумывать их сами. Например, захотеть попробовать внедрить новую зависимость в проект, с которой давно хотелось разобраться, и вжух у вас на проекте +1 зависимость. Или захотелось написать новый функционал в каком-нибудь своем стиле, которого нет на проекте. Давайте напишем один из новых сервисов на golang с grpc интерфейсом? Почему нет? Или часть api переведем на graphql. Внедряются новые практики, увеличивается пул зависимостей и энтропия растет. Сложность проекта растет. Нужно бороться.


Сложности кодовой базы


На финальной стадии проекта важно отслеживать сложность кода. Если на первых стадиях при активной разработки продукта в угоду скорости выпуска новых фичь можно закрыть глаза на переусложненный код на эндгейме, самое время заняться рефакторингом и упрощением. Почему это важно? Важно это потому, что команда, разрабатывающая ИС изначально, будет постепенно меняться, будет происходить ротация. Многие, кто толкал проект вперед на первых двух стадиях, уйдут в новые проекты, ведь на эндгейме уже нет того драйва, нет челенджей. Будут приходить новые люди, команда будет ротироваться, а это значит, что очень важно, чтобы новые разработчики максимально быстро вникали в продукт. Сложный и непонятный код будет этому только мешать. На мой взгляд, лучше всего для отслеживания сложности кода использовать такую метрику, как "Когнитивная сложность". Не буду описывать, как именно рассчитывается этот показатель, для этого лучше посмотреть рассказ самого создателя вот в этом виде. В нем нет ничего сложного. Лучше всего измерять этот показатель с помощью SonarQube, ведь компания SonarSource, которая создала этот инструмент статического анализа кода, разработала и саму метрику. Отслеживать этот показатель удобно на "Митинге по качеству" и за счет большой доли рефакторинга и снижения количества нового функционала ИС на стадии эндгейма, сложность кодовой базы должна падать.


Единообразие стиля


Как я уже писал на стадии эндгейма разработчикам, привыкшим к бурной деятельности на проекте, сложно привыкнуть к размеренному темпу финальной стадии развития ИС. За счет этого возникает острое желание внедрить в проект что-то новое без необходимости по надуманным причинам. Даже написание нового функционала в новом для проекта стиле увеличивает хаос и снижает время эксплуатации ИС. Что уж говорить о внедренных новых технологиях и зависимостях по причине банальной скуки. Все это повышает порог входа в проект для новых разработчиков. Лишает проект лица. Размывает его. Для отслеживания такой метрики как "Единообразие", на мой взгляд, отлично подходит подход, когда пишется скрипт генерации компонентной диаграммы С4 на основе кода. Сложность этого скрипта описывает и единообразие кода. Если скрипт получился небольшим, легким и понятным, код ИС написан в хорошем едином стиле. Если скрипт получился сложным и большим, единообразие кода страдает. Получив эту информацию, можно направить свои усилия на переработку тех участков проекта, из-за которых код скрипта стал больше и сложнее. Исправив эти выделяющиеся кусочки проекта, скрипт генерации станет проще, а соответственно и код станет белее единнобразынам, что снизит порог входа. Попробуйте, возможно вам зайдет этот метод. Мне зашел.


Зависимости


Продолжая тему пагубного новаторства на стадии эндгейма, не могу не упомянуть про зависимости. С одной стороны, зависимости — это переиспользование кода. Зачем писать что-то самому, когда уже кто-то написал за тебя? На начальных этапах развития проекта это может сильно сократить время разработки и прототипирование нового функционала. На стадии эндгейма все зависимости, добавленные в проект на предыдущих стадиях и не являющиеся объективно необходимыми, должны быть убраны или заменены на собственные решения. В первую очередь, я конечно говорю про зависимости, разрабатываемые энтузиастами. Почему? Думаю для ответа на этот вопрос лучше всего представить просто любого случайного человека, которого вы не знаете. Со своими проблемами, заботами и детскими травмами. Представили? А теперь представьте, что от этого человека зависит ваше благополучие и благополучие ваших родных. Будет ли все хорошо у вас, зависит от того, встал ли этот человек сегодня с той ноги. Так себе картина. Хорошим шагом, на мой взгляд, на стадии эндгейма будет провести аудит всех зависимостей проекта и избавиться от лишнего. Кроме этого, каждая новая зависимость, добавленная разработчком на этой стадии, должна проходить этап анализа и оценки необходимости ее использования. Добавить новую библиотеку в проект гораздо проще, чем потом ее убрать. На стадии эндгейма нет большой пользы от добавления новой зависимости, а минусов при этом достаточно.

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


  1. dyadyaSerezha
    30.12.2022 06:04

    Все хорошо, но...

    Живой организм непрерывно повышает свою энтропию – или, можно сказать, производит положительную энтропию, – тем самым стремясь к опасному состоянию максимальной энтропии, то есть смерти…

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