Software architecture as code — A way to bridge the gap between architecture and code
Software architecture diagrams are among the most commonly shared assets within software development teams. Some are hand-written collections of boxes and lines on a whiteboard, others are more-advanced like Microsoft Visio-style block diagrams on a Wiki. Unfortunately, due to various reasons during the project implementation, many of these diagrams can easily become out-of-date and abstract, which can lead to misalignment between the architecture of the system and the actual code. And we all know how important is to have accurate and updated documentation of the solution that you are working on, at any point in time.
The diagram below is an example of an insurance modernisation project where an engineering team is responsible for example, for modernising the risk rating engine by breaking down a monolith process (app) and introducing the cloud-native micro-services. As you can imagine, moving this implementation forward, some changes may be inevitable and even though they may be well-designed and implemented, there may be gaps in reflecting them in this diagram, which will negatively impact the quality of implementation, maintainability of the solution, deployment across multiple environments etc.
To address this challenge, the software development community has been exploring ways to create architecture diagrams that are more accurate, up-to-date, and integrated with the codebase. One approach that has gained popularity in recent years is to use tooling that generates architecture diagrams from the actual code, often referred to as “living” or “executable” architecture diagrams. By generating the diagrams from the code, these tools ensure that the diagrams are always up-to-date and accurate, reflecting the current state of the system. Additionally, these diagrams can help to improve the overall quality of the codebase by highlighting areas of the system that may be overly complex or tightly coupled.
One of the tools, which is very top on my list is definitely the Structurizr. With this tool, from a single model, you may create multiple diagrams, which is very powerful.
The procedure for your software architecture code is then pretty much similar to your application and/ or infrastructure code — you can store them in your code repository, make changes and track various versions during your implementation. Below, you may have a look at the code sample for the insurance risk rating module diagram from above.
workspace
!identifiers hierarchical
model user = person "Insurance Broker"
softwareSystem = softwareSystem "Software System"
webapp = container "Premium Rating Portal"
service1 = group "Service 1" service1Api = container "Service 1 API" tags "Service 1" "Service API"
>
container "Service 1 Database" tags "Service 1" "Database"
service1Api -> this "Reads from and writes to"
>
>
service2 = group "Service 2" service2Api = container "Service 2 API" tags "Service 2" "Service API"
>
container "Service 2 Database" tags "Service 2" "Database"
service2Api -> this "Reads from and writes to"
>
>
service3 = group "Service 3" service3Api = container "Service 3 API" tags "Service 3" "Service API"
>
container "Service 3 Database" tags "Service 3" "Database"
service3Api -> this "Reads from and writes to"
>
>
service4 = group "Service 4" service4Api = container "Service 4 API" tags "Service 4" "Service API"
>
container "Service 4 Database" tags "Service 4" "Database"
service4Api -> this "Reads from and writes to"
>
>
service5 = group "Service 5" service5Api = container "Service 5 API" tags "Service 5" "Service API"
>
container "Service 5 Database" tags "Service 5" "Database"
service5Api -> this "Reads from and writes to"
>
>
service6 = group "Service 6" service6Api = container "Service 6 API" tags "Service 6" "Service API"
>
container "Service 6 Database" tags "Service 6" "Database"
service6Api -> this "Reads from and writes to"
>
>
service7 = group "Service 7" service7Api = container "Service 7 API" tags "Service 7" "Service API"
>
container "Service 7 Database" tags "Service 7" "Database"
service7Api -> this "Reads from and writes to"
>
>
service8 = group "Service 8" service8Api = container "Service 8 API" tags "Service 8" "Service API"
>
container "Service 8 Database" tags "Service 8" "Database"
service8Api -> this "Reads from and writes to"
>
>
user -> webapp
webapp -> service1Api
service1Api -> service2Api
service1Api -> service3Api
service2Api -> service4Api
service2Api -> service5Api
webapp -> service3Api
service3Api -> service4Api
service3Api -> service7Api
service4Api -> service6Api
service7Api -> service8Api
>
>
views container softwareSystem "Containers_All" include *
autolayout
>
container softwareSystem "Containers_Service1" include ->softwareSystem.service1->
autolayout
>
container softwareSystem "Containers_Service2" include ->softwareSystem.service2->
autolayout
>
container softwareSystem "Containers_Service3" include ->softwareSystem.service3->
autolayout
>
styles element "Person" shape Person
>
element "Service API" shape hexagon
>
element "Database" shape cylinder
>
element "Service 1" background #91F0AE
>
element "Service 2" background #EDF08C
>
element "Service 3" background #8CD0F0
>
element "Service 4" background #F08CA4
>
element "Service 5" background #FFAC33
>
element "Service 6" background #DD8BFE
>
element "Service 7" background #89ACFF
>
element "Service 8" background #FDA9F4
>
>
>
>
Overall, the use of executable architecture diagrams can help to bridge the gap between architecture and code, making it easier for teams to understand and maintain the architecture of complex software systems. In this post, I presented you with one tool that you may consider, but you may consider others such as PlantUML, Diagrams, etc.
Архитектура как кот VS Архитектура как кол
Есть еще путь — изменить саму среду. Но что-то мне подсказывает, что это путь “в один конец”. Проходя его, идеи и цели трансформируются.
Но есть и более глобальные ограничения. Можно сказать — фундаментальные. К таким ограничениям я отношу память, опыт, знания и время. Рамки некоторых ограничений можно раздвигать. Обучаясь, тренируясь, накапливая опыт. Но они будут оставаться с тобой всегда. А вот время.
Работа архитектором в Работа.ру я, непосредственно, проектирую две крупные системы. Также я выполняю роль корпоративного архитектора. Как вы думаете, меня хватает на все? Конечно нет.
У нас много команд. Они каждый день что-то пилят. Что-то катят. Описать происходящие можно вариацией известного анекдота: пока архитектор изучает наш ИТ ландшафт, мы его меняем.
Если задуматься, больше сотни людей, каждый день прокачивают свои навыки. Накапливают опыт. Пытаются затащить новые технологии. И если я буду пытаться все это возглавить, я автоматически стану “узким местом” для развития компании.
Больше архитекторов? Решение интересное, но бесперспективное. Дело в том, что нарушается Agile Manifesto. Команда теряет автономность. Возникают ограничения ее эффективности.
Пожалуй, идеальным решением может быть внедрение в каждую команду по одному архитектору. Но что он там будет делать 8 часов 5 дней в неделю? Для команды выделенная роль архитектора в подавляющем большинстве случаев избыточна. И архитектора обязательно чем-то донагрузят.
Но, стоп! Ведь команды прямо сейчас что-то пилят. Т.е. прямо сейчас они реализуют архитектурные решения. Получается, незримый архитектор есть в каждой команде. Он может концентрироваться в лиде или быть размазанным по всей команде. Он может быть плохим или хорошим. Но главное — он есть.
И мы задумались… а можно ли как-то использовать интеллектуальный потенциал команд консолидированно? Создать не просто успешные команды, а развить положительную синергию их деятельности. Первым шагом для нас стала версия DocHub, пропагандирующая принцип contract-first.
Настроив процессы развития контрактов через GitFlow, мы заметно расширили свои возможности. Теперь, каждая команда, не ожидая архитектора, может развивать контракты. При этом управляемость не ухудшилась, а улучшилась. Я стал выполнять роль ревьювера контрактов. Архитектора стало “больше”.
Вдохновленные этой историей, мы пошли дальше. DocHub позволил решить ряд проблем. Но далеко не все. Осталась главная проблема — целевое развитие архитектуры. Т.е. достижение командами состояния, отраженного в архитектуре — как будет.
Была проделана работа по анализу существующих инструментов, которые могли бы подойти нам. Ключевой идеей сразу стало развитии архитектуры через код. На горизонте забрезжил PlantUML.
Но есть проблема. Каждый раз, когда мы рассматриваем язык описания архитектуры, мы тут же упираемся в необходимость его знать. И, автоматически, поднимаем требования к нашим разработчикам. В воображении рисуется Уроборос (змея, кусающая себя за хвост).
Как известно, проблемы не приходят поодиночке. Допустим, мы заставим разработчиков выучить PlantUML. И даже заставим их вносить изменения в файлы, описывающие архитектуру. Но как это все собирать в кучу со всех команд? Как рендерить? В конфлюенсе?
И вот, наш бедный разработчик теперь должен писать что-то на PlantUML, в конфлюенсе. Пришли к тому, что было. Даже хуже. Нарастили ограничения.
Думаю, интригу я нагнал достаточно. Пора познакомить вас с новым DocHub. Теперь это инструмент управления архитектурой через код. Он должен значительно снизить наши ограничения. Позволить командам видеть весь актуальный ландшафт. А это, в свою очередь, приведет к той заветной положительной синергии.
Управление версиями архитектуры
В развивающихся проектах архитектура мутабельна. Стандартной ситуацией является одновременная проработка нескольких архитектурных решений, которые должны стать единым целым. Особенно явно эта проблема выражается при наличии нескольких автономных команд, создающих единую систему.
Для монокомандых систем проблема остается актуальной. Внезапное изменение приоритетов и требований приводит к накоплению противоречивых архитектурных решений. Формируется технический долг.
Аналогичные проблемы свойственны кодовой базе систем. В процессе параллельной разработки фич, разработчики сталкиваются с задачей объединения результата в релизы. Решается она через инкрементальное развитие кода. Популярным инструментом является git.
Если внезапно забыл как работать с гитом.
Практикуются различные методологии управления кодом. Из популярных можно выделить GitFlow и GitHub flow.
Идея заключается в том, что разработчик при создании новой фичи клонирует ветку (branch) общей кодовой базы в отдельную. В ней он ведет разработку. По завершению работы создается Pull request / Merge request. Это специальный, формализованный запрос в рамках системы управления версиями на объединение веток. Он оценивается (Code review) другими разработчиками. В случае положительного решения, изменения внедряются в общий код.
Решать запросы на объединение помогают инструменты сравнения, встроенные в системы управления версиями. Они наглядно отражают изменения в коде. Выявляют конфликты. Позволяют их устранять.
В отличие от процесса разработки, где все построено на коде, архитектура требует создания графических артефактов. Для этого используются визуальные редакторы. Объединение версий диаграмм является проблемой. Тратятся значительные ресурсы на механическую деятельность. А если вы ещё и дома, на диване, на ноутбуке с тачпадом, без мышки… Впрочем, что-то я отвлекся.
DocHub предлагает отказаться от использования визуальных редакторов в пользу описания архитектуры кодом. Использовать принципы управления архитектурой аналогично принципам управления кодовой базой. Для этого предоставляются четыре языка описания архитектуры:
- PlantUML — позволяет создавать диаграммы из обычного текстового языка;
- Markdown — язык разметки, созданный с целью обозначения форматирования в тексте;
- Swagger — язык описания интерфейсов для описания RESTful API;
- Манифесты — структурированные файлы в формате YAML/JSON для описания архитектурных объектов.
Таким образом, процесс развития архитектуры становится максимально близким к разработке систем. Это дает возможность, помимо решения основной проблемы (управление версиями), получить дополнительные преимущества:
- Унифицировать процессы развития архитектуры и разработки;
- Архитектурные артефакты могут быть размещены непосредственно в репозитории кодовой базы и развиваться одновременно с кодовой базой системы;
- Возникает возможность управления архитектурными идеями через Pull request;
- Создается база для взаимного проникновения экспертиз разработки и проектирования.
Одному из главных преимуществ мне хотелось бы посвятить отдельный раздел.
Управление децентрализованной архитектурой
Под “децентрализованной” понимается сложная, многокомпонентная архитектура системы, части которой распределены по командам разработки. Каждая команда развивает свой сегмент параллельно и независимо, но должна учитывать общую концепцию. Ярким примером является микросервисная архитектура.
На первый план здесь выходит синхронизация решений команд, влияющих на общий архитектурный ландшафт. Остро стоит вопрос управления технологическим стеком и переиспользования имеющихся в компании наработок.
Управление “архитектурой как код”, позволяет применить опыт Open Source сообществ. В этом случае существует центральный репозиторий с концептуальной архитектурой (как будет). Все имеют доступ к нему, получая необходимые сведения о планах развития. Изменения в репозиторий попадают через Pull requests. Ревьюверами являются техлидеры команд.
Таким образом достигается информирование об архитектурных решениях. Возникает консенсус. Происходит обмен опытом.
Описание архитектуры “как есть” остается в командах. Т.е., несмотря на то, что имеется централизованный репозиторий «как будет», у команд остается право на автономное принятие быстрых решений. Этот подход реализует Agile манифест. Если необходимо срочно внести обоснованные изменения в продукт, должна быть возможность это сделать. Такая ситуация считается инцидентом.
Противоречие с центральным репозиторием устраняется путем сверки “как есть” с “как будет”. Отклонения обосновываются и, с отставанием, вносятся. Таким образом, инцидентные решения остаются в поле управления.
Управление архитектурой холдинга (экосистем)
Под холдингом понимается группа компаний, развивающих цифровые продукты, имеющие потребность в интеграции с выраженным центром стратегического управления.
Холдинги имеют проблемы координации развития архитектуры экосистемы. Контроль достижения стратегических целей является ключевым для них.
Компании холдинга имеют разную степень автономности. Часто находятся на различных этапах развития. Это выражается в неоднородности процессов управления.
Таким образом, управление архитектурой экосистемы является нетривиальной задачей. DocHub предлагает и тут использовать принципы развития кодовой базы Open Source сообществами.
Центр в этом случае выступает майнтейнером (Maintainer) архитектурного кода. Он является владельцем центрального репозитория архитектуры. Устанавливает стандарты работы с ним.
Компании выступают в роли контрибьюторов (Contributors). У них есть собственный форк или ветка в центральном репозитории. Развитие архитектуры экосистемы ведется через Pull requests.
DocHub используется как универсальное средство представления артефактов экосистемы.
Архитектурные фасады
Под архитектурным фасадом понимается публичная часть архитектуры. Распространенным примером являются API-контракты сервиса.
Фасады могут иметь различную степень детализации и состав. В некоторых случаях для клиента достаточно только публикации контрактов. Но зачастую, у него возникает ряд вопросов по сценариям использования. Также может оказаться полезным отразить верхнеуровневую архитектуру внешних сервисов. Для решения этой задачи необходим комплект публичных артефактов.
DocHub с этой задачей хорошо справляется. Он может быть развернут в качестве архитектурного фасада. Внешние пользователи получают удобный интерфейс для изучения публичной архитектуры.
Посмотреть, потрогать
В отличии от первой версии DocHub, эта версия публикуется в альфе. Это обусловлено тем, что мы хотим получить как внутренние, так и внешние мнения об инструменте. Учесть их.
В настоящее время в нашей компании идет пилотное внедрение инструмента. О его результатах выйдет отдельная статья.
Живое демо можно посмотреть тут https://dochub.info/. Это развернутый DocHub, описывающий архитектуру самого себя.
Вы можете развернуть DocHub у себя. Но учтите, что он интенсивно допиливается. Ветка концепта — https://github.com/RabotaRu/DocHub/tree/archops-conception-v2 (readme устарело и будет обновлено. Честно-честно). Развертывание такое:
git clone https://github.com/RabotaRu/DocHub.git cd DocHub git checkout archops-conception-v2 npm install npm run serve
DocHub будет доступен по адресу: http://localhost:8080/
Планы
Мы надеемся привлечь комьюнити к развитию инструмента. Просим открыто выражать свои мнения о нем. Предлагаем генерировать идеи.
Ближайшие цели: внедрение инструмента и подведение итогов.
- Доработка механизма контроля консистентности архитектуры;
- Сравнение версий;
- Пользовательские запросы к манифестам на языке JSONata.
Architecture as Code: реализуем подход Саймона Брауна
Если вы знакомы с подходом к документированию, предложенным Саймоном Брауном, вы могли заинтересоваться им, но, возможно, задавались вопросом о его реализации. Этот репозиторий заполняет пробел, представляя конкретный шаблон реализации подхода, который состоящего из:
- Модели архитектуры программного обеспечения как код, построенные с использованием Structurizr Lite
- Документация, созданная с помощью шаблона Arc42
- Журнал решений, созданный с помощью ADR Tools
Предполагается хранение этой документации в репозитории и работа с ней так же, как и с кодом.
Для чего можно использовать этот шаблон?
- Предпродажа
- Исследование проекта
- Документ по архитектурному решению (SAD)
- Постоянная документация архитектуры вашей системы
Как запустить
- docker compose up -d
- Откройте веб-браузер и перейдите по адресу http://localhost:8081/
Как использовать Structurizr Lite
- http://localhost:8081/workspace/diagrams — диаграммы
- http://localhost:8081/workspace/documentation/Internet%20Banking%20System — документация
- http://localhost:8081/workspace/decisions/Internet%20Banking%20System — ADR
- Справочник по языку
- Руководство по началу работы с Structurizr Lite
- Посмотрите два доклада в нижней части FAQ по C4
- Документы Arc42 находятся в internet-banking-system/docs
- ADR находятся в internet-banking-system/adrs
Что внутри?
1. Модели архитектуры программного обеспечения как код
Live Demo
Structurizr основывается на идее «диаграммы как код», позволяя создавать несколько диаграмм архитектуры программного обеспечения из единой модели.
Существует ряд инструментов для создания совместимых рабочих областей Structurizr, среди которых Structurizr DSL рекомендуется большинству команд.
В примере DSL ниже создаются две диаграммы на основе единого набора элементов и отношений.
model < user = person "User" softwareSystem = softwareSystem "Software System" < webapp = container "Web Application" < user ->this "Uses" > container "Database" < webapp ->this "Reads from and writes to" > > > views < systemContext softwareSystem < include * autolayout lr >container softwareSystem < include * autolayout lr >theme default >
2. Документация
Live Demo
Каждый архитектурный документ в этом репозитории создан с использованием шаблона Arc42 и хранится в формате asciidoc, что позволяет легко отслеживать изменения и внедрять улучшения документации.
3. Журнал решений
Live Demo
Журнал решений создан с помощью ADR Tools, позволяя вести запись каждого архитектурного решения, принятого в проекте, в формате markdown.
Уроки по тегу «архитектура кода»
В каталоге хекслета найдено 17 уроков по теме «архитектура кода». Уроки по теме «архитектура кода» есть в курсах: JS: Объектно-ориентированный дизайн, Python: Объектно-ориентированный дизайн.
Знакомимся с объектом Proxy, с помощью которого можно изменять поведение объекта, не меняя код объекта
Знакомимся с поэтапной сборкой сложных объектов, композицией и текучим интерфейсом
Учимся правильно структурировать программу в стиле ООП
Знакомимся с целями и задачами курса
Знакомимся с основными принципами организации объектов, описывающих предметную область
Выясняем, как решают типовые задачи в программировании
Обсуждаем способы создания текучего интерфейса
Знакомимся с одним из базовых принципов проектирования классов
Учимся правильно переопределять базовую конфигурацию без создания опасных ситуаций
Узнаем, как решают типовые задачи в программировании
Познакомимся с основными принципами организации объектов, описывающих предметную область
Узнаем о курсе, его структуре, задачах и целях
Познакомимся с одним из базовых принципов проектирования классов
Научимся правильно переопределять базовую конфигурацию без создания опасных ситуаций
Научимся правильно структурировать программу в ООП стиле
Познакомимся с поэтапной сборкой сложных объектов, используя композицию и текучий интерфейс
Узнаем способы создания текучего интерфейса