Репозиторий внутри

Модули

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

Раньше я придерживался политики доступа и права взаимодействия (теперь считаю это решение неверным, но для истории решил сохранить его):

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

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

Теперь мое мнение таково, что модули могут общаться друг с другом, но границы общения должны быть четко обозначены (например используя паттерн Медиаторов, пример реализации Module1Module2Mediator).

Структура модуля

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

Адрес к директории или файлуТипОписание
DocsFolderХранит документацию по текущему модулю
- README.mdFileФайл описывающий некоторые тонкости по использованию данного модуля
ConfigurationFolderХранит настройки модуля
- RouteProvider.phpClassРеализует маршрутизацию модуля (связь запросов и обработчиков запросов)
- DependencyInjectionProvider.phpClassРеализует подключение сервисов модуля в Dependency Injection Container
DataFolderDataAccess Layer - слой хранения данных (это сущности, модели и data-провайдеры внешних сервисов)
- UserFolderПример директории, в которой хранятся файлы по работе с пользователями
- - UserModel.phpModelКласс работы с пользователем (чистая модель - не хранит запросы по работе с др. таблицами бд). Нельзя бизнес-сервисы дергать из моделей.
- - UserDsp.phpServiceDsp (data source provider) - класс с функциями, в которых реализуется работа c данными. Очень важный момент: метод DSP всегда выполняет только одну функцию и не хранит бизнес-логику и не занимается форматированием/валидацией данных, его обязанность сохранить/возвратить/удалить данные. Пример: при работе с данными пользователей, таблица пользователей обязана быть главной таблицей из которой выбираются данные, остальные таблицы второстепенные (JOIN к ним может быть, а может и не быть).
- - EnumFolderМесто расположения файлов-списков, оформленный с помощью интерфейса с константами
- - - UserFieldEnum.phpInterfaceСписок полей в бд, которые могу быть названы с ошибками или на русском, в общем которые нужно зарефакторить, но времени на это пока нет
- - - UserTypeEnum.phpInterfaceСписок типов пользователя
BusinessFolderBusiness Layer - это Application Layer (слой хранения бизнес-логики предметной области)
- MedicalServiceFolderХранит сервисы медицинских услуг (поэтому имя директории содержит суфикс Service, иначе суфикс Service писать директории не нужно). Функции сервиса содержат только бизнес-логику (валидация или форматирование данных выполняется за его пределами).
- - DtoFolderХранит классы реализующих паттерн Dto
- - - SomeDto.phpClassИспользуется для передачи данных между подсистемами модуля/модулей
- - TemplateFolderХранит список файлов-шаблонов (мы используем twig по-умолчанию для всех backend шаблонов)
- - - MailTemplate.twigFileШаблон письма для отправки на email
- - FormatterFolderХранит классы позволяющих форматировать данные медицинских услуг
- - - MedicalServiceFormatter.phpServiceКлассов позволяющих форматировать данные услуг
- - MedicalFacade.phpServiceПозволяет взаимодействовать с медицинскими услугами (любой класс-фасад с именем из одного слова, обязан иметь суфикс Facade)
- PatientFolderХранит сервисы по работе с пациентами 
- - PatientFacade.phpServiceФасад - хранит все методы по работе с пациентом (тут объявляются все зависимости и существующие бизнес-трейты)
- - HandlerFolder

Директория хранит хендлеры по работе с пациентом, идеологично похожие но не имплементирующие RequestHandlerInterface Функция хендлера:

  • выполняет список вызовов в значении, подобном теории автоматов
  • не содержит проверок бизнес-логики (не содержит бизнесовых if-ов, например изменение логики поведения функции хендлера в зависимости от переданного значения)
  • может содержать условия валидация данных, проверки доступа (if-ы проверок параметров запроса)
  • может содержать условие на отдаваемый формат данных (if requestType == xml), только в том случае, когда в приложении нет последующего слоя-преобразователя данных
- - - PatientOrdersTrait.phpTraitТрейт реализует работу с заказами пациента
- - RequestFolderДиректория хранит объекты запросов (в данном примере потому, что PatientOrdersHandler.php доступен наружу)
- - - PatientOrdersRequest.phpClassОбъект запроса полученный с помощью JMS\Serializer\Annotation
- - ResponseFolderДиректория хранит объекты ответа (в данном примере потому, что PatientOrdersHandler.php доступен наружу)
- - - PatientOrdersResponse.phpClassОбъект ответа полученный с помощью JMS\Serializer\Annotation. Плюсы использования JMS\Serializer\Annotation: 
- строгая типизация запросов/ответов 
- ООП подход 
- автоматическая документация
- - - TranslationFolderДиректория хранит файлы переводов ответов с английского языка
- - - - Ru.yamlYmlФайл перевода с английского на русский
InfrastructureFolderТак называемый инфраструктурный слой, например классы реализующие какой-то общий функционал или расширяющие функциональность сторонних библиотек (бизнес-логики тут нет)
- LoggingFolderХранит файлы расширяющие функционал стороннего модуля для логирования (например Monolog)
- - EnumFolderХранит файлы-списки
- - - ChannelEnum.phpInterfaceСписком каналов логирования
- - ProcessorFolderХранит процессоры, которые обрабатывают данные логирования
- - - SessionProcessor.phpClassПроцессор, который обрабатывает каждую запись отправляемую в лог
- DatabaseFolderХранит классы реализующие работу с базой данных
- - MySQLFolderХранит классы по работе с б.д. MySQL
- - - EnumFolderХранит файлы-списки
- - - - TableNameEnum.phpInterfaceСписок таблиц б.д.
- - - - NumericEnum.phpInterfaceОсобенности целочисленных типов данных (пример)
- ValidationFolderКлассы валидации разного вида данных
- - ScalarValidator.phpServiceКласс с методами валидации скалярных данных
- MiddlewareFolderPresentation Layer - классы реализующие обработку запроса (отвечают за преобразование протоколов и кодирование/декодирование данных)
- - RequestFolderДиректория хранит Handler-классы реализующие MiddlewareInterface
- - ResponseFolderДиректория хранит Handler-классы реализующие паттерн ResponseListener
UIFolderuser interface — по́льзовательский интерфейс (Front-end)
- VueFolderХранит файлы и директории vue компонентов (структура SPA-приложения на Vue.js)
- - App.vueFileОсновной файл конфигурации текущего модуля
- - Router.vueFileОсновной файл роутов текущего модуля
- - ComponentFolder;Директория компонентов
- - - PatientOrdersFolderХранит файлы компонента, которые будут скомпилированы
- - - - PatientOrders.vueFileСодержит подключение шаблона, скрипта и стили vue компонента, все это будет скомпилировано
- - - - PatientOrders.jsFileСкрипт vue компонента
- - - - PatientOrders.cssFileСтили vue компонента
- - - - PatientOrders.htmlFileШаблон vue компонента
- BootstrapFolderПример расширения еще одно всем известной фронтенд библиотеки
- - ThemeFolderСобственная тема
- - - OfficeFolderМесто применения
- - - - Tree.cssFileФайл, который расширяет/переопределяет тему библиотеки
TestsFolderХранит тесты подсистем модуля
- FunctionalFolderХранит функциональные тесты подсистем модуля
- UnitFolderХранит одиночные тесты подсистем модуля
- bootstrap.phpFileautoload-файл для тестирования на основе подмены классов (используется только в модуле Core)
PatternFolderХранит список паттернов используемых в данном модуле (если паттерн используется в нескольких модулях, то кладется в Core\Pattern
- DaoInterface.phpInterfaceИнтерфейс для правильной реализации паттерна

В выше обозначенной структуре важно, чтобы имена директорий/файлов пишутся в стиле UpperCamelCase (PascalCase)

UI (Frontend)

Код интерфейса лучше хранить в отдельной директории модуля. Предлагаю, рассмотреть вариант, когда UI написан на языке JavaScript и популярном сейчас фреймворке Vue (главной особенностью которого является факт того, что все в нем является компонентом).

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

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

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

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

Например:

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

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

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

Источник: 1 - 2- 3 - 4 - 5 - 6 - 7 - 8 - 9


04.09.2008 11:06

Комментарии

Комментариев пока нет.


Copyrights © 2007 - 2026 YaPro.Ru