Привет, Хабр! Зачем нужна архитектура приложения и какие цели она должна выполнять?

Разработка архитектуры ПО - это искусство и наука проектирования программного обеспечения таким образом, чтобы оно удовлетворяло всем заявленным требованиям, а также обеспечивало максимальную простоту доработки, развертывания и масштабирования приложения.

Архитектура должна помогать нам писать максимально гибкий код, который мы сможем расширять с приходом новых функций, а не переписывать с нуля.

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

Вот например Microsoft предлагают монолитную структуру кода в одной сборке, как одно из решений.

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

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

???? Разделение между бизнес-логикой и инфраструктурой

Посмотрим на представление Чистой архитектуры приложения ASP.NET Core от Microsoft

Выделены три блока: Ядро, Инфраструктура и Фреймворк, который их объединяет. Обратите внимание, что нет явного слоя представления. Его компоненты находятся рядом с контейнером зависимостей и конвейером обработки запросов. Если мы еще вспомним, что все современные системы делятся на фронтенд и бэкенд, то API может содержать только контроллеры.

????Будь проще

Python является простым и гибким языком программирования, который подходит для разработки различных приложений и систем. Он имеет свою философию, известную как "Дзен Пайтона", которая включает в себя ряд принципов и рекомендаций, выделю два:

???? Явное лучше, чем неявное. Простое лучше, чем сложное.

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

Не следует лишний раз создавать абстракции, если можно обойтись без них. Например, если ядро доступно для всех слоев, тогда можно использовать явный тип из него. В Trunk Based Development используются абстракций во время работы над фичей, а после завершения задачи абстракция удаляется.

Не создавайте дублирующие Model, Entity, DTO, наследуя их от абстракции. Создайте модель сразу в ядре и используйте ее для всех слоев, если она нигде не отличается. Этого достаточно для прототипа. Когда продукт-менеджер захочет добавить новую функцию в базу, тогда уже будет создана сущность Entity и абстракции. Однако, стоит заметить, что в 80% случаев проекты не продвигаются дальше этапа прототипа.

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

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

☝️С чего начать?

Чистая архитектура говорит про сценарии. Заказчики чаще всего используют блок-схемы и диаграммы последовательности для обозначения своих мыслей, что делает легче мыслить сценарии использования (use cases). В DDD используется концепция ubiquitous language - единого языка. Давайте использовать это как наш единый язык.

???? Начинать систему надо со сценариев(use cases)

В Use case можно вызывать другие Use case. Важно, что все взаимодействия происходят через сценарии, которые требует бизнес. Далее все сценарии вызывают код инфраструктуры через абстракции.

Имутабельность и чистые функции. Все сценарии не имеют состояния, они лишь являются инструкцией для запроса. Чистые функции имеют маленький порог входа, каждый junior может разобраться и внести правки в бизнес-процесс.

Если проект начнет расти, то можно создавать слои, но эти слои будут расширениями существующих, а не промежуточными. Т.е. если у нас появятся слои Persistence, Domain, Application. То это будут слои расширения для существующих т.е. Infrastructure.Persistence, Core.Domain, Core.Application.

???? Никто из инфраструктуры не может использовать Use case!

Избегать вызова сценариев непосредственно из уровня инфраструктуры. Это может привести к потере контроля над кодом

????Итоги

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

  • Главное соблюдать логическое деление бизнес логики и инфраструктурного кода, а не физическое разделение слоев. Для этого лучше сразу использовать use cases.

  • Ваша архитектура приложения может стать как в примере у Дяди Боба, но это должно прийти с требованиям к проекту.

  • Важно помнить, что добавление абстракций и паттернов должно быть основано на потребностях приложения, а не на их доступности. Вместо того, чтобы добавлять их на этапе создания приложения, следует добавлять их по мере необходимости.

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