Проект со сложной логикой на Symfony – как проектировать? Примеры?
Здравия!
NOTE: сразу прошу прощения за длиннопост.
Начинаю проектировать новый проект, в котором будет:
* Много странной/сложной логики (вроде "когда пятая планета в фазе сириуса на шестом дне от седьмой среды после 42 недели високосного года, но только если во-о-о-он тот пост не старше недели"), в которой критериев для состояния чего-либо может быть не один уровень. Однако, Внешнее API немногим сложнее типичного CRUD'а.
* Уровни доступа для групп пользователей (которые можно создавать через админку) вплоть до каждого параметра некоторых бизнес-моделей. Например:"Вот в этой табличке вон тот столбец могут видеть только такие-то группы юзеров".
* Много дополнительных автоматических действий при совершении какого-либо действия типа "при изменении значения вот в этой ячейке этой таблицы сделать то, сё, пятое, десятое и компот". Цепочки могут быть достаточно длинными и глубокими чтобы не помнить их не вооружившись ТЗ. Многие из них должны быть отложенными или асинхронными ибо могут быть тяжёлыми.
* Основная работа – с внешними сервисами по API, с дублированием некоторых сервисов на уровне бизнес логики типа "Если при совершении действия сервис1 отвалился – пробовать сервисы 2,3,...,100500 пока не получится, в таком-то порядке по такому-то критерию".
* Долгоживучесть проекта – и поддерка, и допиливание логики, которую невозможно предусмотреть сейчас. Годами.
* Проект будет представлять из себя API – никаких шаблонов/вёрстки/фронта там не предполагается. Точнее, оно будет, но отдельным проектом, возможно, на Angular.
В качестве фреймворка предполагаю взять Symfony – с ним ещё не довелось работать, но, судя по их книге, кажется, не нужно будет бороться с ним в проекте такого типа.
Ближе к вопросам.
Чтобы всё не превратилось в очень жирные модели – репозиторий отдельно, модели отдельно (Доктрина, я читал, умеет – велосипед не надо изобретать). Как хранить бизнес-логику чтобы модели не превратились в монстров из десятков тысяч строк? Читал про Command Bus где, если правильно понял, на каждое действие в системе – свой класс? Как их организуете (их тогда будут сотни)?
Есть ли смысл выносить каждую доменную модель в модуль/микросервис, хранить всю связанную логику где-то там внутри, а с остальными общаться по внешнему API? За ответы в клиентскую часть – отдельный сервис-фронтенд? Каков оверхед? Используют ли такое на практике? Какие подводные камни?
Раньше для дополнительных действий мне достаточно было использовать что-то вроде beforeUpdate/afterCreate модели. Сейчас же эти методы рискуют стать гигантскими и очень сложными даже если выносить логические куски в отдельные методы. К тому же, многие из них будут вынесены в очередь задач (в rabbitmq, например) и обработаны асинхронно. Но некоторые – нет и в каких-то случаях будет очень важна последовательность выполнения хуков. Как не превратить кидание/получение событий типа PostBeforeEdit/PostBeforeEditHandler в "callback hell"? В одном похожем проекте я такое видел (правда, на js) – при каждом клике никогда не знаешь сколько десятков действий произойдёт, даже вооружившись отладчиком. Было бы хорошо держать конфиг подобной логики человекочитабельным и в одном месте – как вы это решаете?
ACL. Где храните указанную логику? Сетку предполагаю хранить в базе и кэшировать. Какие структуры для описанного выше – best practice? В моём понимании это выглядит как куча трёхмерных кубов доступа "crud – group – entity – field", как это сделать более плоским пока только одна идея – делать кучу таблиц many-to-many. Но мне кажется, что работа с этими "джойнами" при каждом запросе будет вторым узким местом после внешних api.
Версионирование. Как вы версионируете подобные проекты? А если нужна "N-1" рабочая версия на продакшене? Сейчас храню в разных ветках git'а и деплою их отдельно. Есть ли смысл разделять версии в рамках единой кодовой базы проекта и как (неймспейсы, конфиг, модуль, что-то ещё)?
И, самое главное – как всё это совместить? По отдельности вышеописанное уже применял на практике. Но всё и сразу в голове не укладывается. На какие проекты (точнее, на код) можете посоветовать посмотреть для лучшего понимания? Ссылки на репозитории?
Заранее спасибо тем, кто осилит длиннопост, поделится своим опытом и, возможно, пришлёт пример на код подобного проекта.