Чтобы сделать масштабное или сложное приложение или сервис, нужно тщательно спланировать процесс его создания и развитие программы: как она будет расти, меняться, что делать разработчикам в случае поломок и как заменить какие-то функции, если они устареют.
Это сложное устройство программного обеспечения называется его архитектурой. Сегодня рассказываем, как это устроено.
Что такое архитектура ПО и для чего она нужна
Если по-простому, то архитектура программного обеспечения — это продуманный план развития программы.
Программа может состоять из большого количества функций, классов и объектов. В небольших сервисах можно просто открыть редактор для написания кода и набирать, добавляя новые возможности на ходу. Но чем дальше развивается и растёт такая программа, тем больше вероятность того, что она начнёт себя вести неожиданным образом — например, при добавлении новых возможностей старые вдруг начнут работать не так, как нужно.
В маленьких проектах почти всегда программу можно подправить или вообще переписать, если исправить уже невозможно. Но даже в таких небольших блоках кода и при понятном описании ошибок может быть тяжело найти проблему или понять, как нужно было делать, чтобы избежать промахов.
В больших программах без плана обойтись невозможно: над кодом работают чаще всего несколько человек, и нужно сделать так, чтобы сервис продолжал работать и через несколько лет даже при большом количестве изменений. Поэтому разработчики решили делать план с учётом всех требований к продукту.
Коротко — главное:
Если ваш проект небольшой — можно без архитектуры.
Если задумано что-то масштабное и потенциально грандиозное, нужно обязательно продумать все ходы и прописать детальный план развития, чтобы заранее понимать, куда движется программа.
Основные принципы архитектуры ПО
Из-за того, что все сервисы и приложения служат своим задачам, единого руководства по созданию универсальной архитектуры не существует. Но есть несколько советов при её создании, которые подходят почти ко всем вариантам ПО.
Архитектура системы должна начинаться с исследования. У будущей программы всегда есть заказчик, даже если это будете вы сами. Кроме заказчика, есть клиенты, предполагаемые сценарии использования, ресурсы, нагрузки. Всё это нужно собрать и посмотреть, как система будет работать в разных сценариях и ситуациях — это повлияет на то, какой подход для создания программы лучше выбрать.
Система по возможности должна быть разделена на независимые модули. Это означает, что кодовая база должна делиться на фрагменты, каждый из который будет отвечать за свою часть работы. Тогда проводить масштабирование, обновление и устранение неполадок будет удобнее и безопаснее. Компоненты должны быть связаны друг с другом как можно слабее, чтобы поломки и баги в одной части не несли критических последствий для других частей. Идеальный вариант — API или его аналог, когда модули обмениваются между собой данными в едином формате.
Приложение необязательно должно состоять из разных фрагментов, если есть другой вариант для отслеживания его работоспособности и развития. Но чаще всего это проще сделать, поделив программу на модули.
Части программы не должны зависеть друг от друга от верхних уровней к нижним. Например, код сервера не должен зависеть от формы авторизации на сайте. Это упрощает понимание системы и защищает от непредвиденных багов в важных частях сервисов.
Архитектура приложения должна предполагать возможность масштабирования. Самый очевидный сценарий: приложение вдруг стало популярным, нужно увеличить количество серверов, которые обслуживают пользователей. Если не учесть возможность масштабирования заранее, быстро добавить такие серверы и распределить нагрузку не получится.
Отказоустойчивость и безопасность. При проектировании нужно учитывать возможность ошибок и сбоев и предусмотреть алгоритмы действий в этих случаях. Самый простой пример — ограничивать пользователей программы в предоставлении прав, чтобы клиент не мог случайно получить доступ администратора.
Наблюдаемость и мониторинг. Чтобы видеть, как всё работает, разработчики и администраторы в идеале должны иметь доступ к метрикам и показателям. В несложных проектах можно обойтись без этого, но в крупных, от бесперебойной работы которых зависят много людей, это точно нужно.
Типы архитектурных стилей
В зависимости от первоначальных исследований разработчики получают понимание, по какому пути пойдёт их программа и как будет развиваться. Со временем начали появляться похожие решения, которые объединились в группы и стали архитектурными стилями.
Нельзя сказать, что один стиль лучше другого. Хотя одни стили используются чаще, это часто продиктовано другими условиями: количеством разработчиков в команде, ресурсами заказчика, специфическими задачами. Что использовать, будет определять ответственный за проектирование — архитектор.
На сегодня есть много архитектурных стилей — в Википедии их сейчас 35. Мы расскажем про два основных вида архитектуры ПО, остальные строятся на их основе.
Монолитная архитектура
Это самый популярный вид архитектуры для небольших сервисов и приложений.
Для следования этому стилю не нужно делать ничего специального — просто писать весь код, не разделяя его на модули. Это и есть монолит — вся кодовая база в одном месте.
Плюсы монолитной архитектуры:
- Писать монолитную архитектуру удобно, её просто тестировать и запускать.
- Благодаря тому что все функции находятся в одном месте, у разработчика или разработчиков есть чёткое представление о взаимосвязях внутри программы.
Минусы:
- С развитием поддерживать большую кодовую базу становится сложно. Большая программа превращается в громоздкую, работать с ней уже не так удобно.
- Из-за того, что у приложения есть только один центральный компонент, любые изменения в одной части могут вызвать изменения в другой.
- Если нужно изменить или масштабировать одну функцию или объект, сделать это может быть сложно, потому что в монолите чаще всего всё связано между собой.
Вот несколько крупных компаний, которые используют монолитную архитектуру, но не всегда ограничиваются только ей:
- GitHub;
- Twitter;
- Atlassian;
- Airbnb;
- SoundCloud;
- Netflix.
Микросервисная архитектура
Такая архитектура делит весь проект на сегменты — микросервисы.
Большое приложение может иметь отдельные микросервисы для каждой задачи. Получаются отдельные приложения: блок управления пользователями, работа с базой данных, обработка заказов, доставка, виджеты. Всё это как-то связано между собой, можно добавлять новые модули и менять их содержимое, не трогая способ взаимодействия.
Плюсы микросервисов:
- Поддерживать и развивать микросервисы проще, чем монолитную архитектуру, так как они слабо зависят друг от друга, поэтому можно изменять и обновлять один, не боясь разрушить общее приложение.
- На каждый микросервис можно выделять разных разработчиков. Эти команды несложно организовать, потому что микросервисы независимы.
Минусы:
- Это дороже и сложнее, чем монолитная архитектура.
- Взаимодействие между разными микросервисами всё равно нужно настраивать, потому что это всё-таки одно приложение. Это может быть сложно.
- Тестирование и безопасность могут требовать больше времени и подготовки, потому что система получается довольно сложная.
На микросервисах тоже строят свои продукты много известных компаний:
- Amazon;
- Uber;
- Coca-Cola;
- eBay;
- SoundCloud;
- Netflix.
Обратите внимание, что некоторые компании используют и монолитную, и микросервисную архитектуру. Поэтому необязательно строго придерживаться какого-то одного принципа, если работу удобнее организовать с одновременным использованием разных подходов.
Архитектурные паттерны
Кроме архитектурных стилей, есть ещё паттерны, или шаблоны. Это проверенные подходы к проектированию, которые хорошо справляются с уже известными задачами. Паттернов гораздо больше, чем стилей, потому что конкретных маленьких задач больше, чем глобальных по построению целого сервиса.
Большинство паттернов относится к микросервисной архитектуре, потому что взаимодействие в монолитном варианте намного проще.
Вот несколько примеров архитектурных паттернов.
Слои (layers) — паттерн монолитной архитектуры. Весь проект разделяется на несколько слоёв, и каждый уровень отвечает за отдельную задачу. В микросервисной архитектуре эти слои выносятся в отдельные сервисы.
Реестр сервисов (Service Registry). Паттерн микросервисов, при котором все они регистрируются в центральном реестре. При обращении одного микросервиса к другому он обращается к этому реестру и узнаёт текущий адрес нужного сервиса. Это даёт возможность для микросервисов обнаруживать друг друга прямо во время работы и часто используется во время масштабирования проекта.
Источник событий (Event Sourcing). Схема, при которой сохраняются все состояния системы — и текущее, и все предшествующие. Это даёт возможность восстановить состояние приложения на любой момент времени. Особенно полезно в сервисах, где важна история изменений и возможность отката.
Отдельная база данных для каждого сервиса (Database per Service). Каждый микросервис получает собственную базу, чтобы не зависеть от одного хранилища и изолировать данные разных сервисов. Иногда это работает хорошо, но бывают ситуации, когда проще вести всё в одной базе, чтобы не тратить силы на поддержку десятка разных баз и работу с ними.
API-композиция (API Composition). Решение, которое помогает получать данные из разных веб-сервисов после использования паттерна с отдельными базами данных. По этому шаблону создаётся отдельный API, который вызывает разные модули и соединяет полученные результаты в памяти.
Предохранитель (Circuit Breaker). Шаблон для предотвращения поломок. Если один из сервисов начинает давать сбои, Circuit Breaker закрывает к нему доступ, пока разработчики не починят систему. Это предотвращает перегрузку и позволяет восстановить общий сервис. Звучит просто и логично, но такой предохранитель не должен останавливать всю систему — а это уже сложная задачка при проектировании больших систем, где всё друг с другом связано.
Проектирование архитектуры ПО
Архитектура — это способ организации компьютерных программ. Но это не строгий свод правил и приёмов, поэтому недостаточно просто выучить паттерны и стили. Для проектирования нужно понимание как основных принципов работы программного обеспечения, так и опыт работы с конкретными технологиями.
Сам процесс тоже может различаться: архитектор может придумать схему в голове, нарисовать её, построить 3D-модель. Главное, чтобы ему самому было удобно работать и можно было объяснить исполнителям их конкретные задачи.
Кто разрабатывает архитектуру
Архитектуру чаще всего разрабатывают разработчики бэкенда. Это делают как опытные архитекторы, так и остальные программисты, чаще всего начиная уже с уровня джуна.
После развития до уровня сеньора бэкенд-разработчик может развиваться в трёх направлениях:
- ничего не менять, работать на позиции сеньора, продолжать расти в зарплате и получать новые, более сложные и серьёзные задачи как разработчик;
- стать тимлидом — организовывать команду, меньше работать с техникой;
- стать архитектором — больше работать с системой и технологиями, следить за развитием и правильной работой сервисов.
При этом навык проектирования архитектуры не приходит сам по себе, а в компаниях для повышения часто нужно уметь немного проектировать. Вот как может выглядеть такая градация в зависимости от позиции.
- Разработчик-джун выполняет понятные задачи, которые чаще всего ему объясняют более опытные разработчики. Он оттачивает свои навыки технологий, знакомится с командой и стеком инструментов. Часто он выполняет роль рабочих рук: работает в команде с мидлами или сеньорами, помогает с их задачами и перенимает опыт.
- Мидл должен уметь спроектировать и сделать небольшую часть проекта самостоятельно. Ему не нужно проектировать всю систему, но он должен уметь сделать её фрагмент, например загрузку страниц конкретного раздела сайта из бэкенда на фронтенд со всеми нужными связями с остальными компонентами приложения.
- Сеньор — опытный разработчик, который может взять на себя проектирование нескольких частей сервиса. Это ещё не архитектор, но специалист, который находится от него на ступень ниже.
- Архитектор — проектирует систему целиком и, возможно, сам разрабатывает некоторые модули приложения.
Преимущества хорошей архитектуры ПО
Одни из главных преимуществ, которые даёт хорошая архитектура, — предсказуемость ПО и наблюдаемость.
Предсказуемость программы даёт понимание, куда будет двигаться проект, как его масштабировать и каких проблем можно ожидать. С хорошим проектом команда знает уже на этапе исследования, сколько понадобится сил и времени на реализацию и может заранее усилить потенциально слабые места системы.
Наблюдаемость достигается за счёт прозрачности устройства системы и мониторинга — настроенной системы отслеживания состояния проекта. Зная структуру взаимодействия всех частей, можно добавить в каждую элементы для передачи состояния. Тогда часть сбоев будет видно заранее, а некоторые можно будет быстро починить.
Инструменты и методы архитектурного проектирования
Для проектирования необязательно использовать какие-то особенные инструменты или придерживаться жёстких подходов. Архитектору важно создать схему для себя, чтобы точно понимать взаимодействие составляющих проекта между собой.
На сегодня существует большое количество инструментов и стандартов для проектирования архитектуры ПО, в том числе для командной работы. Вот некоторые:
- UML (Unified Modeling Language) — язык для создания диаграмм классов;
- ArchiMate — открытый стандарт для моделирования корпоративной архитектуры;
- C4 Model — визуальный метод моделирования архитектуры;
- Microsoft Visio, Lucidchart и Draw.io — графические редакторы диаграмм и схем.
Выстроенная в графическом редакторе схема архитектуры приложения может выглядеть примерно так:
Самые распространённые ошибки при создании архитектуры приложения
Большинство ошибок при проектировании архитектуры сводятся к нарушению основных принципов, по которым её готовят:
- Не провести предварительное исследование и не установить требования к будущему приложению.
- Выбрать монолитную архитектуру без учёта возможности масштабирования.
- Провести проектирование без учёта разделения ответственности разных модулей.
- Спроектировать систему без документации.
- Не проанализировать возможные риски.
Как стать архитектором
Чтобы стать архитектором, сначала нужно стать разработчиком. Если хотите узнать, каково это, попробуйте курсы Практикума по разработке. На всех программах — уроки с актуальными на сегодня знаниями, проекты в портфолио, поддержка наставника и бесплатная часть для тех, кто хочет начать, но не знает как.