Skip to main content

Краткий обзор архитектуры

Astral Architecture Guide состоит из архитектурных слоев, некоторые слои делятся на сегменты.

CommonScheme

Зависимости между слоями/сегментами приложения направлены сверху вниз.

Нижестоящий слой/сегмент ничего не должен знать о вышестоящем.

Пример структуры проекта:

├── app/                          
├── screens/
├── modules/
├── data/
└── shared/

Shared. Независимость от низкоуровневых реализаций и библиотек

Shared

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

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

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

Пример структуры Shared для React стэка:

├── app/                          
├── screens/
├── modules/
├── data/
└── shared/
| ├── constants/
| ├── types/
| ├── utils/
| ├── services/
| ├── stores/
| ├── ui/
| | ├── components/
| | ├── hooks/
| | ├── external.ts
| | └── index.ts
| └── index.ts

Data. Работа с данными приложения

Data

Data слой отвечает за работу с данными:

  • Получения данных из источников (сервер, localStorage…)
  • Агрегация и форматирование данных
  • Кэширование и модификация кэша
  • Распространение типов DTO по приложению

Data позволяет:

  • Защитить приложение от изменений API
  • Отвязаться от источника данных и метода их получения

Data содержит два сегмента:

  • Repositories . Facade, предоставляющий данные приложению.
  • Sources. Сервисы, отвечающие за получение данных из разных источников. Sources может быть автосгенерированным
├── app/                          
├── screens/
├── modules/
├── data/
| ├── repositories/
| ├── sources/
| └── index.ts
└── shared/

Sources

Sources - сегмент с сервисами без логики, ответственные только за получение данных из различных источников. Источник может быть любой: API, localStorage…

Sources не занимаются форматированием данных, они просто их достают из источника и передают Repository.

Repositories

Repositories - это сервисы, используемые в Modules для работы с данными. Данные в Modules запрашиваются только через Repositories.

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

Разработка через Contract First

Архитектурный подход предоставляет удобный инструмент для разработки в случае, когда API еще не реализовано, но уже есть контракты (Contract First).

Contract First подход

Modules. Ориентированность на бизнес

Modules

Modules - самый важный слой приложения. Modules должен иметь высокое покрытие тестами.

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

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

В Astral Architecture предметная область разбивается на подобласти (модули), в рамках которых существуют свои термины, сущности и бизнес процессы.

Благодаря модульности проект может масштабироваться: модуль может быть отдан на разработку другой команде или вынесен в независимый микрофронтенд.

Модуль содержит два сегмента:

  • Features. Фичи, поставляемые модулем
  • Domain. Чистая бизнес-логика, поставляемая модулем

Пример структуры:

├── app/                          
├── screens/
├── modules/
| └── payment/
| | ├── features/
| | ├── domain/
| | └── index.ts
├── data/
└── shared/

Features. Фичи приложения

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

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

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

Features

Пример структуры:

├── app/                          
├── screens/
├── modules/
| └── payment/
| | ├── features/
| | | ├── PaymentSwitch/
| | | ├── CardPayment/
| | | ├── CashPayment/
| | | └── index.ts
| | ├── domain/
| | └── index.ts
├── data/
└── shared/

Feature содержит в себе все необходимое для работы:

  • UI компонент, отвечающий только за отрисовку фичи. В компоненте не реализуется никакая логика
  • Логику фичи. Вся логика фичи, включая ui-логику, реализуется вне ui компонента
  • Стили компонента
  • Другие UI компоненты, входящие в состав основного компонента
  • Другие программные сущности необходимые для корректной работы фичи

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

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

  • state manager
  • hook (React стэк)
  • service

Отделение view слоя от логики дает следующие преимущества:

  • Возможность изменять логику и ui независимо
  • Простота переиспользования логики или ui по необходимости
  • Независимость от используемого фреймворка. Фреймворк при определенных обстоятельствах можно заменить, а логику переиспользовать
  • Простота тестирования. Можно тестировать отдельно логику и ui
  • Однозначность расположения логики. Вся логика всегда находится в одном месте
  • Логика не “размазывается” по компонентам. Избавляет от сложностей в поддержке кода
  • Повышение читаемости кода
  • Упрощение поддержки и доработки приложения

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

Domain. Чистая бизнес-логика

Domain содержит :

  • Чистую логику, реализующую бизнес-требования
  • Логику, переиспользуемую между фичами или в других модулях
  • Работу с данными, взаимодействие с Data
  • Типы, описывающие особенности предметной области
  • Константы, относящиеся к предметной области

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

Пример структуры:

├── app/
├── screens/
├── modules/
| └── cart/
| | ├── features/
| | └── domain/
| | | ├── services/
| | | ├── stores/
| | | | ├── CartStore/
| | | | └── index.ts
| | | ├── utils/
| | | ├── types/
| | | ├── constants/
| | | └── index.ts
| | └── index.ts
├── data/
└── shared/

Screens. Место, где собираются фичи приложения

Screens

Screens - это экраны приложения.

Скрины собираются из features разных модулей. Здесь же происходит интеграция features.

Screens используется в роутинге Application для привязки к рутам приложения и взаимодействия с окружением роутинга (например, query params).

Пример структуры:

├── app/                          
├── screens/
| ├── Feedback/
| ├── NoAccess/
| ├── NotFound/
| ├── PopularGoods/
| ├── NewGoods/
| | ├── NewGoods.tsx
| | ├── store/
| | └── index.ts
| └── index.ts
├── modules/
├── data/
└── shared/

Application. Единственный слой, зависимый от специфики окружения и фреймворка

Application

Application слой является единственным слоем, который:

  • Зависит от окружения
    • Особенности сборщика
    • Работа с env
  • Зависит от специфичности используемого фреймворка
  • Зависит от низкоуровневых реализаций (используемых библиотек)

Application слой содержит:

  • Роутинг приложения
  • Инициализацию/настройку приложения и всех сервисов

Пример структуры для React:

├── app/ 
| ├── Routing/
| └── App.tsx
├── screens/
├── modules/
├── data/
└── shared/

Пример структуры для Nextjs:

├── pages/          # pages является application слоем (Nextjs специфичность)
| ├── index.tsx
| ├── _app.tsx
├── screens/
├── modules/
├── data/
└── shared/

Тестирование

Тестирование в Astral Architecture Guide являются важной частью проектируемой системы.

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

В Astral Architecture Guide описаны принципы тестирования, позволяющие реализовывать важные атрибуты тестирования:

  • Защита от багов
  • Устойчивость к рефакторингу - низкий уровень хрупкости
  • Скорость выполнения
  • Простота поддержки