212 похожих чатов

Приветствую. Подскажите плиз, кто как хранит логику, которая не умещается

в агрегатах? Ну т.е. сценарии юзкесов.
В чем собственно я вижу проблему: вот есть некий юзкейс (класс обработчик), в который инжектятся репозитории и какие либо еще сервисы и там логика. Банально: заказ можно передать курьеру, если у курьера меньше 20 активных заказов, если заказ уже выполнен и оплачен. Т.е. этот юзкейс охватывает взаимодейсвтие баланса, статуса произодства заказа и данных о курьере. Если эту логику оставить в юзкейсе - то у нас в одном месте и зависимости и логика, что не хорошо. Значит надо логику из юзкейса куда то переносить. Куда? Создавать отдельный класс/чистую функцию? Но тогда мы идем в сторону анемичности и сервис-классов. Или эту логику переносить в один из классов/агрегат, например в курьера? Но тогда идем в сторону повышения каплинга. Или вообще как-то иначе?

55 ответов

27 просмотров
Павел-Г. Автор вопроса

Хм, думал что юзкейс это домен. А в вашем предложении доменный сервис типа будет чистым и без зависимости?

https://enterprisecraftsmanship.com/posts/domain-vs-application-services/#:~:text=The%20main%20difference%20between%20them,whereas%20application%20services%20don't.&text=And%20application%20services%20orchestrate%20those,by%20entities%20and%20value%20objects.

Павел-Г. Автор вопроса

Спасибо, ответ как раз по ссылке. 👍

Павел-Г. Автор вопроса

На саму никак, он влияет можно ли отдать в доставку.

как? Товар же уже оплачен

Павел-Г. Автор вопроса

Например у меня нет ) пост оплата

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

Павел-Г. Автор вопроса

во во во я про это

ну всё равно будет по идее какая-то транзакция, которую будет тыкать человек, соглашаясь, что мол "да, я готов заплатить столько-то" - это и будет твоя "оплата". А если вы работаете по постоплате - как бизнес вообще уверен, что ему заплатят?

> это значит что домен наиболее устойчивый к изменениям какое-то странное следствие

я просто не оч соображаю под вечер, ну я думаю все всё поняли

Павел-Г. Автор вопроса

Я сам ему задавал этот вопрос - на честном слове) но так или иначе, надо проверить что товар "оплачен" и этот if надо куда то поместить

ну а как вы проверяете, что "товар оплачен"? Если вы работаете по постоплате - непонятно. Товар не может быть оплачен в этот момент.

не надо проверять - если у тебя есть ивент - это факт

Павел-Г. Автор вопроса

Да, пожтому и стоит if

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

Павел-Г. Автор вопроса

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

модуль оплаты подтверждает, что товар оплачен (я не знаю как у тебя бизнес убеждается, что ему оплатят товар, если вы по постоплате работаете) В модуле доставки нет значения оплачен или нет - в модуль доставки прилетает событие, что товар такой-то оплачен, всё. В модуле доставки запускается процесс доставки

Павел-Г. Автор вопроса

доставка в ручную тыкается

а почему она вручную тыкается?

Павел-Г. Автор вопроса

Потому что приходит курьер. Ему менеджер отдает товар и тыкает - отдал товар

в какой момент во всём это происходит настоящая оплата? Ну то есть деньги покупатель когда отдаёт? В момент когда к нему курьер приходит с товаром?

Павел-Г. Автор вопроса

Когда захочет. Есть баланс, его пользователь пополняет. Как только его пополнят, с него перетекает на товар. Если баланса хватает товар считается оплаченным

а "отдал товар" менеджер тыкает для чего?

Павел-Г. Автор вопроса

Чтобы потом у курьера товр появился в его части

я бы предложил тебе скинуть код, потому что тут люди тебя вряд ли поймут. проще всего сделать валидейшн-леер какой-то, к-ый проверит, что чекаут оплачен. с другой стороны, если у тебя баундед контексты, в контекст курьера можно положить ордер с минимальным набором полей, где будет Order {id, isPaymentCompleted }

Павел-Г. Автор вопроса

Вот это кстати предложение интересное в качестве варианта, только получается надо это поле дублировать, и это немного усложняет вещи в особенности конченой согласованности. Когда товар может перейти в другое состояние а курьеру уже отдали.

получается, что никакая у тебя не постоплата. Покупатель просто оплачивает товар из кошелька. Момент списания тугриков с кошелька и будет моментом оплаты. Зачем проверять хватает ли денег на кошельке, если до этого у покупателя уже деньги списались с кошелька? Ведь в момент списания они у него были

нет, я не говорю о дублировании таблиц в базе, я говорю об ограничении маппингов на уровне орм в твоём приложении. таблица всё ещё будет одна, поэтому всё будет косистентно

Павел-Г. Автор вопроса

Пользователь заказывает товар. У него на балансе -1000. Товар проходит стадиб производства и лежит на складе. Ему звонят (это тема конечно странная на честнмо слове) - мол, дорогой, пополни баланс

Павел-Г. Автор вопроса

Ммм интересно, спасибо. ГРубо говоря две сущности из разных контекстов читают данные из одной таблицы

типа того. ну или там под разные сущности делать свои вьюшки, как вариант

Павел-Г. Автор вопроса

👍

это и есть секрет разделения контекстов в ddd) вместо 1 класса знающего все ответы, много специализированных для разных областей применения

Павел-Г. Автор вопроса

Ну контексты +- минус мне понятны, а вот что они на одни таблички ссылаться могут - не думал

ит депендс. иногда могут, иногда не могут, иногда могут использовать вьюхи от одной таблицы

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

Павел-Г. Автор вопроса

Можно, согласен. Как вариант, почему бы и нет, спасибо. Другое дело что это немного делает разрыв, так как (хоть и мало вероятно), но чисто в теории можно товар сделать и непополаченным снова, а ивент еще не обработался, это надо как-то тоже учесть. Т.е. пока это хоть и красиво, но повышает сложность отчасти. Т.е. таких флагов уже минимум 2 - оплата заказа и статус производства.

сложность это всё конечно повышает. Одна только инфраструктура для того чтобы ивенты надёжно летали чего стоит. Что касается того, что заказ может стать неоплаченным - это надо отдельно разбираться почему и зачем так. Вообще заказ не может стать неоплаченным - покупатель оплатил, траназкция была. Дальше может делать отмену заказа или возврат товара - но это уже продолжение процесса или процессов, в общем тут отдельно думать надо

Павел-Г. Автор вопроса

Есть кейс, что менеджер может увеличить стоймость заказа постфактум) зачеми почему - хз, но есть

я не эксперт, но на сколько я знаю это не очень законно после оплаты менять цену

Павел-Г. Автор вопроса

Думаю да...

Павел-Г. Автор вопроса

Чет подзадумался. А данном контексте, разве это бизнес правило не выходит на уровень приложения?

- заказ — выполнен и оплачен - курьер — имеет меньше 20 активных заказов - заказ - передать - курьер Есть ли тут какое-то решение приложения или может быть что-то используется не из домена? Вроде нет.

Павел-Г. Автор вопроса

Понятно, спасибо. Я просто прикинул, что если брать несколько копий приложений, то правила именно 20 заказов, и например выдавать только оплаченные - можно менять от приложения к приложению.

заказ может быть неоплачен, если прошёл сбой в процессе обработки транзакции на стороне банка. если ты слушаешь ивент успешной авторизации карты, то он может пройти, но он не означает, что транзакция завершилась

а шо там за сбои происходят?

ну, лёг пейментовый шлюз, например

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

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

а, ну это всё нюансы и out of order messaging, это всё решается

на случае "могут зависнуть" и нужны всякие там таймауты и тд. с возможность "если долго небыло ответа - сходи узнай живой или нет"

да, это всё понятно, нюансы проектирования, но тем не менее

Кстати, VO тоже может иметь логику тк VO относятся к домену

Павел-Г. Автор вопроса

Спасибо за дополнения 👍🤓

Похожие вопросы

Обсуждают сегодня

#include <stdio.h> #include <stdlib.h> #include <time.h> void mass_first_generate(int mass[5][7]) {     for (int N = 0; N < 5; N++) {         for (int A = 0; A < 7; A++) {   ...
Чувак
6
Всем привет! Имеется функция: function IsValidChar(ch: UTF8Char): Boolean; var i: Integer; ValidChars: AnsiString; begin ValidChars := 'abcdefghijklmnopqrstuvwxyzABCDE...
Евгений
44
Всем привет! Решаю 99 OCaml Problems и столкнулся со следующей проблемой (прошу палками не забивать, я OCaml практически не трогал до этого момента): open OUnit2 let create_...
К|/|pи/\/\ 6е3yглbIи
2
https://www.linkedin.com/posts/ugama-benedicta-kelechi-codergirl-103041300_mobiledevelopment-fluttertraining-handsonlearning-activity-7263445699227254784-IdHB?utm_source=share...
CoderGirl
16
возможно ли как-то передать в электрон или таури медиа поток с рендера 2д движка? двиг запускается как dll, а дальше надо как-то отправлять рендер кодировать не подходит, зр...
Kyle Nekto
7
Ну вот просто даже давайте вот как. Какой нибудь конкретный кейс, можете в пример привести, где бч работает и приносит прикладную пользу, а не просто что бы было? Не крипту.
Alexander Andreev
22
Помогите пожалуйста. Делаю систему плагинов. Проблема сейчас в такая: плагины загружаются в основном потоке. FLibHandle := SafeLoadLibrary(FFileName) Но нужно еще выполнить фу...
Илья 🤣
10
объясните пожалуйста, почему функция не работает должным образом? вроде должно брать активное окно сравнивать его размер с размером экрана, и если есть совпадение = true прове...
JF
12
лучше скажите, причём тут паскаль?
Alexey Kulakov
36
Но, может, есть уже проверенная? Наши требования такие: 1. Сообщения должны приходить из Инста в CRM оду 2. Должна быть возможность подключить несколько экаунтов Инстаграм. Р...
Alexander Sharoiko MSE / Александр Шаройко
13
Карта сайта