powered by simpleCommunicator - 2.0.41     © 2025 Programmizd 02
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / DDD разнесение кода логики по классам
25 сообщений из 169, страница 3 из 7
DDD разнесение кода логики по классам
    #39910686
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудух
т.е. пример - говно?


Вообще, я ещё немного поковырялся в примере и вот что нашёл:

https://github.com/dotnet-architecture/eShopOnContainers/blob/23992ed3249cd257ac5fc42b23f2864b2ddf347b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
    public class ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler
                        : INotificationHandler<OrderStartedDomainEvent>
    {
        private readonly ILoggerFactory _logger;
        private readonly IBuyerRepository _buyerRepository;
        private readonly IIdentityService _identityService;
        private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;

        public ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler(
            ILoggerFactory logger, 
            IBuyerRepository buyerRepository, 
            IIdentityService identityService,
            IOrderingIntegrationEventService orderingIntegrationEventService)
        {
            _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
            _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
            _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        public async Task Handle(OrderStartedDomainEvent orderStartedEvent, CancellationToken cancellationToken)
        {            
            var cardTypeId = (orderStartedEvent.CardTypeId != 0) ? orderStartedEvent.CardTypeId : 1;
            var buyer = await _buyerRepository.FindAsync(orderStartedEvent.UserId);
            bool buyerOriginallyExisted = (buyer == null) ? false : true;

            if (!buyerOriginallyExisted)
            {                
                buyer = new Buyer(orderStartedEvent.UserId, orderStartedEvent.UserName);
            }

            buyer.VerifyOrAddPaymentMethod(cardTypeId,
                                           $"Payment Method on {DateTime.UtcNow}",
                                           orderStartedEvent.CardNumber,
                                           orderStartedEvent.CardSecurityNumber,
                                           orderStartedEvent.CardHolderName,
                                           orderStartedEvent.CardExpiration,
                                           orderStartedEvent.Order.Id);

            var buyerUpdated = buyerOriginallyExisted ? 
                _buyerRepository.Update(buyer) : 
                _buyerRepository.Add(buyer);

            await _buyerRepository.UnitOfWork
                .SaveEntitiesAsync();

            var orderStatusChangedTosubmittedIntegrationEvent = new OrderStatusChangedToSubmittedIntegrationEvent(orderStartedEvent.Order.Id, orderStartedEvent.Order.OrderStatus.Name, buyer.Name);
            await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedTosubmittedIntegrationEvent);

            _logger.CreateLogger<ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler>()
                .LogTrace("Buyer {BuyerId} and related payment method were validated or updated for orderId: {OrderId}.",
                    buyerUpdated.Id, orderStartedEvent.Order.Id);
        }
    }



А как же... CQRS, там, разделение на команды и запросы, где запись в командах, а чтение в запросах?
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910687
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудух
а вот это почему так объявляется (get/set)? и как именно используется в CQRS?
полудух
Код: c#
1.
public string UserId {get; private set;}



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


полудух
т.е. пример - говно?


Таки да, к сожалению :(
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910689
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще, идеального примера мне найти не удалось. Но во всех проектах нашлось много чего ценного и полезного. Поэтому нам приходилось использовать удачные находки и нарабатывать свои, конечно основываясь на теории и имеющейся практики, а также исходя из текущих и будущих задач.

Сейчас хорошо, искать особо не нужно. Есть постоянно актуализируемый сборник:

https://github.com/ddd-cqrs-es?language=c# (выбран фильтр C# для удобства)
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910708
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

имхо люди хотят халявы, статейки с примером на пару экранов
а читать Гради Буча, Бертрана Майера, Мартина Фаулера, Эрика Эванса и др.
понимать когда и почему это всё придумывалось, как развивалась и как применяется сейчас
это же слишком сложно :)
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910710
Фотография StalkerS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудух
а вот это почему так объявляется (get/set)? и как именно используется в CQRS?
полудух
Код: c#
1.
public string UserId {get; private set;}


С CQRS это никак не связано, это синтаксис языка С#, а CQRS это подход к архитектуре, причем довольно специфичный и подходящий только для весьма ограниченного числа систем
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910712
Фотография StalkerS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt

А как же... CQRS, там, разделение на команды и запросы, где запись в командах, а чтение в запросах?

С CQRS тут все в порядке, Buyer тут является агрегатом, который сохраняется с помощью репозитория, а чтения тут нет
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910720
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
StalkerS,

что значит весьма ограниченного числа систем?
В ozon используют CQRS.
А там и электронная коммерция, и логистика, и склады, и биллинг, и туризм...
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910721
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В 2gis используют CQRS, и DDD, и Event Storming
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910729
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA
а читать Гради Буча, Бертрана Майера, Мартина Фаулера, Эрика Эванса и др.

смысл их читать, если там деза:
hVostt
Понятно, что универсального решения нет. Но у Фаулеровского (от 2013 года) DDD никакого решения на этот счёт нет. Выкручивайтесь сами так сказать.

hVostt
Я Фаулера уважаю. Но это не значит, что буду слепо следовать его указаниям. Нужно пользоваться также и своей головой, и на опыте далеко не всё работает по написанному .
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910730
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Буча, кстати, пытался читать "ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОЕКТИРОВАНИЕ С ПРИМЕРАМИ ПРИМЕНЕНИЯ"...
грёбаная дичь... там же 90% воды... чуть не утонул (
посмотрите на главу 12 "ADA. СИСТЕМА УПРАВЛЕНИЯ ДВИЖЕНИЕМ" - читать невозможно, кто так пишет про программирование систем... ГДЕ там про программирование?! Сплошная вода.
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910731
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
другое дело Ален Голуб - "Верёвка достаточной длины, чтобы выстрелить себе в ногу"
вот эта книжка лучшая по ООП и программированию в целом.
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910732
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Вообще, я ещё немного поковырялся в примере и вот что нашёл:
...

вот щас страшно было, да...
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910739
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудух
Буча, кстати, пытался читать "ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОЕКТИРОВАНИЕ С ПРИМЕРАМИ ПРИМЕНЕНИЯ"...
грёбаная дичь... там же 90% воды... чуть не утонул (
посмотрите на главу 12 "ADA. СИСТЕМА УПРАВЛЕНИЯ ДВИЖЕНИЕМ" - читать невозможно, кто так пишет про программирование систем... ГДЕ там про программирование?! Сплошная вода.


Да утырки этот Буч и его соавторы, вода и белиберда
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910742
love_bach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сначала сразу ссылку на этот пример хотел кинуть, с телефона было не удобно.
Если я правильно понимаю, там большинство сервисов сами по себе - "Домены", и выделять внутри них какие-то поддомены - лишнее (видимо, в силу простоты, и демонстрации "не надо усложнять там где не надо", и "грести все под одну гребенку"). С ними понятно.
Но, вот этот - Ordering - он содержит и, в том числе, домен. И там, например, есть в

Код: c#
1.
2.
public class Order
        : Entity, IAggregateRoot



такой метод:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
// DDD Patterns comment
        // This Order AggregateRoot's method "AddOrderitem()" should be the only way to add Items to the Order,
        // so any behavior (discounts, etc.) and validations are controlled by the AggregateRoot 
        // in order to maintain consistency between the whole Aggregate. 
        public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1)
        {
            var existingOrderForProduct = _orderItems.Where(o => o.ProductId == productId)
                .SingleOrDefault();

            if (existingOrderForProduct != null)
            {
                //if previous line exist modify it with higher discount  and units..

                if (discount > existingOrderForProduct.GetCurrentDiscount())
                {
                    existingOrderForProduct.SetNewDiscount(discount);
                }

                existingOrderForProduct.AddUnits(units);
            }
            else
            {
                //add validated new order item

                var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units);
                _orderItems.Add(orderItem);
            }
        }



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

Теперь первоначальный вопрос уточню так:

1) если есть полная уверенность, что можем инкапсулировать "чистую" логика домена, то размещаем её в корне агрегата?
2) если что-то сильно выйдет за рамки 1) - рефакторим - выносим в команды, все-равно деваться некуда, и рефакторинг это не исправление "ошибок", это реакция на новые требования?
3) но, если все-равно есть ненулевая вероятность 2), может, ну его нафиг 1) и сразу 2)?
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910745
love_bach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
полудух
т.е. пример - говно?


Вообще, я ещё немного поковырялся в примере и вот что нашёл:

https://github.com/dotnet-architecture/eShopOnContainers/blob/23992ed3249cd257ac5fc42b23f2864b2ddf347b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
    public class ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler
                        : INotificationHandler<OrderStartedDomainEvent>
    {
        private readonly ILoggerFactory _logger;
        private readonly IBuyerRepository _buyerRepository;
        private readonly IIdentityService _identityService;
        private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;

        public ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler(
            ILoggerFactory logger, 
            IBuyerRepository buyerRepository, 
            IIdentityService identityService,
            IOrderingIntegrationEventService orderingIntegrationEventService)
        {
            _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
            _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
            _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        public async Task Handle(OrderStartedDomainEvent orderStartedEvent, CancellationToken cancellationToken)
        {            
            var cardTypeId = (orderStartedEvent.CardTypeId != 0) ? orderStartedEvent.CardTypeId : 1;
            var buyer = await _buyerRepository.FindAsync(orderStartedEvent.UserId);
            bool buyerOriginallyExisted = (buyer == null) ? false : true;

            if (!buyerOriginallyExisted)
            {                
                buyer = new Buyer(orderStartedEvent.UserId, orderStartedEvent.UserName);
            }

            buyer.VerifyOrAddPaymentMethod(cardTypeId,
                                           $"Payment Method on {DateTime.UtcNow}",
                                           orderStartedEvent.CardNumber,
                                           orderStartedEvent.CardSecurityNumber,
                                           orderStartedEvent.CardHolderName,
                                           orderStartedEvent.CardExpiration,
                                           orderStartedEvent.Order.Id);

            var buyerUpdated = buyerOriginallyExisted ? 
                _buyerRepository.Update(buyer) : 
                _buyerRepository.Add(buyer);

            await _buyerRepository.UnitOfWork
                .SaveEntitiesAsync();

            var orderStatusChangedTosubmittedIntegrationEvent = new OrderStatusChangedToSubmittedIntegrationEvent(orderStartedEvent.Order.Id, orderStartedEvent.Order.OrderStatus.Name, buyer.Name);
            await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedTosubmittedIntegrationEvent);

            _logger.CreateLogger<ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler>()
                .LogTrace("Buyer {BuyerId} and related payment method were validated or updated for orderId: {OrderId}.",
                    buyerUpdated.Id, orderStartedEvent.Order.Id);
        }
    }



А как же... CQRS, там, разделение на команды и запросы, где запись в командах, а чтение в запросах?


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

такие моменты у меня и вызывают вопросы. не думаю, что это он так облажался. скорее всего не хватило выразительности DDD
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910749
love_bach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt

полудух
т.е. пример - говно?


Таки да, к сожалению :(


можешь выделить, что тебе особенно не понравилось, а как бы ты сделал?
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910756
love_bach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA
hVostt,

имхо люди хотят халявы, статейки с примером на пару экранов
а читать Гради Буча, Бертрана Майера, Мартина Фаулера, Эрика Эванса и др.
понимать когда и почему это всё придумывалось, как развивалась и как применяется сейчас
это же слишком сложно :)


золотые слова! хотим халявы!
есть какие-то более-менее приближенные к примеру комментарии?
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910758
ViPRos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA
hVostt,

имхо люди хотят халявы, статейки с примером на пару экранов
а читать Гради Буча, Бертрана Майера, Мартина Фаулера, Эрика Эванса и др.
понимать когда и почему это всё придумывалось, как развивалась и как применяется сейчас
это же слишком сложно :)

список этих долбоебов слишком велик, а гарантий, что они там что то написали правильно - исчезающе мал
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910766
love_bach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ViPRos
skyANA
hVostt,

имхо люди хотят халявы, статейки с примером на пару экранов
а читать Гради Буча, Бертрана Майера, Мартина Фаулера, Эрика Эванса и др.
понимать когда и почему это всё придумывалось, как развивалась и как применяется сейчас
это же слишком сложно :)

список этих долбоебов слишком велик, а гарантий, что они там что то написали правильно - исчезающе мал


отбросим это. что хотел сказать?
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910771
mirudom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемые форумчане,
Где то до кода, который приводится, должно быть написано, что мол код не является промышленным, а только служит иллюстрацией к описанию проблемы/паттерна в лучшем случае в каком то конкретном контексте.
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910772
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
StalkerS
hVostt

А как же... CQRS, там, разделение на команды и запросы, где запись в командах, а чтение в запросах?

С CQRS тут все в порядке, Buyer тут является агрегатом, который сохраняется с помощью репозитория, а чтения тут нет


Если у вас архитектура строится на CQRS, значит любые изменения данных системы должны быть в командах. Если бы в приведённом коде обработчика события был бы вызов команды, было бы ок.

Сейчас тут далеко не всё в порядке.
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910773
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудух
skyANA
а читать Гради Буча, Бертрана Майера, Мартина Фаулера, Эрика Эванса и др.

смысл их читать, если там деза:
hVostt
Понятно, что универсального решения нет. Но у Фаулеровского (от 2013 года) DDD никакого решения на этот счёт нет. Выкручивайтесь сами так сказать.

hVostt
Я Фаулера уважаю. Но это не значит, что буду слепо следовать его указаниям. Нужно пользоваться также и своей головой, и на опыте далеко не всё работает по написанному .


Это не деза. Это люди, у которых ещё имеется собственные взгляды и мнения, которые не являются аксиомами. Знать различные точки зрения и подходы очень полезно.
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910775
mirudom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще.
Уважаемые форумчане,
еже ли было б ВСЕ просто и однозначно, то мы б составили конкуренцию людям, которых нанимают вместо московских дворников.
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910776
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA
hVostt,

имхо люди хотят халявы, статейки с примером на пару экранов
а читать Гради Буча, Бертрана Майера, Мартина Фаулера, Эрика Эванса и др.
понимать когда и почему это всё придумывалось, как развивалась и как применяется сейчас
это же слишком сложно :)


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

Всегда хочется найти "единственно правильное решение", или близкое к нему.
Особенно это выражается в начале пути, и у меня так было.
...
Рейтинг: 0 / 0
DDD разнесение кода логики по классам
    #39910779
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
love_bach
такой метод:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
// DDD Patterns comment
        // This Order AggregateRoot's method "AddOrderitem()" should be the only way to add Items to the Order,
        // so any behavior (discounts, etc.) and validations are controlled by the AggregateRoot 
        // in order to maintain consistency between the whole Aggregate. 
        public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1)
        {
            var existingOrderForProduct = _orderItems.Where(o => o.ProductId == productId)
                .SingleOrDefault();

            if (existingOrderForProduct != null)
            {
                //if previous line exist modify it with higher discount  and units..

                if (discount > existingOrderForProduct.GetCurrentDiscount())
                {
                    existingOrderForProduct.SetNewDiscount(discount);
                }

                existingOrderForProduct.AddUnits(units);
            }
            else
            {
                //add validated new order item

                var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units);
                _orderItems.Add(orderItem);
            }
        }




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

Теперь первоначальный вопрос уточню так:

1) если есть полная уверенность, что можем инкапсулировать "чистую" логика домена, то размещаем её в корне агрегата?
2) если что-то сильно выйдет за рамки 1) - рефакторим - выносим в команды, все-равно деваться некуда, и рефакторинг это не исправление "ошибок", это реакция на новые требования?
3) но, если все-равно есть ненулевая вероятность 2), может, ну его нафиг 1) и сразу 2)?



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

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
        // DDD Patterns comment
        // This Order AggregateRoot's method "AddOrderitem()" should be the only way to add Items to the Order,
        // so any behavior (discounts, etc.) and validations are controlled by the AggregateRoot 
        // in order to maintain consistency between the whole Aggregate. 
        public void AddOrderItem(OrderItem orderItem)
        {
            if (orderItems.Any(o => o.ProductId == productId))
            {
                throw new InvalidOperationException("A similar order item is already exists.");
            }
            else
            {
                _orderItems.Add(orderItem);
            }
        }



Отвечая на вопросы:

love_bach
1) если есть полная уверенность, что можем инкапсулировать "чистую" логика домена, то размещаем её в корне агрегата?
2) если что-то сильно выйдет за рамки 1) - рефакторим - выносим в команды, все-равно деваться некуда, и рефакторинг это не исправление "ошибок", это реакция на новые требования?
3) но, если все-равно есть ненулевая вероятность 2), может, ну его нафиг 1) и сразу 2)?


Я придерживаюсь проверенного на практике мнения, что при использовании CQRS, все изменения необходимо производить только в командах. Это позволяет точно понимать что вообще с доменом происходит и где это искать.

Не нужно делать поиск по всему проекту, а где же ЕЩЁ используется репозиторий, и где ждать жёсткого подсрачника при рефакторинге или при выпуске релиза.

Размещая логику в аргегате, рано или поздно придёт понимание, что это не логика никакая. Это всего лишь методы, изменяющие агрегат. Добавить/удалить вложенную сущность (позиция заказа, например), изменить цену, количество, наименование и т.д. Или какая-то базовая примитивная валидация. Польза сомнительная, затраты существенные.
...
Рейтинг: 0 / 0
25 сообщений из 169, страница 3 из 7
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / DDD разнесение кода логики по классам
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]