Разработка Архитектуры Проекта, Кораблей И Javascript

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

Как сделать его непотопляемым и порадовать своих клиентов.

Ниже мы рассмотрим примеры из реальной жизни и постараемся учиться на чужих ошибках.

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

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



Разработка архитектуры проекта, кораблей и JavaScript

Статья основана на докладе Алексея Богачука (архитектора решений EPAM) с конференции HolyJS 2018 Питер .

Под катом — видео и стенограмма доклада.



Подходы к архитектуре и роль архитектора проекта



Мы плавали - мы знаем

Об этом рассказали моряки шведского корабля «Васа».

Но они плыли, спасаясь с тонущего корабля, только что спущенного со стапелей.

При чем тут Васа?

Разработка архитектуры проекта, кораблей и JavaScript

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

Шведский король заключил контракт с архитектором-корабелом Хенриком Хубертссоном.

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

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

  • корабль должен быть самым большим на Балтийском флоте: длина 70 метров, ширина 10 метров;
  • вам нужно три палубы для размещения 300 солдат;
  • на его борту должно было быть 64 орудия в два ряда;
  • На строительство отведено 3 года.



Разработка архитектуры проекта, кораблей и JavaScript

Аналогов такого корабля в то время не было.

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

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

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

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

Налицо следующие архитектурные ошибки Хенрика (которые, кстати, могли бы стоить ему жизни, если бы он дожил до суда):

  • Все противоречивые ограничения не были сбалансированы.

  • Никакого управления рисками не было, так как раньше никто не строил корабли такого масштаба.

  • Отсутствовало и управление взаимоотношениями с клиентами — Хенрику не хватило смелости спорить с королем.

  • Использовались неправильные технологии строительства.

  • Архитектор согласился на невыполнимые требования.

В результате этих просчетов корабль «затонул» еще на стадии проектирования.

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

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



Влиятельные друзья

Сколько плохо спроектированных приложений умирает до того, как будет написана первая строка кода? Цикл влияния архитектуры на проект следующий:

Разработка архитектуры проекта, кораблей и JavaScript

Слева направо:
  1. Есть заинтересованные стороны, или заинтересованные лица (в случае с кораблем это король и казначейство).

  2. У них свои цели (первый корабль в Европе).

  3. Цели диктуют требования (конкретные характеристики будущего корабля).

  4. Далее составляются чертежи, схемы и проект.
  5. Строительство по проекту.

Ошибка на одном из этих этапов может испортить будущее вашего проекта.



Справочник для архитектора решений

Мы рассмотрим примеры из реальной жизни и постараемся учиться на чужих ошибках.

Заодно составим книгу полезных рекомендаций для архитектора решений.

Хенрик Хубертссон обжегся, потому что у него его не было.

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

Все рассказы будут включать архитектурные ката (проблемы).

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



История крутого Джимми

Требования клиента
  • Замените текущее решение пользовательского интерфейса.

  • Внедрить новый подход к разработке и внедрению данного решения.

  • Нам нужен лучший пользовательский опыт.
  • В то же время следуйте всем лучшим практикам.

  • Поддерживает различные платформы.

Что было сделано Требования очень общие, конкретики нет. Непонятно, что со всем этим делать.

При этом команда разработчиков находится в Минске, а заказчик — в Монреале.

Из-за того, что между Беларусью и Канадой действовали санкции, работа напрямую с Канадой вестись не могла.

С заказчиком было решено работать через офис в Дублине.

Из-за всех этих задержек во времени и посредничества не удалось связаться с заказчиком и узнать окончательные требования или внести предложения по реализации.



Разработка архитектуры проекта, кораблей и JavaScript

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

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

По итогам работы была сделана презентация.

Пришло время показать результаты.

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

Конечно, все оказалось сделано совсем не так, как ожидал заказчик.

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

Он не принимал никаких решений и вообще не имел к проекту никакого отношения.

Где ошибка? На самом первом этапе определения архитектуры были неправильно определены заинтересованные стороны.

Заключение Любая архитектура начинается с идентификации заинтересованных сторон (стейкхолдеров).

Для их выявления существует множество подходов, мы рассмотрим один из них – построим матрицу RACI.

РАСИ

Аббревиатура расшифровывается: Р – ответственный, тот, кто будет реализовывать; А – ответственные лица, принимающие решения; С – консультировался (деловые люди), консультирование; Я – информированный человек, который должен быть информирован.

Каждую из заинтересованных сторон необходимо отнести к той или иной категории.

Матрица определяет роли и задачи.



Разработка архитектуры проекта, кораблей и JavaScript

Построив такую матрицу, вы сможете понять, кто является заинтересованными сторонами.

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

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

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

Лук

«Луковый» подход несколько отличается от матриц RACI.

Разработка архитектуры проекта, кораблей и JavaScript

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

В этом примере разработчики, DevOps и контент-менеджеры будут взаимодействовать с самой системой.

Чуть выше по абстракции стоят люди из бизнеса.

Есть и внешние регуляторы: СМИ, законы и т. д. Например, для выпуска приложения в некоторых странах требуется пройти аудит, проводимый сторонней компанией; он определит доступность и другие качества, необходимые для проекта; это требования внешних заинтересованных сторон.

Итак, мы пишем в справочнике нашего архитектора, что первый и необходимый этап — это выявление заинтересованных сторон.



История: Недостаточно быстро

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

На основании этого был сформулирован ряд требований.

Требования клиента

  • Будьте быстрее конкурентов
  • Необходимо добиться того, чтобы транзакция прошла не более чем за 0,5 секунды.

Что ты сделал Проект был реализован, но оказался неудачным.

Почему? Опять же требования были не совсем корректны.

Целью было не совершать транзакции за 0,5 секунды, а сделать их быстрее, чем у конкурента.

В результате скорость была увеличена до 0,5 секунды, но участник в это время достиг 0,4 секунды.

Мы видим ошибку в определении бизнес-цели.

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

Часто они остаются неизвестными.

Нас больше интересуют технические цели, включающие в себя бизнес-цель.

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

Все это нужно знать и учитывать при построении архитектуры.

Точно так же, как и то, что проекты без цели мертвы с самого начала.



Разработка архитектуры проекта, кораблей и JavaScript

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

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

Бизнес-цели никогда не следует упускать из виду при проектировании архитектуры.

Полезные рекомендации для себя вы можете найти в книге «Раскрытие требований», авторы — Ян Александер, Льерка Беус-Дукич.



Разработка архитектуры проекта, кораблей и JavaScript



История о том, как пионеры доили лошадь

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

Он уже содержит сложную бизнес-логику.

Требования клиента

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

  • Приложение должно иметь автономный режим.

Что ты сделал Исходя из требований было решено писать на React Native. Разработка началась.

В ходе первого звонка были получены уточнения и дополнения к требованиям:

  • Компания раздает сотрудникам телефоны, и все они работают на Android.
  • Заказчика интересует только офлайн-режим.

  • Срок: два месяца.

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

Было решено использовать PWA (Progressive Web Apps).

У меня уже был опыт подобной работы.

Было написано не просто PWA-приложение, оно было изоморфным.

Сервисы с сервера были переиспользованы на клиенте, были написаны специальные обертки, с помощью которых можно было общаться с этими сервисами.

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



Разработка архитектуры проекта, кораблей и JavaScript

Итак, проблемы были с требованиями, которые не так просты.

Давайте рассмотрим пример требований:

Разработка архитектуры проекта, кораблей и JavaScript

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

Но для архитектора важнее то, какой должна быть система.

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

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

Разработка архитектуры проекта, кораблей и JavaScript

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

Заключение Архитектор должен сосредоточиться на нефункциональных требованиях, особенно на ограничениях и атрибутах качества.

Следующая ката об этом.



История белой вороны

Требования клиента
  • Разработать отдельный сервис, конвертирующий и кэширующий данные в формате xml.
  • Он должен сделать это из сторонней устаревшей системы.

Что ты сделал Разработали хороший работающий сервис, сделали на Node.js. Вот так схематически стала выглядеть система в целом вместе с введенным новым сервисом.



Разработка архитектуры проекта, кораблей и JavaScript

Очевидно, Node.js здесь — белая ворона, хотя все работало хорошо.

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

Каковы ограничения?

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

Далее мы переходим к атрибутам качества, к ним у нас особый интерес.



Атрибуты качества



Очень безопасная библиотека

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



Разработка архитектуры проекта, кораблей и JavaScript

В основе истории лежит атрибут «безопасности».

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

Тем не менее, это происходит. Мы видим, что слепое применение атрибутов качества также может быть чревато.



Телефон в лесу

А что насчет производительности? Понятно, что нет людей, которых не заботит производительность.

Вот сценарий.

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

Таким образом, это влияет на нашу систему, но не на всю систему, а на веб-интерфейс.

Например, ему нужно получить какие-то данные в течение трёх секунд. Это тот сценарий производительности, который нам нужно получить.



Разработка архитектуры проекта, кораблей и JavaScript

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

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

Такое обращение к атрибутам на диаграммах называется архитектурной тактикой.

Какую архитектурную тактику можно применить к системе «телефон в лесу» на основе рассматриваемых сценариев?

  • Улучшите UX, чтобы пользователь почувствовал, что производительность выше.

  • Оптимизируйте ресурсы (JS, CSS, изображения, шрифты и т. д.).

  • Выполните кэширование.

  • Добавьте сервис-воркеров, критический путь.

  • Примените компрессию.

  • HTTP/2.
Однако в случае с телефоном в лесу UX и критический путь нам подходят не сразу.

Еще раз, тактика должна диктоваться сценариями.

Это работа архитектора – выбрать из всех тактик необходимую в конкретном случае.

Но приложение — это не только интерфейс.

На производительность также влияют DNS, бэкенд, базы данных, и все это тоже можно оптимизировать.

Существует множество тактик, как это сделать, но опять же, использование той или иной зависит от варианта использования.

Давайте попробуем использовать шаблон CQRS (разделение ответственности за командный запрос).

Использование этого шаблона в качестве тактики влияет даже на несколько уровней приложения: как внутренний, так и внешний.



Разработка архитектуры проекта, кораблей и JavaScript

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

Мы находимся в лесу с телефоном и хотим быстро прочитать наши данные из этой базы.

Шаблон говорит, что мы должны разделить запросы на чтение и запись.

Добавим быструю базу данных для чтения.

Добавляем все инструменты для синхронизации этой базы данных с существующей.



Разработка архитектуры проекта, кораблей и JavaScript

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

Итак, мы применили некоторые тактики.

Запускаем приложение и видим, что не помогло, так как нет подключения к Интернету.

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



Стойкий оловянный солдатик

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

Чтобы приложение работало стабильно, можно применить принцип Fail Fast:

  • Всегда заранее проверяйте точки интеграции.

  • Избегайте медленных соединений.

  • Проверьте введенные данные.

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

Давайте применим к нему паттерн «Выключатель».



Разработка архитектуры проекта, кораблей и JavaScript

Пока все идет хорошо, мы ничего не делаем.

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

Если запрос снова провалится, мы снова остаёмся в офлайн-режиме с увеличенным таймаутом.

И если запрос прошел успешно, возвращаемся в онлайн-режим.

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



Подводная лодка

Существует множество подходов к обеспечению отказоустойчивости.

Одним из них является переборка (переборка, например, на подводной лодке).

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

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

Возникает ошибка в бизнес-логике.

Мы регистрируем это.

Для получения информации об ошибке нам нужен контекст, в котором она произошла.

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

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

Нужно разделить ошибки на критические и не очень и сбрасывать только первые.



Дырявое ведро

Стратегия, аналогичная описанной выше, используется в паттерне «Дырявое ведро».



Разработка архитектуры проекта, кораблей и JavaScript

У нас есть счетчики разных типов ошибок.

При возникновении ошибки счетчик ошибок этого типа увеличивается.

По истечении времени ожидания этот счетчик уменьшается.

Но если количество ошибок начинает зашкаливать, счетчик не успевает уменьшаться и, образно говоря, переполняет ведро, после чего делаем дамп памяти.

Далее работаем над ошибкой, которая привела к переполнению счетчика.

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

Так строится архитектура.



Разработка архитектуры проекта, кораблей и JavaScript

Что означают зеленые стрелки? Различные сервисы взаимодействуют друг с другом посредством различных протоколов, баз данных и других сервисов.

Тем, кто хочет больше узнать о шаблонах отказоустойчивости, будет полезна книга Роберта С.

Ханмера «Шаблоны отказоустойчивого программного обеспечения».



Разработка архитектуры проекта, кораблей и JavaScript

Также рекомендуем книгу «Архитектура программного обеспечения на практике», авторы: Лен Басс, Пол Клементс, Рик Казман.

В нем вы узнаете о других качествах и тактиках их следования.



Разработка архитектуры проекта, кораблей и JavaScript



Пример на десерт

Случай
  • Мы хотим предложить существующим клиентам улучшения текущей платформы.

  • На этой платформе уже написано около 400 статических сайтов.

  • Проблема в том, что это дорого и отнимает много времени.

  • Управление контентом также является дорогостоящим и трудоемким процессом.

  • Платформа написана на Drupal.
Допустим, для решения этих проблем можно использовать следующие фреймворки:

Разработка архитектуры проекта, кораблей и JavaScript

Мы уже нашли заинтересованных лиц.

Необходимо определить цели.

Самая глобальная цель — удовлетворить клиента.

Цель бизнеса — оптимизировать затраты заказчика (это уже интересная цель для заказчика).

Дальше идут более конкретные цели: сократить время вывода продукта на рынок, сократить время управления контентом.

Тогда обнаруживаются следующие ограничения:

  • Писать нужно в Drupal, так как клиент приобрел лицензию и поддержку на некоторое время.

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

Определив признаки качества, мы выяснили:
  • Важно сохранить возможность поддержки всех 400 сайтов (ремонтопригодность).

  • Необходимо реализовывать тесты так, чтобы не нарушить существующую функциональность (тестируемость).

  • Повторное использование всего существующего контента (повторное использование).

  • Должно работать быстро (производительность).

  • Доступность для определенных типов сайтов (доступность).

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

Рассмотрим модель С4. Построено несколько диаграмм.

Контекстная диаграмма:

Разработка архитектуры проекта, кораблей и JavaScript

Определяем роли людей, которые будут работать с платформой.

В данном примере это посетители, разработчики и контент-менеджеры.

Перейдем к диаграмме контейнера:

Разработка архитектуры проекта, кораблей и JavaScript

С точки зрения бизнеса существует веб-сайт, который посещают пользователи.

Разработчики работают с генератором сайтов, контент-менеджеры работают в контент-хабе.

Мы интегрируемся со сторонними системами в процессе обновления платформы.

Схема компонентов выглядит следующим образом:

Разработка архитектуры проекта, кораблей и JavaScript

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

Существует точка интеграции между контент-хабом и генератором сайта.

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

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

Учитывая все предыдущие практики, мы добавляем необходимые подходы в модуль Службы шаблонов.

Обратите внимание, что Drupal используется исключительно в центре контента.

Приходим к выводу, что для статической генерации подходят фреймворки NuxtJS или Next.js, которые написаны на Vue.js и React.js соответственно.

В качестве замены точек интеграции выгодно использовать GitHub и ветки, таким образом мы приходим к JAM-подходу.

Означает JavaScript, API, Markdown.

Разработка архитектуры проекта, кораблей и JavaScript

Видно, что стек, который решено использовать, отличается от исходного.

С одной стороны, мы использовали Node.js и какой-то современный фреймворк.

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

Таким образом, мы пришли к пониманию подхода Javascript, API, Markdown. Заключение Вам необходимо тщательно выбирать окончательный стек технологий.

Это мы записываем в книгу нашего архитектора.



Последняя история

Случай Архитектор определил все заинтересованные стороны, требования, цели, ограничения.

Далее был сделан некий проект. Разработка приложения шла хорошо, но в итоге проект провалился.

Почему это случилось? Дело в том, что разработчики проекта не знали о требованиях, заинтересованных сторонах, ограничениях и атрибутах качества.

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

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



Разработка архитектуры проекта, кораблей и JavaScript



Полученные результаты

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

Распечатайте его и повесьте на видном месте.

Чтобы построенные вами корабли плавали на воде, а еще лучше — плыли в нужном направлении:

  • Любая архитектура начинается с идентификации заинтересованных сторон (стейкхолдеров).

  • При проектировании архитектуры необходимо учитывать бизнес-цели.

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

    Он должен понимать, каким должно быть приложение, которое он разрабатывает.

  • Архитектурная тактика должна диктоваться вариантами использования.

  • Окончательный стек технологий необходимо тщательно выбирать.

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

Если вам понравился репортаж, обратите внимание: 24-25 ноября новый
Теги: #Управление разработкой #JavaScript #Системный анализ и проектирование #архитектура приложений
Вместе с данным постом часто просматривают: