dzen

Архитектура программного обеспечения – принципы, методы и стили

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

Что такое плохая архитектура и как ее распознать?

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

  1. Излишне сложный — По иронии судьбы писать сложный код легко, это может сделать любой, но писать простой код трудно.
  2. Жесткий/хрупкий — Поскольку он излишне сложен, его нелегко понять и, следовательно, его довольно сложно поддерживать. Становится сложно даже внести какие либо небольшие правки.
  3. Не тестируемый— Такой код будет тесно связан, как правило, не будет следовать принципу единой ответственности, его будет трудно протестировать.
  4. Недостижимый — Хрупкий код с меньшим покрытием тестов в процессе эволюции, превращается в кошмар для поддержки

Что такое хорошая архитектура и какими свойствами она обладает?

  1. Просто — Легко понять.
  2. Модульность/многослойность/Четкость — Это важно для того, чтобы один слой мог изменяться независимо от других с минимальной связью между слоями
  3. Гибкий/расширяемый— Может быть легко адаптирован к новым меняющимся требованиям
  4. Тестируемый/поддерживаемый — Легко тестируемый, добавляйте автоматизированные тесты и поощряйте культуру TDD и, следовательно, легко поддерживаемый

Зачем беспокоиться об архитектуре, принципах, практиках?

Снижение затрат — Хотя изначально скорость разработки будет меньше, но в конечном итоге общая стоимость создания, а затем и технической поддержки будет меньше

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

Оптимизация — Регулярно задумывайтесь о рефакторинге кода. Это позволит содержать большие объемы кода в чистоте и порядке.

Оптимизация производительности — Не делайте оптимизации производительности кода, пока не достигните LRT.

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

Адаптивность/Эволюция — Следуя вышесказанному, программное обеспечение всегда следует эволюционной модели, когда оно продолжает адаптироваться к новым требованиям бизнеса и масштаба

Каким инструментам, методологиям и методам мы можем следовать?

  1. Lean методология — Создайте правильную вещь. Постройте то, что необходимо.
  2. Agile методология— Постройте правильный путь. Создавайте программное обеспечение таким образом, чтобы оно было гибким, адаптируемым и быстро реагировало на меняющиеся требования рынка
  3. Практика разработки на основе тестов и автоматизированных тестов (TDD) – Практика, при которой тесты пишутся до того, как будет написан сам код приложения. Что позволяет писать исключительно легко поддерживающийся код. Покрытие тестами близится к настоящим 100%.

Каким архитектурным стилям следовать?

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

  1. Доменно-ориентированная архитектура (Domain Centric Architecture)
  2. Архитектура, ориентированная на приложения (Application Centric Architecture)
  3. Кричащая Архитектура (Screaming Architecture)
  4. Архитектура микросервисов (Microservices architecture)
  5. Архитектура, управляемая событиями (Event-Driven Architecture, EDA)
  6. Разделение ответственности за командные запросы (Command Query Responsibility Segregation, CQRS)

Доменно-ориентированная архитектура

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

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

Исходный источник: https://images.app.goo.gl/cW5QmNMxn912DM4D6

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

Исходный Источник: https://images.app.goo.gl/dRgpzwPR9w8u5u4t7

Плюсы

  1. Это позволяет использовать мышление, основанное на предметной области (DDD). Основное внимание уделяется домену, пользователям и вариантам использования.
  2. Уменьшена связь между доменом (стабильным и меньше меняется) и деталями реализации (которые меняются быстрее, например, уровень представления, база данных).

Минусы

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

Ориентированное на приложение (Многоуровневая архитектура)

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

Исходный источник: https://images.app.goo.gl/UwBEyStMHaVVJt7u5

Абстракции (ЧТО?) — Приложение должно быть построено таким образом, чтобы оно могло содержать бизнес-логику с использованием абстракций. Он должен сосредоточиться на том, что(?) он хочет делать.

Сегрегация(КАК?) — это сделано, аспект деталей реализации можно подключить с помощью инъекции зависимостей(DI). DI применяется не только для внедрения бизнес-логики с использованием различных шаблонов проектирования, но и конкретно применяется при внедрении элементов инфраструктуры, таких как базы данных, кэш, серверы уведомлений, внешние веб-службы и т.д.

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

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

Функциональная организация кода (кричащая архитектура)

Архитектура должна кричать о намерениях системы — дядя Боб

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

Исходный Источник: https://images.app.goo.gl/3am8cnt6BrzFzh3JA

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

Исходный источник: https://levelup.gitconnected.com/let-me-hear-you-screaming-architecture-3adcc02f2ca3

Что касается уровня представления — возможно, вам все еще захочется следовать старому подходу моделей/представлений/контроллеров. Уровень презентации должен быть легким, без какой-либо бизнес-логики. Это помогает в 2-х отношениях. Во-первых, мы устраняем дублирование логики. Во-вторых, такая организация помогает младшим разработчикам пользовательского интерфейса сосредоточиться только на том, чтобы сделать пользовательский интерфейс насыщенным.

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

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

https://images.app.goo.gl/HHfv3ojn17B5L1dU7

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

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

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

Минусы

  1. Первоначальная стоимость выше
  2. Автоматизация DevOps необходима, поскольку в настоящее время необходимо автоматическое развертывание.
  3. Для работы с такими распределенными вычислениями требуется дополнительное время и затраты с точки зрения задержки, балансировки нагрузки, ведения журнала, мониторинга, обеспечения возможной согласованности и т. Д

Архитектура, управляемая событиями (EDA)

Микросервисы теперь могут взаимодействовать друг с другом, используя механизм запроса/ответа, такой как JSON, через вызовы REST или используя управляемую событиями архитектуру с посредником сообщений. Современная архитектура предпочитает EDA, поскольку она позволяет службам более гибко реагировать, сокращать задержки, обеспечивать надежное, отказоустойчивое, гарантированное обслуживание и позволяет лучше масштабироваться.

В EDA есть 3 участника, а именно производитель, который создает запускающее событие, посредник сообщений, который надежно передает сообщение, и потребитель, который может подписаться на конкретное или на все события. Это приводит к “реактивному программированию”, которое реагирует на событие(триггер), поступающее из потока данных, что приводит к более быстрому времени отклика и, следовательно, к низкой задержке.

Для микросервисов, которым требуются ACID свойства транзакций между микросервисами с использованием возможной согласованности, вместо EDA используется шаблон SAGA, в котором используется явный механизм отката для обработки условий ошибок для отката изменений. Это, однако, усложняет конструкцию, поэтому следует использовать с осторожностью.

EDA также породила Event Sourcing в качестве нового механизма хранения данных в БД. Здесь объекты БД никогда не обновляются. Вместо того, чтобы получить текущее состояние объекта, создается путем применения событий в том же порядке, в каком они были получены. Оптимизация производительности достигается в источнике событий путем создания моментальных снимков текущего состояния с фиксированными интервалами.

Шаблон CQRS-Разделение ответственности за командные запросы

Появление микросервиса и EDA также породило шаблон CQRS. Команда-это то, что изменяет состояние базового объекта, и запрос не изменяет объект, а просто возвращает запрошенное подмножество объектов.

Чем это полезно? Несколько примеров

  1. Вы можете улучшить масштабируемость чтения, не влияя на запись. Например, добавив дополнительные дополнительные узлы в MongoDB для удовлетворения требований к чтению, вы выборочно масштабируете возможность чтения.
  2. Команда должна отправить обновления в базу данных. Вы можете выбрать уровень кэширования для обеспечения более быстрого чтения.
  3. Иногда объект может принадлежать другому микросервису, и каждый раз запрос к другому микросервису может быть дорогостоящим, поэтому вы можете использовать уровень кэширования для своих запросов. Данные дублируются, но до тех пор, пока они сохраняются и меняются не очень быстро, вы можете значительно сократить задержку. Это иногда также обеспечивает устойчивость. Даже если другой микросервис недоступен, ваш микросервис может продолжать нормально работать. например, Кэширование каталога продуктов в заказе-микросервисе.

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

Исходник: https://sarada-sastri.medium.com/software-architecture-principles-practices-styles-a0263aa11530

Рейтинг
( 1 оценка, среднее 5 из 5 )
Maxyc Webber/ автор статьи
Мне 35 лет. Опыт профессиональной разработки 15 лет. Занимаюсь разработкой и поддержкой корпоративных систем автоматизации бизнеса, а также высоконагруженными проектами. Мне нравится решать нестандартные проблемы бизнеса. Имею опыт формирования команд под проект, налаживания процесса разработки, коммуникации программистов и заказчиков. Есть опыт работы с зарубежными заказчиками (ОАЭ, Польша, Германия, Швейцария).
Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.