Что нужно знать об отличной архитектуре проекта

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

Как мне это сделать?

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

О чем я буду говорить?

  • Микросервисная архитектура
  • Внедрение зависимостей .Net Core
  • ТВЕРДЫЙ
  • Луковая Архитектура
  • Чистая Архитектура
  • DDD (доменно-ориентированный дизайн)

О чем я буду говорить в части кодирования?

Здесь я буду использовать луковичную архитектуру с микросервисом.

  • .Net Core 3.1
  • Репозитории
  • CQRS и MediatR
  • Entity Framework | Сначала код
  • MySQL

Архитектура микросервисов

В книге Микросервисы .NET: архитектура для контейнерных приложений .NET, которая является собственным источником Microsoft и которую вы можете скачать отсюда, микросервисы объясняются следующим образом:

Как следует из названия, архитектура микросервисов - это подход к созданию серверного приложения как набора небольших сервисов. Это означает, что архитектура микросервисов в основном ориентирована на серверную часть, хотя этот подход также используется для клиентской части. Каждая служба работает в своем собственном процессе и взаимодействует с другими процессами с помощью таких протоколов, как HTTP / HTTPS, WebSockets или AMQP.

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

Какого размера должен быть микросервис?

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

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

Почему именно микросервисная архитектура?

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

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

Используйте принципы SOLID и внедрение зависимостей

Принципы SOLID - это критически важные методы, которые можно использовать в любом современном и критически важном приложении, например, при разработке микросервиса с шаблонами DDD.

SOLID - это аббревиатура, объединяющая пять фундаментальных принципов:

• Принцип единой ответственности

• Принцип открытости / закрытости

• Принцип замещения Лискова

• Принцип разделения интерфейса

• Принцип инверсии зависимостей

SOLID - это больше о том, как вы проектируете внутренние уровни приложения или микросервиса, а также о разделении зависимостей между ними. Это связано не с доменом, а с техническим дизайном приложения.

Последний принцип, принцип инверсии зависимостей, позволяет отделить уровень инфраструктуры от остальных уровней, что позволяет лучше отделить реализацию уровней DDD.

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

Чаще всего классы объявляют свои зависимости через свой конструктор, что позволяет им следовать принципу явных зависимостей. Внедрение зависимостей обычно основано на конкретных контейнерах инверсии управления (IoC). ASP.NET Core предоставляет простой встроенный контейнер IoC, но вы также можете использовать свой любимый контейнер IoC, например Autofac или Ninject.

Следуя принципам SOLID, ваши классы, естественно, будут небольшими, хорошо структурированными и легко тестируемыми. Но как узнать, внедряется ли в ваши классы слишком много зависимостей?

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

Доменно-ориентированный дизайн (DDD)

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

Представленный и ставший популярным программистом Эриком Эвансом в его книге 2004 года «Дизайн, управляемый предметной областью: преодоление сложности в основе программного обеспечения», дизайн, управляемый предметной областью, представляет собой расширение и применение концепции предметной области в том, что касается разработки программного обеспечения. DDD фокусируется на трех основных принципах:

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

Многоуровневая архитектура
Одной из основных концепций DDD является четырехуровневая архитектура.

  • Уровень домена
  • Уровень приложения
  • Слой презентации
  • Уровень инфраструктуры
    Эта тема будет лучше понятна с луковой архитектурой.

Луковая Архитектура

Как показано на схеме, традиционная многоуровневая архитектура имеет иерархию «UI» - ›« Business Logic »-› «Data». Я думаю, что было бы полезно поговорить о трудностях этой архитектуры и цене, которую эти трудности накладывают на нас, а не о выгодной отдаче.

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

Как видно, в Onion Architecture слои расположены по кругу, один внутри другого. Он получил такое название, потому что выглядит как Лук. Фактически, мы можем сказать, что зависимость каждого слоя только от одного внутреннего слоя с точки зрения функциональности, а не изображения, объясняется таким образом, потому что он анимирует анатомию луковицы.

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

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

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

Уровень презентации - это то место, где вы в идеале хотели бы разместить проект, к которому пользователь может получить доступ. Это может быть WebApi, Mvc Project и т. Д.

Уровень инфраструктуры немного сложнее. Это то место, где вы хотели бы добавить свою инфраструктуру. Инфраструктура может быть любой. Может быть, уровень ядра Entity Framework для доступа к БД или уровень, специально созданный для генерации токенов JWT для аутентификации, или даже уровень Hangfire. Вы поймете больше, когда мы начнем реализацию луковой архитектуры в проекте ASP.NET Core WebApi.

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

Преимущества луковой архитектуры

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

Чистая Архитектура

Каждая из чистых архитектур производит системы, которые:

  • Независимо от рамок. Архитектура не зависит от наличия какой-либо библиотеки программного обеспечения с множеством функций. Это позволяет вам использовать такие фреймворки в качестве инструментов, вместо того, чтобы загонять вашу систему в их ограниченные ограничения.
  • Тестируемый. Бизнес-правила можно тестировать без пользовательского интерфейса, базы данных, веб-сервера или любого другого внешнего элемента.
  • Независимо от пользовательского интерфейса. Пользовательский интерфейс можно легко изменить, не меняя остальную часть системы. Веб-интерфейс можно заменить, например, консольным, без изменения бизнес-правил.
  • Независимо от базы данных. Вы можете заменить Oracle или SQL Server на Mongo, BigTable, CouchDB или что-то еще. Ваши бизнес-правила не привязаны к базе данных.
  • Независимо от какого-либо внешнего агентства. Фактически, ваши бизнес-правила просто ничего не знают о внешнем мире.

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

CQRS и MediatR

Разделение ответственности за команды и запросы (CQRS) было введено Грегом Янгом и активно продвигалось Уди Даханом и другими. Он основан на принципе CQS, хотя и более подробно. Его можно рассматривать как шаблон, основанный на командах и событиях, а также, необязательно, на асинхронных сообщениях.

Во многих случаях CQRS связан с более сложными сценариями, такими как наличие другой физической базы данных для чтения (запросов), чем для записи (обновления). Более того, более развитая система CQRS может реализовать Event-Sourcing (ES) для вашей базы данных обновлений, поэтому вы будете хранить только события в модели предметной области, а не хранить данные текущего состояния.

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

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

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

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

Заключение

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

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

Ресурсы:

Микросервисы, SOLID, внедрение зависимостей



Чистая архитектура

Блог чистого кодера

Луковая архитектура

Луковая архитектура: часть 1 | Программирование в Палермо (jeffreypalermo.com)

Https://www.gencayyildiz.com/blog/nedir-bu-onion-architecture-tam-teferruatli-inceleyelim/

CQRS

CQRS (martinfowler.com)

В моей первой статье, которая будет продолжаться с этого момента, я разработаю веб-API с упомянутой структурой.

Спасибо за чтение!