Архитектура приложения в репозитории

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

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

Архитектура приложения в репозитории

Иногда слои организуют таким образом, чтобы бизнес-логика полностью скрывала источник данных от представления. Чаще, однако, код представления может обращаться к источнику данных непосредственно. Хотя такой вариант менее безупречен с теоретической точки зрения, в практическом отношении он нередко более удобен и целесообразен: код представления может интерпретировать команду пользователя, активизировать функции источника данных для извлечения подходящих порций информации из базы данных, обратиться к средствам бизнес-логики для анализа этой информации и осуществления необходимых расчетов и только затем отобразить соответствующую картинку на экране. (Мартин Фаулер, книга "Архитектура корпоративных программных приложений")

В проектировании приложения мы придерживаемся следующих постулатов:

Структура

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

Имя модуля Описание Доступ
Core ядро проекта не может взаимодействовать ни с одним модулем системы, но любой модуль может взаимодействовать с модулем Core
Report отчеты/статистика может взаимодействовать с любым модулем, но ни один модуль не может взаимодействовать с модулем Report
ModuleName любой другой модуль может взаимодействовать только с модулем Core, ни один модуль не может взаимодействовать с модулем ModuleName

Данные правила доступа обусловлены требованием обеспечить минимальную связанность модулей проекта + исключить возможную рекурсию. 
Стоит заметить, что UI посредством Front Controller-a может взаимодействовать с Command Hadler-ом любого модуля.

Структура модуля имеет обязательные и необязательные директории, ниже изложена структура модуля, описанная максимально абстрактно, но с примерами реализации. Итак, рассмотрим возможное содержимое директории src/ModuleName/

Адрес к директории или файлу Тип Описание
Docs Folder Хранит документацию по текущему модулю
- README.md File Файл описывающий некоторые тонкости по использованию данного модуля
Configuration Folder Хранит настройки модуля
- RouteProvider.php Class Реализует подключение роутингов модуля в объект RouteCollection
- DependencyInjectionProvider.php Class Реализует подключение сервисов модуля в Dependency Injection Container
Command Folder Command Handler - хранит файлы-команд, которые могут быть запущены из консоли
- MedicalServiceSyncCommand.php Class Файл содержит список инструкций по синхронизации медицинских услуг (паттерн Command)
Data Folder DataAccess Layer - слой хранения данных (это сущности, модели и data-провайдеры внешних сервисов)
- User Folder Пример директории, в которой хранятся файлы по работе с пользователями
- - UserModel.php Model Класс работы с пользователем (чистая модель - не хранит запросы по работе с др. таблицами бд). Нельзя бизнес-сервисы дергать из моделей.
- - UserDsp.php Service Dsp (data source provider) - класс с функциями, в которых реализуется работа c данными. Очень важный момент: метод DSP всегда выполняет только одну функцию и не хранит бизнес-логику и не занимается форматированием/валидацией данных, его обязанность сохранить/возвратить/удалить данные. Пример: при работе с данными пользователей, таблица пользователей обязана быть главной таблицей из которой выбираются данные, остальные таблицы второстепенные (JOIN к ним может быть, а может и не быть).
- - Enum Folder Место расположения файлов-списков, оформленный с помощью интерфейса с константами
- - - UserFieldEnum.php Interface Список полей в бд, которые могу быть названы с ошибками или на русском, в общем которые нужно зарефакторить, но времени на это пока нет
- - - UserTypeEnum.php Interface Список типов пользователя
Business Folder Business Layer - это Application Layer (слой хранения бизнес-логики предметрой области), мы придерживаемся SOA (Service Layer по Маринеску)
- MedicalService Folder Хранит сервисы медицинских услуг (поэтому имя директории содержит суфикс Service, иначе суфикс Service писать директории не нужно)
- - Dto Folder Хранит классы реализующих паттерн Dto
- - - SomeDto.php Class Используется для передачи данных между подсистемами модуля/модулей
- - Template Folder Хранит список файлов-шаблонов (мы используем twig по-умолчанию для всех backend шаблонов)
- - - MailTemplate.twig File Шаблон письма для отправки на email
- - Formatter Folder Хранит классы позволяющих форматировать данные медицинских услуг
- - - MedicalServiceFormatter.php Service Классов позволяющих форматировать данные услуг
- - MedicalFacade.php Service Позволяет взаимодействовать с медицинскими услугами (любой класс-фасад с именем из одного слова, обязан иметь суфикс Facade)
- Patient Folder Хранит сервисы по работе с пациентами 
- - PatientFacade.php Service Фасад - хранит все методы по работе с пациентом (тут объявляются все зависимости и существующие бизнес-трейты)
- - Handler Folder Директория хранит хендлеры по работе с пациентом, идеологично похожие но не имплементирующие RequestHandlerInterface
- - - PatientOrdersTrait.php Trait Трейт реализует работу с заказами пациента
- - Request Folder Директория хранит объекты запросов (в данном примере потому, что PatientOrdersHandler.php доступен наружу)
- - - PatientOrdersRequest.php Class Объект запроса полученный с помощью JMS\Serializer\Annotation
- - Response Folder Директория хранит объекты ответа (в данном примере потому, что PatientOrdersHandler.php доступен наружу)
- - - PatientOrdersResponse.php Class Объект ответа полученный с помощью JMS\Serializer\Annotation. Плюсы использования JMS\Serializer\Annotation:
- строгая типизация запросов/ответов
- ООП подход
- автоматическая документация
- - - Translation Folder Директория хранит файлы переводов ответов с английского языка
- - - - Ru.yaml Yml Файл перевода с английского на русский
Lib Folder Классы реализующие какой-то общий функционал или расширяющие функциональность сторонних библиотек (бизнес-логики тут нет)
- Monolog Folder Хранит файлы расширяющие функционал стороннего модуля для логирования
- - Enum Folder Хранит файлы-списки
- - - ChannelEnum.php Interface Списком каналов логирования
- - Processor Folder Хранит процессоры, которые обрабатывают данные логирования
- - - SessionProcessor.php Class Процессор, который обрабатывает каждую запись отправляемую в лог
- Database Folder Хранит классы реализующие работу с базой данных
- - MySQL Folder Хранит классы по работе с б.д. MySQL
- - - Enum Folder Хранит файлы-списки
- - - - TableNameEnum.php Interface Список таблиц б.д.
- - - - NumericEnum.php Interface Особенности целочисленных типов данных (пример)
- Helper Folder Общие классы нашей команды, которые могут пригодится в любом месте кода
- - Validation Folder Классы валидации разного вида данных
- - - ScalarValidator.php Service Класс с методами валидации скалярных данных
- Middleware Folder Presentation Layer - классы реализующие обработку запроса (отвечают за преобразование протоколов и кодирование/декодирование данных)
- - Request Folder Директория хранит Handler-классы реализующие MiddlewareInterface
- - Response Folder Директория хранит Handler-классы реализующие паттерн ResponseListener
UI Folder user interface — по́льзовательский интерфейс (Front-end)
- Vue Folder Хранит файлы и директории vue компонентов (структура SPA-приложения на Vue.js)
- - App.vue File Основной файл конфигурации текущего модуля
- - Router.vue File Основной файл роутов текущего модуля
- - Component Folder; Директория компонентов
- - - PatientOrders Folder Хранит файлы компонента, которые будут скомпилированы
- - - - PatientOrders.vue File Содержит подключение шаблона, скрипта и стили vue компонента, все это будет скомпилировано
- - - - PatientOrders.js File Скрипт vue компонента
- - - - PatientOrders.css File Стили vue компонента
- - - - PatientOrders.html File Шаблон vue компонента
- Bootstrap Folder Пример расширения еще одно всем известной фронтенд библиотеки
- - Theme Folder Собственная тема
- - - Office Folder Место применения
- - - - Tree.css File Файл, который расширяет/переопределяет тему библиотеки
Tests Folder Хранит тесты подсистем модуля
- Functional Folder Хранит функциональные тесты подсистем модуля
- Unit Folder Хранит одиночные тесты подсистем модуля
- bootstrap.php File autoload-файл для тестирования на основе подмены классов (используется только в модуле Core)
Pattern Folder Хранит список паттернов используемых в данном модуле (если паттерн используется в нескольких модулях, то кладется в Core\Pattern
- DaoInterface.php Interface Интерфейс для правильной реализации паттерна

В выше обозначенной структуре есть важные моменты:

  1. любой объект обязан быть создан с помощью DependencyInjectionProvider.php кроме объекта, экземпляров которого может быть одновременно несколько, например: Model, CDbCriteria, Entity, EntityAttributeValue, DataTransferObject, ValueObject
  2. Configuration-классы не имеют никаких состояний провайдера и не должны использовать других зависимых классов (должны быть final)
  3. имена директорий/файлов пишутся в стиле UpperCamelCase (PascalCase)

UI (Frontend)

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

На примере PatientOrders-а, это директория: www/UI/ModuleName/PatientOrders в которой js, css и html, будет скомпилированны в Build.js

Файл Build.js не должен попасть в git индекс, поэтому следует добавить в .gitignore игнорирование всех файлов Build.js

Если предполагаются какие-либо медиа-файлы, то их следует размещать в директории www/Resource/ModuleName/PatientOrders/

Например:

Путь Описание
www/Resource/ModuleName/PatientOrders/Image Директория с изображениями
www/Resource/ModuleName/PatientOrders/Pdf Директория с PDF-документами
www/Resource/ModuleName/PatientOrders/Zip Директория с архивами

Директории UI и Resource расположены выше по иерархии по следующим причинам:

  • нет нагроможденности в директории www (всего две директории: UI и Resource, вместо Х директорий равных кол-ву директорий модулей)
  • удобный роутинг (удобно конфигурировать роутинг статики на веб-сервере)
  • удобно монтировать директории (часто директории UI и Resource являются монтированными имея общее единое место хранения)

Источник: 1 - 2 - 3 - 4

Оцени публикацию:
  • 1,5
Оценили человек: 1

Похожие статьи:


Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Сколько будет Οдин + Τри
Главная
X

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2019 YaPro.Ru

Главная » Веб-мастеру » Интересное »