Laravel Выбор Framework

Sufir

Я не волшебник, я только учусь
Генерируй id до регистрации, откажись от AUTO_INCREMENT. nextval(), например (Postgres, Oracle, любая-нормальная-СУБД). В MySQL можно эмулировать. Я лично стараюсь не юзать AUTO_INCREMENT, избавляет от многих проблем.
Не так давно к этому пришел, насколько всё проще, удобнее и изящнее стало.
 

fixxxer

К.О.
Партнер клуба
Меня смущает, что на практике скорее всего придётся использовать и числовой (для FK, для производительности, для human readablity, etc.) и UUID одновременно.
Ридабилити понятно, а в остальном не вижу проблем c PK/FK полями типа uuid. В мыскле, правда, придется ручками в binary(16), вот тут уж не знаю, насколько это (не)эффективно.
 

stalxed

Новичок
Генерируй id до регистрации, откажись от AUTO_INCREMENT. nextval(), например (Postgres, Oracle, любая-нормальная-СУБД). В MySQL можно эмулировать. Я лично стараюсь не юзать AUTO_INCREMENT, избавляет от многих проблем.
Ну допустим есть какой-то write сервис. Он ничего не возвращает, отлично.
Принимает комманду UserRegistrationCommand{public $username, public $password, public $email}.
Этот сервис уже использует фабрику, ну допустим фабрика умеет генерировать значение сама, ,без разницы как, дальше мы передаем построенный объект(с сгенерированным id) репозиторию(методу add, к примеру), он выполняет всю необходимую работу по сохранению в БД. Ну и это всё оборачиваем в транзакцию. И вот дальше получается, что сервис должен вернуть клиенту(Rest Api, Html Web, Cron) IDшник.
Т.е. write сервис уже возвращает значение.
В книге IDDD Вернана круто описано, мол можно вообще write команды взять пустить в тот же RabbitMQ и забыть про них, consumerы когда-то там выполнят регистрацию пользователя...
А что пользователю показывать в это время?
И что вот делать с ошибками, которые нельзя отвалидировать на презентационном уровне?
 

Вурдалак

Продвинутый новичок
Код:
-UserRegistrationCommand{public $username, public $password, public $email}
+UserRegistrationCommand{$id, public $username, public $password, public $email}.
В некоторых системах id вообще генерят на клиенте (в браузере).
И что вот делать с ошибками, которые нельзя отвалидировать на презентационном уровне?
А какое это отношение имеет к CQRS? :) Если ты юзаешь асинхронные команды, то будь готов к тому, что фидбек будет сложнее. Через различные нотификации, если оно клиенту вообще нужно. Регистрация в данном случае неудачный пример, тут обычно требуется синхронность. А вот удаление альбома с кучей фоток — вполне можно выполнить асинхронно, предупредив пользователя, что операция займёт некоторое время.
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
И что вот делать с ошибками, которые нельзя отвалидировать на презентационном уровне?
В js как-то спокойно все обходятся promises/a+, если обобщать - то смотрим в сторону монадической валидации. CQRS здесь действительно никоим местом. :)
 

stalxed

Новичок
А если вернуться как раз к такому типичнейшему действию как регистрация.
1) Пользователь ввел login, email, password.
2) Команду можем делать только синхронной, пользователю нужен ответ.
3) Отправляем сервису login, email, password - получаем id...
У нас уже не CQRS.
На клиенте генерировать ID это уже имхо дико.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
nextval() в Postgres - точно такое же нарушение CQS, как и любая increment-and-return функция - в memcached, shared memory, etc

соблюдать CQRS можно только исполняя последовательно и независимо все 4 действия по отдельности: ставим блокировку, инкрементим, выбираем последнее значение, снимаем блокировку,
реализовать это в условиях многопоточности и негарантированной передачи данных достаточно сложно потому что клиенты не будут снимать блокировку
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Не.

Проблема с инкрементом возникает в случае, если нам важно значение инкрементируемой переменной (скажем, счетчик какой-то). А с nextval() нам пофигу, получится в итоге подряд или с дырками через 100 - просто такой вариант unique id.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
неважно, можно не инкременить, а генерить случайное значение, нарушение CQRS остается :)
 

stalxed

Новичок
можешь перечислить эти проблемы в столбик?
я сходу вижу только проблему с тестами
Главная проблема метод equals и eventы.
Пока нет уникальности(а значит и ID), то сравнивать entity(сущности) невозможно.
Сравнивать по полям данных нельзя, это не Value Object.
Ну у меня лично была задача, что хотел сравнивать объекты в ОЗУ, не сохраняя их, но ключ можно было генерить на основе данных.

Дальше цитата с книги IDDD Вернона:

Why might timing matter? Consider a scenario where the client subscribes to outgoing Domain Events. An Event occurs when a newProductinstantiation completes. The client saves the published Event to anEvent Store (8). Eventually those stored Events are published as notifications that reach subscribers outside the Bounded Context. Using the approach ofFigure 5.3, the Domain Event is received before the client has the opportunity to add the newProductto theProductRepository. Thus, the Domain Event would not contain the valid identity of the newProduct. For the Domain Event to be correctly initialized, the identity generation must be completed early.Figure 5.4demonstrates that approach. The client queries for the next identity from theProductRepository, passing it to theProductconstructor.

There is another problem that can occur when identity generation is delayed until the Entity is persisted. It occurs when two or more new Entities must be added to ajava.util.Set, but their identity has not yet been assigned, making them equal to the other new ones (for example,null, or0, or-1). If the Entity’sequals()method compares identities, those newly added to theSetwill appear to be the same object. Only the first object added will be contained, and all others will be excluded. This causes a dubious bug whose root cause is at first difficult to understand and fix.
Вот у меня раз возникла проблема из второго абзаца.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
А если вернуться как раз к такому типичнейшему действию как регистрация.
думаю, вопрос лучше рассматривать комплексно потому что случаев гораздо больше: оформление заказа, финансовые транзакции
На клиенте генерировать ID это уже имхо дико.
вполне допустимо при условии валидации этого ID, поэтому случай нерепрезентативный
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Главная проблема метод equals и eventы.
Пока нет уникальности(а значит и ID), то сравнивать entity(сущности) невозможно.
Сравнивать по полям данных нельзя, это не Value Object.
Ну у меня лично была задача, что хотел сравнивать объекты в ОЗУ, не сохраняя их, но ключ можно было генерить на основе данных.
прости, но я твой экран не вижу и значения фраз "метод equals и eventы" не понимаю. предлагаю общаться общеупотребительными терминами со ссылками на трактовку терминов
 

fixxxer

К.О.
Партнер клуба
Ну про equals очевидно же

PHP:
interface Equatable<T> {
    bool equals(T other);
}
 

stalxed

Новичок
equals стандартный метод в object(от которого наследуются все объекты) в Java и C#, который обычно перегружают, для уточнения сравнения двух объектов. Возвращает тип bool, который указывает на то, что объекты эквивалентны. Для entity - это обычно на основе ID, для Value Object - на основе всех полей данных объекта.

А Domain Event - это события происходящие в domain области....
 

fixxxer

К.О.
Партнер клуба
ставим блокировку, инкрементим, выбираем последнее значение, снимаем блокировку,
реализовать это в условиях многопоточности и негарантированной передачи данных достаточно сложно потому что клиенты не будут снимать блокировку
Ну в эту тему и вбросил ссылочку выше. Это проблема собственно не CQRS, это уже CAP theorem. :)
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
@fixxxer, да, отличная ссылка :)
я вспомнил о CAP просто потому что это единственная и очень серьезная причина нарушать CQRS в распределенных многопользовательских системах.
мы бы спокойно делали insert; select, если бы не race condition
 

Вурдалак

Продвинутый новичок
можешь перечислить эти проблемы в столбик?
я сходу вижу только проблему с тестами
  • служебный метод setId() в командах, событиях, сущностях. Мусор, лишний код и/или соглашения;
  • функциональные тесты, сценарии;
  • невозможность сообщить клиенту id будущей сущности в случае асинхронного выполнения команды.
Да мне первого пункта хватает.
 
Сверху