Skip to content

Прохождение архитектурных развилок

При прохождении архитектурных развилок (architectural trade-offs) между разными архитектурными решениями используются эвристики, известные как архитектурные паттерны**/шаблоны**. Эти паттерны на сегодня являются основными способами передачи архитектурного опыта между архитекторами. Принятие согласованных между собой наборов отдельных чётко сформулированных решений, которые делаются в той или иной ситуации делается в виде набора паттернов, который называется языком паттернов**/шаблонов**. Использование языков паттернов впервые предложил в строительной архитектуре Кристофер Александер с коллегами в 1977 году[1]. Дальше это было подхвачено программными архитекторами, расцвет использования языков паттернов случился в нулевые годы 21 века. Предлагались самые разные языки паттернов, включая паттерны свободного программного обеспечения[2] и организационные паттерны[3], но постепенно в организационной архитектуре были приняты другие способы организации знания (методы стали передаваться через разнообразные варианты корпусов знаний/body of knowledge, в которых преобладал «процессный подход»), а вот в программной архитектуре такой подход остался[4].

Паттерны — это какие-то шаблонные/типовые решения, ведущие систему к успеху путём снятия противоречий в типовой ситуации. Эти противоречия обсуждаются как forces/drivers/соображения. Основное, что отличает языки паттернов от других способов моделирования решений, так это особое внимание к процедуре прохождения развилок в решениях: явно обсуждается конфликт каких-то характеристик (в случае архитектурных паттернов это архитектурные характеристики, например, конфликт между скоростью работы монолитного модуля и скоростью внесения в него изменений). Паттернов для какой-то предметной области существует много, и они уподобляются словам в языке: при помощи их можно принимать цепочки тесно связанных решений, как строить предложения в словах какого-то языка. Отсюда и название «язык паттернов».

Главное отличие разных языков паттернов/шаблонов (pattern languages) от разных корпусов знаний (body of knowledge)[5] и процессных стандартов (process standard)[6] описаний методов (типа ISO 15288 для методов системной инженерии киберфизических систем, или ISO 12207 для методов программной инженерии) то, что они предполагают объяснения в своём составе, а не просто говорят «делай вот такие действия», причём эти объяснения прямо исходят из идей системного творчества (поиск решения через выход на противоречия описан в подразделе по системному творчеству руководства по системному мышлению).

В книге «Fundamentals of Software Architecture» первым законом архитектуры предлагается «в архитектуре все решения являются результатом прохождения развилок», но вот второй закон**—** это ««почему» в архитектуре важнее «как»». Архитектурные паттерны как раз выполняют этот второй закон: они дают в своих описаниях «почему». Описание паттерна представляет собой несколько страниц структурированного текста, в котором могут встречаться (часто не все) разделы:

  1. Имя паттерна — короткое название, которое будет использоваться в речи, типа «архитектура, центрированная на данных» (data-centric architecture, паттерн 1 в работе «Patterns for Light-Weight Fault Tolerance and Decoupled Design in Distributed Control Systems»[7]).
  2. Тип (классификация паттернов в языке как наборе паттернов, место в таксономии. Скажем, в оригинальном языке паттернов строительной архитектуры Кристофера Александера всего 253 паттерна, поэтому они разбиты на группы, соответствующие масштабу: города, здания, строительство).
  3. Этот паттерн так же известен как (синоним имени).
  4. Ситуация/context — описание ситуации, в которой нужно применять паттерн.
  5. Проблема — по возможности сформулированная как противоречие проблема, которую призван решить паттерн. Например, «если выключится произвольный один блок, система должна продолжать работать».
  6. Соображения/влияния/силы/forces — рассуждения (по-русски иногда говорят «расклады»), которые необходимо принять во внимание, когда выбираешь предлагаемое паттерном решение проблемы. Если это архитектурный паттерн, то именно тут говорится о том, куда решение паттерна двигает архитектурные характеристики (надёжность, масштабируемость, ремонтопригодность, развиваемость и т.д.). Обычно все эти характеристики двигаются разнонаправленно: что-то улучшается, что-то ухудшается.
  7. Решение — что, собственно, нужно сделать.
  8. Формальное обоснование — использование какого-то стандарта инженерных обоснований для обоснования предлагаемого решения, подробней это обсуждается в нашем руководстве в разделе по инженерным обоснованиям. Например, популярно использование языка GSN (goal structured notation), а в паттернах защиты/security могут использовать «модели целей» STRIDE. Чаще всего формальные обоснования требуют в паттернах решений для безопасности и защиты, ибо формализация дорогая, но в части безопасности на цену обращают внимания мало, «не хочешь сидеть в тюрьме — плати».
  9. Последствия — тут важно, что обсуждаются как позитивные, так и негативные последствия применения паттерна (помним, что паттерн помогает пройти развилку, это решение для trade-off, и чем-то приходится жертвовать ради чего-то более важного).
  10. Общий сценарий — часто приводят как часть, по которой дальше делается формальное обоснование.
  11. Известные использования — если это и впрямь «паттерн» (шаблон), то он был выявлен как успешное повторение какого-то решения. Где этот паттерн оказался успешен? Или это не паттерн, а просто только что в первый раз придумали, и никто ещё этот «паттерн» не использовал?
  12. Литература по прежним работам с паттерном.
  13. Добавляют часто также варианты паттерна (если они не различаются настолько, чтобы делать отдельный паттерн) и связанные паттерны (в рамках языка и из других языков паттернов).

Не всегда описание паттерна именно «структурированный текст» с указанными разделами, хотя в разных сборниках паттернов используется ровно вот такой вид. Но в современной литературе от структурированного представления по большей части ушли, и используют не «букву», а «дух» работы с паттернами. Скажем, глава «5. Component-Based Decomposition Patterns» книги «Software Architecture: The Hard Parts» приводит язык паттернов с шестью паттернами. Эти паттерны даны как более-менее связный рассказ, в котором присутствуют все важные для описания каждого паттерна разделы, но эта структура описания не выделена в тексте, и текст ей следует не слишком строго.

Во многих архитектурных статьях, постах в блогах упоминаются «паттерны», часто говорится о каких-то forces (и они почему-то оказываются архитектурными характеристиками, но не всегда). Когда вы встречаете эти упоминания, вы должны знать: они связаны с организацией мышления архитекторов в форме паттернов, а терминология и стиль архитектурного мышления «паттернами» идёт ещё от строительной архитектуры, из книжки Кристофера Александера с коллегами, из далёкого 1977 года.

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

Как и любое другое решение в инженерии, использование паттернов конкурирует с другими способами описания деятельности. По большому счёту, языки паттернов должны быть описаны в руководстве по методологии. В архитектуре (прежде всего программной архитектуре) они закрепились именно за счёт того, что много внимания уделялось достижению трудноуловимых архитектурных характеристик, которые Кристофер Александер в строительной архитектуре называл «целостностью» или даже «жизнью»: то, что невозможно было выразить простыми указаниями на функциональность, но это был 1977 год! За это время стало понятно, что эти самые forces/расклады могут быть чётко определены и даже измерены как архитектурные предметы интереса, и архитектурные решения ищут оптимум для значений этих характеристик. Паттерны с их попытками не просто сказать, «что делаем», но и «почему делаем» сыграли тут большую роль. Выкиньте всё, связанное с обоснованиями и объяснениями — и вы получите упрощённый вариант, процессные стандарты и body of knowledge. OMG Essence как раз один из таких стандартов: он говорит, как описывать метод, но в этом описании нет места для «почему так» и «чего хотелось бы, и что в этом друг другу противоречит», и «чего мы при этом добьёмся». Конечно, языки паттернов — это более трудоёмкая форма документирования методологического знания!

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

Основная цель, для которой создавались языки паттернов — это документирование опыта собственной работы, а также обучение коллег лучшим методам достижения нужных архитектурных характеристик. Поэтому опытные люди, которым не нужно никого учить, и которые не нуждаются в обучении сами, и которые не признают полезности «мышления письмом» для улучшения собственной работы, в языках паттернов не нуждаются. Их мнение тоже широко представлено, они паттерны критикуют (хотя часто они критикуют и процессные стандарты, и body of knowledge, и даже учебники!). Их тезис: «все эти ваши шаблоны только стесняют творчество, это просто способ зарабатывать деньги для тех, кто эти шаблоны пишет!». В руководстве по системному мышлению об этом говорится как аргументе против «рельсов мышления»: призыв изобретать велосипед каждый раз заново приводит к тому, что мы постоянно имеем дело не с самыми современными велосипедами, а с теми первыми неуклюжими велосипедами, которые делали первые изобретатели велосипедов, ибо современные изобретатели велосипедов нельзя считать, что умней и опытней предыдущих. Конечно, лет через двадцать это будут уже очень неплохие велосипеды, но денег инвесторов и нервов покупателей жалко.

Поэтому предлагается паттерны из опубликованных уже языков паттернов использовать как минимум для обучения, получения кругозора в том, что встречается в жизни (в нашем случае встречается в архитектуре, но в общем случае — в каких бы то ни было методах, для которых был сделан какой-то язык паттернов как способ описать метод). И дальше уже изобретаем велосипеды, но хотя бы что-то уже знаем из учебного материала с языком паттернов. Это решает противоречие: «изобретать паттерны по ходу дела» (вместо «использовать накопленное знание в проекте») и «использовать накопленное знание в обучении».

Во всех учебниках по паттернам (а также во всех других вариантах описания методов: процессных стандартах, корпусах знаний и т.д.) предупреждается, что паттерны из предложенного их языка нужно обязательно адаптировать к конкретному проекту. Для адаптации нужно понимать, как устроены паттерны, как описывается деятельность — это означает, что для адаптации архитектурных паттернов нужно быть «немножко методологом», использовать фундаментальное знание об описании методов работы. И тогда паттерны «из книжки» будут адаптированы к проекту, или даже придуманы новые паттерны (которые в этот момент будут не паттернами, а просто архитектурными решениями). Прямое задействование паттернов «из учебника архитектуры» обычно в проекте не поощряется.

Итого: прохождение архитектурных развилок (trade-offs) сводится к принятию решений в соответствии с какими-то паттернами этих решений, но всегда есть возможность породить какую-то альтернативу, задействовать другой паттерн, или даже сделать архитектурное изобретение, которое потом станет новым архитектурным паттерном.

Языки паттернов развиваются со временем. Так, в программной архитектуре лучшим методом было использование «шестиугольной архитектуры»[8], предложенной Alistair Cockburn, часто называемой «порты и адаптеры». Делались модули, которые со всеми внешними сервисами разговаривали через определённые порты, к которым изготавливались адаптеры/коннекторы, чтобы изолировать структуру модуля от изменений в окружении (нужно тогда только немного изменить адаптер, но не сам модуль). Всё это хорошо работало, но база данных тоже была «через адаптер» — и когда менялась структура данных, всё равно нужно было менять начинку модуля, а не только адаптер. Дальше этот паттерн стал паттерном «мотоцикла с коляской»: базу данных втащили внутрь модуля, ибо «зацепление/coupling хуже дублирования», а «мотоцикл с коляской» тут оттого, что сам модуль стали делить на предметную/domain часть и инфраструктурную (коммуникация, мониторинг и т.д.) техническую часть. Базу данных сдублировали в разных модулях, и отдельно организовали синхронизацию содержания этих баз данных. Это решение (паттерн «мотоцикл с коляской») оказался чуть сложней, чем «порты и адаптеры», но лёг в основу движения микросервисов[9], которое существенно повлияло на архитектуру корпоративных приложений.

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


  1. https://www.artlebedev.ru/izdal/yazyk-shablonov/ — по-русски pattern language переведён как «язык шаблонов». ↩︎

  2. https://link.springer.com/chapter/10.1007/978-3-030-14291-9_3 ↩︎

  3. https://ailev.livejournal.com/488174.html ↩︎

  4. https://github.com/fkromer/awesome-pattern-languages ↩︎

  5. https://en.wikipedia.org/wiki/Body_of_knowledge ↩︎

  6. https://www.simplifyingprocesses.com/blog/process-standards ↩︎

  7. В сборнике Transactions on Pattern Languages of Programming IV, 2019 ↩︎

  8. https://codesoapbox.dev/ports-adapters-aka-hexagonal-architecture-explained/ ↩︎

  9. https://en.wikipedia.org/wiki/Microservices ↩︎