Size: a a a

2020 September 24

D

Dmitry in symfony
я уже вышел из того возраста когда надо сломя голову ломиться в ночи к компу потому что где-то там что-то упало
лучше уж сделать больше тестов, больше зарезервировать оборудования, создать отказоустойчивость и тп, чем не спать ночами
психическое здоровье знаете ли нерезиновое 🙂
источник

VS

Vyacheslav Startsev in symfony
еще можно в каком-нибудь стат. анализаторе создать правило, по которому будет запрещено юзать хэндлер где-нибудь еще в коде, кроме баса
и тогда можно тоже спать спокойно с валидацией в миддлваре для баса
источник

D

Dmitry in symfony
Vyacheslav Startsev
еще можно в каком-нибудь стат. анализаторе создать правило, по которому будет запрещено юзать хэндлер где-нибудь еще в коде, кроме баса
и тогда можно тоже спать спокойно с валидацией в миддлваре для баса
нельзя, потому что очередной джун забудет добавить валидацию в команду, просто phpdoc забудет
источник

SP

Sergey Protko in symfony
Павел Г.
А почему в write неконсистентный стейт? Ведь вроде он и есть самый главный источник правды.
Вопрос гарантий того что решения о изменении стэйта принимаются на основании актуальных данных.

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

Если же ты геттер хернул и принимаешь решение менять другие вещи на основе стэйта этого агрегата то ты теряешь эти гарантии (либо тебе надо мутить распределенные локи что больно медленно и сложно).

Именно эту проблему решает CQRS. Грубо говоря как поделить операции таким образом что бы изменение стэйта было всегда основано на актуальных данных. Потому "команды"  не возвращают результат операции - мол ты там дальше на ивенты какие-то подписан должен быть что бы потоки данных выстраивались правильно и учитывались штуки типа temporal couping или отложить принятие решение во времени что бы данных накопить.

Если вероятность конкретнтного доступа низкая то ценность в CQRS резко снижается. В том числе и ценность ES для хранения стэйта с агрегатами. Во всяком случае мне сложно придумать задачу сходу где ES хорошо ложится и нет конкурентных действий и проблем с конфликтами.

Есть распространенное мнение что мол "если тебе надо аудит лог изменений бери ES" - так вот - слать в хуй всех этих гениев. Если тебе надо трекать все изменения то куда проще сделать тупой круд с версионизацией данных. Вместо UserProfileChanged стима ивентов проще хранить все ревизии профиля.

Так же есть ситуации когда все что требуется это не процесс описать а просто разрулить конкурентный доступ к данным, в этом случае просто CQRS достаточно.

ES весьма специфичная штука. Далеко не все проблемы оно решает хорошо.

Есть у Грега Янга докладик "The Bizarre Mating Ritual Of The Whipnose Seadevil" где он рассматривает кейсы где ES спасает. Но не надо думать что это сильвербулет и т.д.

Еще одна проблема у людей когда они начинают знакомиться с этими штуками это "если я заюзал ES для вот этой небольшой проблемы значит у меня все должно быть на ES" - это тоже популярное заблуждение и желание людей сделать простой выбор "че в каких ситуациях юзать" за счет устранения выбора.
источник

AP

Alex Papilov in symfony
привет! доставайте шар =)
источник

AP

Alex Papilov in symfony
у меня есть User и Profiles, связь один ко многим,
у меня есть инициализированный объект юзер,
мне нужно получить его profiles, обычно можно просто вызвать $user->getProfiles().
а возможно как нибудь вызвав этот метод получить определенные profils?
например, отфильтровать по типу.
источник

SP

Sergey Protko in symfony
Alex Papilov
у меня есть User и Profiles, связь один ко многим,
у меня есть инициализированный объект юзер,
мне нужно получить его profiles, обычно можно просто вызвать $user->getProfiles().
а возможно как нибудь вызвав этот метод получить определенные profils?
например, отфильтровать по типу.
читай про коллекции и Criteria.
источник

ПГ

Павел Г. in symfony
Sergey Protko
Вопрос гарантий того что решения о изменении стэйта принимаются на основании актуальных данных.

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

Если же ты геттер хернул и принимаешь решение менять другие вещи на основе стэйта этого агрегата то ты теряешь эти гарантии (либо тебе надо мутить распределенные локи что больно медленно и сложно).

Именно эту проблему решает CQRS. Грубо говоря как поделить операции таким образом что бы изменение стэйта было всегда основано на актуальных данных. Потому "команды"  не возвращают результат операции - мол ты там дальше на ивенты какие-то подписан должен быть что бы потоки данных выстраивались правильно и учитывались штуки типа temporal couping или отложить принятие решение во времени что бы данных накопить.

Если вероятность конкретнтного доступа низкая то ценность в CQRS резко снижается. В том числе и ценность ES для хранения стэйта с агрегатами. Во всяком случае мне сложно придумать задачу сходу где ES хорошо ложится и нет конкурентных действий и проблем с конфликтами.

Есть распространенное мнение что мол "если тебе надо аудит лог изменений бери ES" - так вот - слать в хуй всех этих гениев. Если тебе надо трекать все изменения то куда проще сделать тупой круд с версионизацией данных. Вместо UserProfileChanged стима ивентов проще хранить все ревизии профиля.

Так же есть ситуации когда все что требуется это не процесс описать а просто разрулить конкурентный доступ к данным, в этом случае просто CQRS достаточно.

ES весьма специфичная штука. Далеко не все проблемы оно решает хорошо.

Есть у Грега Янга докладик "The Bizarre Mating Ritual Of The Whipnose Seadevil" где он рассматривает кейсы где ES спасает. Но не надо думать что это сильвербулет и т.д.

Еще одна проблема у людей когда они начинают знакомиться с этими штуками это "если я заюзал ES для вот этой небольшой проблемы значит у меня все должно быть на ES" - это тоже популярное заблуждение и желание людей сделать простой выбор "че в каких ситуациях юзать" за счет устранения выбора.
Спасибо за развернутое объяснение!
источник

DT

Dmitriy Tkachenko in symfony
Sergey Protko
Вопрос гарантий того что решения о изменении стэйта принимаются на основании актуальных данных.

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

Если же ты геттер хернул и принимаешь решение менять другие вещи на основе стэйта этого агрегата то ты теряешь эти гарантии (либо тебе надо мутить распределенные локи что больно медленно и сложно).

Именно эту проблему решает CQRS. Грубо говоря как поделить операции таким образом что бы изменение стэйта было всегда основано на актуальных данных. Потому "команды"  не возвращают результат операции - мол ты там дальше на ивенты какие-то подписан должен быть что бы потоки данных выстраивались правильно и учитывались штуки типа temporal couping или отложить принятие решение во времени что бы данных накопить.

Если вероятность конкретнтного доступа низкая то ценность в CQRS резко снижается. В том числе и ценность ES для хранения стэйта с агрегатами. Во всяком случае мне сложно придумать задачу сходу где ES хорошо ложится и нет конкурентных действий и проблем с конфликтами.

Есть распространенное мнение что мол "если тебе надо аудит лог изменений бери ES" - так вот - слать в хуй всех этих гениев. Если тебе надо трекать все изменения то куда проще сделать тупой круд с версионизацией данных. Вместо UserProfileChanged стима ивентов проще хранить все ревизии профиля.

Так же есть ситуации когда все что требуется это не процесс описать а просто разрулить конкурентный доступ к данным, в этом случае просто CQRS достаточно.

ES весьма специфичная штука. Далеко не все проблемы оно решает хорошо.

Есть у Грега Янга докладик "The Bizarre Mating Ritual Of The Whipnose Seadevil" где он рассматривает кейсы где ES спасает. Но не надо думать что это сильвербулет и т.д.

Еще одна проблема у людей когда они начинают знакомиться с этими штуками это "если я заюзал ES для вот этой небольшой проблемы значит у меня все должно быть на ES" - это тоже популярное заблуждение и желание людей сделать простой выбор "че в каких ситуациях юзать" за счет устранения выбора.
Что-то мне подсказывает, что это проблемы подхода "натянуть сову на глобус", как в случае EventSourcing, так и в случае CQRS. У этих принципов строго ограниченные контексты действия влияния, и те проблемы того же ES, про которые ты говоришь, они разве касаются ES непосредственно? Это же всего-лишь способ персистенса, и те проблемы которые ты хочешь прикрепить к ES, относятся к Event-driven системам, разве нет?
источник

SP

Sergey Protko in symfony
Dmitriy Tkachenko
Что-то мне подсказывает, что это проблемы подхода "натянуть сову на глобус", как в случае EventSourcing, так и в случае CQRS. У этих принципов строго ограниченные контексты действия влияния, и те проблемы того же ES, про которые ты говоришь, они разве касаются ES непосредственно? Это же всего-лишь способ персистенса, и те проблемы которые ты хочешь прикрепить к ES, относятся к Event-driven системам, разве нет?
ну это не проблема ES, это объяснение почему ES требует CQRS. Не потому что пишем в одну штуку и чтаем в другую - это не сильно отличается от старого доброго CQS который стоит применять так же. Ну и в целом да - это больше про event/message driven архитектуры, за которые топят и Грег Янг со своим EventStore (стимы данных, CQRS, ES) и Уди Дахан со своим NServiceBus (упор больше на стримы данных и CQRS)
источник

SP

Sergey Protko in symfony
мой поинт в том что если у тебя нет взаимодействия людей в рамках процессов то тебе не нужны все эти CQRS/ES. Если ты пишешь инстаграм у тебя тупой круд. Если ты делаешь убер - то процесс бронирования поездки и т.д. уже включает в себя больше 1-ого человека и там может быть профит.
источник

D

Dmitry in symfony
Sergey Protko
Вопрос гарантий того что решения о изменении стэйта принимаются на основании актуальных данных.

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

Если же ты геттер хернул и принимаешь решение менять другие вещи на основе стэйта этого агрегата то ты теряешь эти гарантии (либо тебе надо мутить распределенные локи что больно медленно и сложно).

Именно эту проблему решает CQRS. Грубо говоря как поделить операции таким образом что бы изменение стэйта было всегда основано на актуальных данных. Потому "команды"  не возвращают результат операции - мол ты там дальше на ивенты какие-то подписан должен быть что бы потоки данных выстраивались правильно и учитывались штуки типа temporal couping или отложить принятие решение во времени что бы данных накопить.

Если вероятность конкретнтного доступа низкая то ценность в CQRS резко снижается. В том числе и ценность ES для хранения стэйта с агрегатами. Во всяком случае мне сложно придумать задачу сходу где ES хорошо ложится и нет конкурентных действий и проблем с конфликтами.

Есть распространенное мнение что мол "если тебе надо аудит лог изменений бери ES" - так вот - слать в хуй всех этих гениев. Если тебе надо трекать все изменения то куда проще сделать тупой круд с версионизацией данных. Вместо UserProfileChanged стима ивентов проще хранить все ревизии профиля.

Так же есть ситуации когда все что требуется это не процесс описать а просто разрулить конкурентный доступ к данным, в этом случае просто CQRS достаточно.

ES весьма специфичная штука. Далеко не все проблемы оно решает хорошо.

Есть у Грега Янга докладик "The Bizarre Mating Ritual Of The Whipnose Seadevil" где он рассматривает кейсы где ES спасает. Но не надо думать что это сильвербулет и т.д.

Еще одна проблема у людей когда они начинают знакомиться с этими штуками это "если я заюзал ES для вот этой небольшой проблемы значит у меня все должно быть на ES" - это тоже популярное заблуждение и желание людей сделать простой выбор "че в каких ситуациях юзать" за счет устранения выбора.
все равно стейт будет шарится, я не могу себе представить агрегат который не расшаривает свой стейт хоть частично
уточню, что под расшариванием стейта я имею ввиду любой доступ к данным агрегата извне

а на основе этого шаринга кто-то может принять любое решение
источник

SP

Sergey Protko in symfony
ну а альтернатива - распределенные локи. У этого подхода есть масса своих недостатков
источник

k

knopkod4v in symfony
Dmitry
все равно стейт будет шарится, я не могу себе представить агрегат который не расшаривает свой стейт хоть частично
уточню, что под расшариванием стейта я имею ввиду любой доступ к данным агрегата извне

а на основе этого шаринга кто-то может принять любое решение
вопрос дробления агрегатов. Ну и вопрос в том для чего шаринг.
источник

DT

Dmitriy Tkachenko in symfony
Sergey Protko
ну а альтернатива - распределенные локи. У этого подхода есть масса своих недостатков
ты говорил когда-то, что коллаборативные точки - это проблема. Вот это оно и есть)
источник

D

Dmitry in symfony
knopkod4v
вопрос дробления агрегатов. Ну и вопрос в том для чего шаринг.
а для чего бы то ни было шаринг
getId()->__toString() например - вот скажем мы получили ИД, ну пусть будет, картинки
без этого не жить, однако это шаринг внутренних данных, но некоторые могут сказать - это не стейт
да, тогда другой пример
image->isProcessed() - шаринг внутреннего состояния ? да
но на основе этого решения какой нибудь потребительно может принять решение процессить картинку или нет
источник

SP

Sergey Protko in symfony
Dmitry
все равно стейт будет шарится, я не могу себе представить агрегат который не расшаривает свой стейт хоть частично
уточню, что под расшариванием стейта я имею ввиду любой доступ к данным агрегата извне

а на основе этого шаринга кто-то может принять любое решение
ну вот вопрос как построить систему так что бы данные не надо было шарить напрямую. Ты можешь подписываться на ивенты и формировать другой агрегат.

Проблема что если у тебя есть N агрегатов которые шарят как-то стэйт - в каком порядке оно меняется и как это дебажить. все эти CQRS это решают за счет того что все взаимодействие идет посредствам стрима сообщений и как следствие достаточно легко зафорсить необходимые последовательносит действий и че как и куда.

На счет "не могу представить" - в этом проблема, люди настолько привыкли шарить стэйт что не могут представить а как по другому. Достаточно просто запретить это делать и вдруг окажется что это возможно.
источник

D

Dmitry in symfony
Sergey Protko
ну вот вопрос как построить систему так что бы данные не надо было шарить напрямую. Ты можешь подписываться на ивенты и формировать другой агрегат.

Проблема что если у тебя есть N агрегатов которые шарят как-то стэйт - в каком порядке оно меняется и как это дебажить. все эти CQRS это решают за счет того что все взаимодействие идет посредствам стрима сообщений и как следствие достаточно легко зафорсить необходимые последовательносит действий и че как и куда.

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

k

knopkod4v in symfony
Dmitry
а для чего бы то ни было шаринг
getId()->__toString() например - вот скажем мы получили ИД, ну пусть будет, картинки
без этого не жить, однако это шаринг внутренних данных, но некоторые могут сказать - это не стейт
да, тогда другой пример
image->isProcessed() - шаринг внутреннего состояния ? да
но на основе этого решения какой нибудь потребительно может принять решение процессить картинку или нет
вообще можно и не получать id картинки для транзакции
В случае с тем, что человек принимает решение - это ок, это для чтения просто
источник

SP

Sergey Protko in symfony
Dmitry
а для чего бы то ни было шаринг
getId()->__toString() например - вот скажем мы получили ИД, ну пусть будет, картинки
без этого не жить, однако это шаринг внутренних данных, но некоторые могут сказать - это не стейт
да, тогда другой пример
image->isProcessed() - шаринг внутреннего состояния ? да
но на основе этого решения какой нибудь потребительно может принять решение процессить картинку или нет
да, isProcessed и прочие "статусы" это может быть сигнальчик что что-то пошло не так с проектированием. Скорее всего должен быть ивент ImageWasProcessed на которое ты подписан и сможешь сам уже принимать решение.

Повторюсь - не надо пытаться натягивать CQRS и ES на старые добрые подходы с request/response моделью (процедуры)
источник