КОДЕКС

Ключевые принципы архитектуры программного обеспечения

Давайте также расшифруем, что такое Архитектура, чем занимается Архитектор.

Я долго не мог понять, что такое «Архитектура» программного обеспечения. Если Архитектура - это прекрасные диаграммы для представления компонентов системы, слоев, взаимодействия и потока данных, тогда что такое «высокоуровневый дизайн». Мне потребовалось много времени, чтобы найти или осознать ответ.

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

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

Что такое архитектура программного обеспечения

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

Кто такой архитектор программного обеспечения

(Я больше занимаюсь архитектурой программного обеспечения как частью повседневной разработки, а не отдельным отделом),

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

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

Ключевые принципы архитектуры программного обеспечения

Уменьшите количество доработок, уменьшите риск

Прежде всего, как уменьшить переделки. Мы не можем контролировать изменения в потребностях бизнеса, новые запросы - это хорошо для бизнеса. Однако мы можем контролировать количество изменений, которые нам нужно внести в приложение для любых новых требований. И магический принцип ТВЕРДЫ. Однако давайте разберемся и поговорим простым языком:

Не повторяйтесь (СУХОЙ): Да, не пишите снова тот код, который вы можете использовать из существующей реализации. Вот где "очень" помогает привычка к постоянному рефакторингу. Нужна какая-то реализация, которую вы уже написали в другом модуле, вытащите ее, сделайте универсальной, чтобы использовать ее из всех мест. Определите, рефакторинг, сделайте универсальным для повторного использования.

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

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

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

Это также значительно снижает общую стоимость владения.

Единица кода: приложение, модуль, класс, функция - все единицы кода в их собственном контексте, и разница заключается в пользователе.

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

Используйте интерфейсы для определения поведения. Интерфейсы помогают добавлять новое поведение в любое время в приложении за счет реализации другого класса. Это означает, что вызывающему или пользователю интерфейса не нужно ничего менять, если мы просто добавим новую реализацию для того же интерфейса и введем ее для пользователя / вызывающего (DI). Нам не нужно вносить никаких изменений в код вызова. Мы просто расширяем поведение, добавляя еще один вариант реализации. По сути, мы улучшили поведение системы, не внося изменений в существующую реализацию, а просто расширив существующее поведение, добавив новый вид.

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

Пример. CoffeeMaker использует CoffeeMachine (интерфейс) для приготовления кофе. У нас есть кофемашина-эспрессо (EspressoCoffeeMachine), которую использует кофеварка. В будущем, если мы хотим добавить больше машин, например, для приготовления капучино, мы можем добавить еще одну машину в систему (CappuccinoCoffeeMachine реализует CoffeeMachine) и внедрить эту новую машину в CoffeeMaker на основе контекста. В результате мы добавили новое поведение без изменения кода в CoffeeMaker, CoffeeMachine, EspressoCoffeeMachine. Но мы просто добавили новую реализацию.

Дизайн для перемен

Изменения - это единственная правда!

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

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

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

Принцип наименьшего (знания, удивление и усилия):

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

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

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

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

Снижение совокупной стоимости владения

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

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

Продолжайте развиваться

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

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

Здесь - отличный ресурс для развития архитектуры и дизайна от Мартина Фаулера, моего виртуального удаленного гуру :)

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

Об эволюции системного дизайна читайте в одном из учебных путешествий.