мне нужна помощь с чем-то я не могу получить мою голову обернутые вокруг относительно Repository и Услуги/Использование регистра модель (часть DDD дизайн) Я хочу реализовать в своем следующем проекте (Laravel PHP) ,Структура данных из хранилища для всех целей?
Все кажется ясным. Только одна часть DDD, которая запутывает, это структуры данных из репозиториев. Кажется, что люди выбирают структуры данных, которые должен вернуть репозиторий (массивы или сущности), но все это имеет недостатки. Один из них - это работа, в которой я смотрел свой опыт в прошлом. И один из них - у вас нет интерфейсов для простых структур данных (массива или простых атрибутов объекта).
Начну с объяснения опыта, имеющегося у меня с предыдущим проектом. У этого проекта были недостатки, но некоторые хорошие сильные стороны, которые я узнал и которые хотели видеть в моем новом проекте, но с решением некоторых ошибок дизайна.
Предыдущий опыт
В прошлом я создать сайт, который был API Centric с использованием рамок Kohana и Doctrine 2 ОРМ (данные модели преобразователя). Поток выглядел следующим образом:
Сайт контроллер → API клиент (HMVC вызовов) → контроллер API → Пользовательские Repository → Doctrine 2 ORM родной Repository/Entity-менеджер
Мой заказ Repository вернулся простые массивы, используя Doctrine2 DQL , Doctrine2 рекомендует данные результата массива для операций чтения. И да, это сделало мой сайт приятным и легким. Контроллер API просто преобразовал данные массива в JSON. Просто как тот.
В прошлом моя компания создала проекты, полностью опираясь на загруженные объекты Doctrine2, и это то, о чем мы сожалели из-за производительности.
Мой REST API поддерживается запросы, как
/api/users?include_latest_adverts=2&include_location=true
на ресурсе пользователей. Контроллер API передал include_location
в репозиторий, который напрямую включал отношение местоположения. Контроллер прочитал latest_adverts=2
и вызвал репозиторий рекламы, чтобы получить последние 2 рекламы каждого пользователя. Массивы были возвращены.
Например, первый массив пользователя:
[
name
avatar
adverts [
advert 1 [
name
price
]
advert 2 [
….
]
]
]
Это оказалось очень успешным. Весь мой сайт использовал API. Было бы очень легко добавить нового клиента, потому что API был совершенно в производстве, уже используя oauth. Весь сайт работает на нем.
Но этот дизайн также имел недостатки. Мой контроллер по-прежнему содержал много логики для валидации, рассылки, параметров или фильтров, таких как has_adverts=true
, чтобы получить пользователей только с объявлениями. Это означало бы, что если бы я создал новый порт, как новый новый интерфейс CLI, мне пришлось бы дублировать многие из этих контроллеров из-за всей проверки и т. Д. Но не дублирование, если бы я создал новый клиент. Таким образом, по крайней мере одна проблема была решена :-)
Мои панели администратора были полностью связаны с репозиторием/entity-менеджером doctrine2, чтобы ускорить разработку (вроде). Зачем? Поскольку у моего API были контроллеры жира с особыми функциональными возможностями только для веб-сайта (специальная проверка, отправка по почте для регистрации и т. Д.). Мне пришлось бы повторить работу или рефакторинг.Поэтому решили использовать объекты непосредственно, чтобы по-прежнему иметь четкий способ написания кода вместо того, чтобы переписывать все мои контроллеры API и переместить их в Службы (например, для сайта & admin). Время было проблемой при исправлении ошибок дизайна.
Для моего следующего проекта я хочу, чтобы весь код прошел через мои собственные репозитории и службы. Один поток для хорошего разделения.
Нового проект (используя DDD идею) и дилемму со структурами данных
Хотя мне нравится идея будет API, ориентированными, я не хочу, чтобы мой следующий проект будет API, ориентированной в ядре, потому что я думаю, такая же функциональность должна быть доступна без протокола HTTP между ними. Я хочу создать ядро, используя идеи DDD.
Но мне понравилась идея с использованием слоя, который просто говорил как API и возвращает простые массивы. Идеальная база для любого нового порта, включая мой собственный интерфейс. Моя идея состоит в том, чтобы рассмотреть мои классы обслуживания как интерфейс API (вернуть данные массива), выполнить проверку и т. Д. Я мог бы иметь Службы специально для веб-сайта (регистрации) и простых служб, используемых администратором или фоновыми процессами. В некоторых случаях администрирования служба не требуется в любом случае для простого редактирования CRUD, я мог бы просто использовать репозитории напрямую. Контроллеры были бы очень тонкими. С этим созданием реального REST API просто возникнет вопрос о создании новых контроллеров с использованием тех же сервисов, которые выполняются моими интерфейсами контроллера.
Для внутренней логики, такой как бизнес-правила, было бы полезно иметь объекты (прозрачные интерфейсы) вместо массивов из репозиториев. Таким образом, я мог бы извлечь выгоду из определения некоторых методов, которые использовали некоторую логику на основе атрибутов. НО Если бы я использовал Doctrine2, и мои репозитории всегда возвращали Entities, мое приложение получило бы большой успех!
Одна структура данных обеспечивает производительность, но без четких интерфейсов, другая обеспечивает четкие интерфейсы, но плохую производительность при использовании шаблона Data Pattern, такого как Doctrine 2 (сейчас или в будущем). Также я мог бы привести к двум типам данных, которые были бы запутанными.
Я думал, что-то подобное этому потоку:
контроллер (тонкий) → UserService (. Включая проверки) → UserRepository (только для хранения) → красноречивый ОРМ
Почему Eloquent вместо Doctrine2? Потому что я хочу немного придерживаться того, что принято в рамках Laravel и сообщества. Поэтому я мог бы извлечь выгоду из модулей сторонних разработчиков, например, для создания интерфейсов администратора или аналогичных моделей на основе моделей (в обход моих правил DDD). Помимо использования сторонних модулей, я бы разработал свой основной материал, поэтому переключение всегда должно быть простым и не влиять на выбор структуры данных или производительность.
Eloquent - это шаблон activerecord. Поэтому у меня возникнет соблазн преобразовать эти данные в объекты POPO, такие как Doctrine2. Но нет ... как сказано выше, с доктринами2 реальных моделей сделает систему очень толстой. Поэтому я снова возвращаюсь к простым массивам. Знание этого будет работать как для любой другой реализации в будущем.
Но он чувствует себя плохо, всегда полагается на массивы. Особенно при создании внутренних бизнес-правил. Разработчику придется угадывать значения в массивах, не иметь автозаполнения в своей среде IDE, не может иметь специальных методов, например, в классах Entity. Но делать два способа борьбы с данными тоже плохо. Или я просто слишком совершенен;) Я хочу ОДИН ясную структуру данных для всех!
Интерфейсы здания и POPO будут означать много дублирования работы.Мне нужно было бы преобразовать модель Eloquent (только файл mapper, а не сущность) в объект объекта, реализующий этот интерфейс. Все это дополнительная работа. И в конечном итоге мой последний слой будет похож на API, таким образом, снова преобразуя его в массивы. Это тоже лишняя работа. Массивы снова кажутся сделкой.
Казалось, что так легко читать в DDD и Hexagonal. Кажется, так логично! Но на самом деле я борюсь с этой простой проблемой, пытаясь придерживаться принципов ООП. Я хочу использовать массивы, потому что это единственный способ быть на 100% уверенным, что я не зависим от выбора модели и запроса на выбор из моего ORM относительно производительности и т. Д. И не имею дублирования в преобразовании в массивы для представлений или API. Но нет четкого договора о том, как может выглядеть пользовательский массив. Я хочу ускорить свой проект, используя эти шаблоны, а не замедлить их :-) Так что не вариант иметь много конвертеров.
Теперь я прочитал много тем. Один делает интерфейсы POPO &, которые соответствуют нормальным объектам, таким как Doctrine2, могут вернуться, но со всей дополнительной работой для Eloquent. Переключение на Doctrine2 должно быть довольно простым, но это может повлиять на производительность настолько плохо или нужно будет преобразовать данные массива Doctrine2 в эти собственные интерфейсы сущностей. Другие предпочитают возвращать простые массивы.
Один человек убеждает людей использовать Doctrine2 вместо Eloquent, но они не учитывают тот факт, что Doctrine2 тяжелый, и вам действительно нужно использовать результаты массива для операций только для чтения.
Мы проектируем хранилища, чтобы изменить их? Не потому, что это «приятно» только по дизайну. Итак, как мы можем полагаться на полные сущности, если это оказывает такое большое влияние на производительность или дублирующую работу? Даже при использовании Doctrine2 только (в сочетании) эта же проблема возникла бы из-за ее производительности!
Все реализации ORM могли бы возвращать массивы, таким образом, не было бы дублирования работы. Хорошая производительность. Но мы пропускаем четкие контракты. И у нас нет интерфейсов для массивов или атрибутов класса (в качестве обходного пути) ... Ugh;)
Я просто пропустил недостающий блок на наших языках программирования? Интерфейсы на простых структурах данных?
Можно ли сделать все массивы и передовую бизнес-логику говорить с этими массивами? Таким образом, нет классов с четкими интерфейсами. Любые предварительно просчитанные данные (обычно возвращаемые методом Entity) будут находиться внутри ключа массива, определенного классом Service. если не мудро, какова альтернатива, учитывая все вышеперечисленное?
Я был бы очень признателен, если бы кто-то с большим опытом работы в этом «домене» с учетом производительности, различных реализаций ORM и т. Д. Мог рассказать мне, как он/она справился с этим?
Заранее благодарен!