2012-03-25 5 views
2

Я все еще пытаюсь склонить голову о том, как применять DDD и, самое последнее, CQRS к реальному производственному бизнес-приложению. В моем случае я работаю над системой управления запасами. Он работает как серверное приложение, открытое через REST API для нескольких клиентских приложений. Мое внимание было сосредоточено на уровне домена с API и клиентами.Применение CQRS для управления запасами

Командная часть домена используется для создания нового заказа и позволяет изменять, отменять, маркировать заказ, как выполненный и отправленный/завершенный. У меня, конечно, есть запрос, который возвращает список заказов в системе (как доступные для чтения, легкие DTO) из репозитория. Другой запрос возвращает PickList, используемый сотрудниками склада для перемещения предметов с полки для выполнения определенных заказов. Чтобы создать PickList, есть расчеты, правила и т. Д., Которые необходимо оценить, чтобы определить, какие заказы готовы к выполнению. Например, если все позиции заказа находятся на складе. Мне нужно прочитать тот же список заказов, перебрать список и применить эти правила и вычисления, чтобы определить, какие элементы должны быть включены в PickList.

Это не простой запрос, так как он вписывается в модель?

UPDATE

В то время как я могу быть в состоянии поддерживать (магазин) набор PickLists, они на самом деле являются динамическими, пока работник не получает следующий PickList. Рассмотрим следующий сценарий:

Получен первый ордер за день. Я могу поднять событие домена, которое запускает AssemblePickListCommand, который применяет все правила и логику для создания одного или нескольких списков выбора для этого ордера.

Полученный второй заказ. Обработчик событий должен теперь ЗАМЕНИТЬ оригинальные PickLists одним или несколькими новыми списками выбора, оптимизированными для обоих ожидающих ордеров.

Аналогичным образом после получения третьего заказа.

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

Складской служащий № 1 запрашивает подборщик. Первый PickList вытягивается и печатается.

Получен четвертый заказ. Как и ранее, обработчик удаляет второй PickList из очереди (единственный оставшийся) и регенерирует один или несколько PickLists на основе второго PickList и нового Order.

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

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

ответ

0

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

+0

В том, что я прочитал, по своей природе команды в одну сторону. Другими словами, я не видел никаких примеров или не читал описание команд, используемых таким образом. Я знаю, что это возможно, просто не то, что я видел. – SonOfPirate

+0

Я не уверен, что мы говорим об одном и том же. Команда 'Assemble Picklist' и ее использование не будут отличаться от любой другой команды. Вероятно, здесь есть некоторые недоразумения. Что именно вы подразумеваете под «командами, используемыми таким образом»? –

+0

Извините, я не получил предупреждение, которое вы прокомментировали. – SonOfPirate

0

У вас, кажется, есть две роли/процессы и, возможно, два совокупных корня - продавец работает с заказами, складским работником с picklists.

AssemblePicklistsCommand() инициируется обработкой заказов и воссоздает всех неназванных пилотов.

Складской работник стреляет AssignPicklistCommand(userid), который пытается выбрать наиболее подходящий неназначенный подборщик и назначить его ему (или ничего не делать, если у него уже есть активный список выбора). Затем он мог использовать GetActivePicklistQuery(userid), чтобы получить список выбора, выбрать предметы с PickPicklistItemCommand(picklistid, item, quantity) и, наконец, MarkPicklistCompleteCommand(), чтобы подать сигнал, что он сделан.

AssemblePicklist и AssignPicklist должны блокировать друг друга (последовательная обработка, оптимистическая согласованность?), Но связь между AssignPicklist и GetActivePicklist чиста - либо у вас есть список выбора, либо нет.

1

Хотя я могу поддерживать (хранить) набор PickLists, они действительно динамичны, пока сотрудник не получит следующий PickList. Рассмотрим следующий сценарий:

Получен первый ордер за день. Я могу поднять событие домена, которое запускает AssemblePickListCommand, который применяет все правила и логику для создания одного или нескольких списков выбора для этого ордера.

Полученный второй заказ. Обработчик событий должен теперь ЗАМЕНИТЬ оригинальные PickLists одним или несколькими новыми списками выбора, оптимизированными для обоих ожидающих ордеров.

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

В частности, я не верю, что вы будете имея эти проблемы моделирования, если «очередь» PickList была реальной. Я думаю, что вместо этого есть коллекция OrderItem, которая живет внутри некоторого агрегата, вы выдаете команды этому агрегату для генерации PickList.

То есть, я бы ожидать, поток, который выглядит как

onOrderPlaced(List<OrderItems> items) 
    warehouse.reserveItems(List<OrderItems> items) 
     // At this point, the items are copied into an unasssigned 
     // items collection. In other words, the aggregate knows 
     // that the items have been ordered, and are not currently 
     // assigned to any picklist 
     fire(ItemsReserved(items)) 

onPickListRequested(Id<Employee> employee) 
    warehouse.assignPickList(Id<Employee> employee, PickListOptimizier optimizer) 
     // PickListOptimizer is your calculation, rules, etc that know how 
     // to choose the right items to put into the next pick list from a 
     // a given collection of unassigned items. This is a stateless domain 
     // *domain service* -- it provides the query that the warehouse aggregate needs 
     // to figure out the right change to make, but it *doesn't* change 
     // the state of the aggregate -- that's the aggregate's responsibility 

     List<OrderItems> pickedItems = optimizer.chooseItems(this.unassignedItems); 
     this.unassignedItems.removeAll(pickedItems); 

     // This mockup assumes we can consider PickLists to be entities 
     // within the warehouse aggregate. You'd need some additional 
     // events if you wanted the PickList to have its own aggregate 
     Id<PickList> = PickList.createId(...); 
     this.pickLists.put(id, new PickList(id, employee, pickedItems)) 
     fire(PickListAssigned(id, employee, pickedItems); 

onPickListCompleted(Id<PickList> pickList) 
    warehouse.closePicklist(Id<PickList> pickList) 
     this.pickLists.remove(pickList) 
     fire(PickListClosed(pickList) 

onPickListAbandoned(Id<PickList> pickList) 
    warehouse.reassign(Id<PickList> pickList) 
     PickList list = this.pickLists.remove(pickList) 
     this.unassignedItems.addAll(list.pickedItems) 
     fire(ItemsReassigned(list.pickedItems) 

Не большой languaging - я не говорю склад. Но он охватывает большинство ваших вопросов: каждый раз, когда создается новый PickList, он создается из последнего состояния ожидающих элементов на складе.

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

Смежные вопросы