Chi possiede gli ordini in un marketplace di fornitori di servizi come la piattaforma?

2

Stiamo sviluppando un'applicazione in cui i provider possono offrire i loro prodotti e i consumatori possono comprarli (una sorta di marketplace). Cerchiamo di applicare i concetti DDD nella nostra progettazione del modello e l'implementazione segue uno stile microservizi. Ciò implica che i dati appartengono a un Contesto Limitato (BC) e solo i microservizi all'interno di quel BC possono accedervi. Al di fuori di questo BC, informazioni specifiche possono essere interrogate solo attraverso un'interfaccia pubblica del BC o sottoscrivendo eventi pubblicati da quel BC.

La mia domanda riguarda la progettazione degli ordini. Gli ordini sono posti dai consumatori e accettati e soddisfatti dai fornitori. Possono anche essere manipolati dal servizio clienti. Al momento un ordine contiene solo prodotti di un unico fornitore, ma in futuro potrei essere invitato a sostenere l'acquisto da più fornitori contemporaneamente.

Tutte le implementazioni che ho visto di sistemi simili contengono un singolo modello Order, che tende ad essere davvero gonfio di informazioni sui prodotti, il fornitore, il consumatore, la fatturazione, le consegne, i pagamenti, ecc. Sto cercando di evitare che , ma sto affrontando la domanda di "Chi possiede l'ordine"?

Posso pensare alle seguenti risposte:

  1. Esiste un contesto limitato agli ordini a cui si accede sia dal consumatore che dal fornitore. Ciò significa che l'API consumer ha un'operazione di Place Order che comunica con gli ordini BC e crea un ordine e l'API Provider ha un'operazione come Accept Order che parla agli stessi ordini BC e modifica lo stato di quello stesso modello di ordine.
  2. Esistono 2 ordini BC: Ordini consumatori e Ordini fornitori. L'API Consumer inserisce un ordine nel Consumer BC. Questo crea l'ordine e pubblica un ConsumerOrderCreatedEvent. Il ProviderOrders BC ascolta questo evento e crea un ordine locale (ProviderOrder) che fa riferimento a ConsumerOrder. Tramite l'API Provider, l'ordine può essere accettato, che pubblicherà un ProviderOrderAcceptedEvent, che consentirà a ConsumerOrders di contrassegnare l'ordine come accettato e informare il consumatore a riguardo.

Il mio approccio personale preferito è l'opzione 2 in quanto vedo diversi vantaggi (vedi sotto), ma non sono sicuro che valgano la complessità aggiunta.

Non posso formulare una domanda specifica, ma poiché questo problema deve essere stato risolto migliaia di volte, vorrei sapere se esiste un approccio preferito, una soluzione ben nota o un progetto di riferimento che possa aiutarmi.

Vantaggi dei contesti separati di ProviderOrders e ConsumerOrders:

  1. Un singolo ConsumerOrder può generare più ProviderOrders (se l'ordine contiene prodotti di più provider
  2. Il flusso di lavoro di un ProviderOrder potrebbe essere diverso / più complesso rispetto al flusso di lavoro di un ConsumerOrder.
  3. Sia il consumatore che il fornitore devono vedere la cronologia degli ordini, che immagino come una tabella denormalizzata per letture veloci, ma entrambe le cronologie degli ordini contengono dati diversi (ad esempio gli ordini dei consumatori contengono informazioni sui provider e gli ordini dei fornitori contengono informazioni sui consumatori) e sono interrogato in modo diverso (dal consumatore e dal fornitore). Questo può essere implementato in un'unica tabella, ovviamente, ma sembra più pulito se si tratta di 2 tabelle dedicate a un unico scopo.
  4. Isolamento dati / partizionamento. Gli ordini cliente sono sempre accessibili dall'ID consumatore, gli ordini fornitore sono sempre accessibili da ProviderId.

Ho una conversazione molto interessante su questo argomento in un forum separato, quindi ho pensato di collegarlo qui, nel caso qualcuno volesse leggere più pensieri su questo argomento. La stessa domanda sul forum di discussione di NServiceBus

Nota: è implementato in .NET, da più team, da più repository e soluzioni Visual Studio, ospitato in un cluster di Service Fabric e utilizzando NServiceBus per la messaggistica.

    
posta Francesc Castells 19.02.2018 - 16:47
fonte

3 risposte

6

L'approccio a due contesti riduce la complessità segregando il nucleo in più contesti ciascuno specificamente responsabile della realizzazione e dell'applicazione delle regole. Rende anche il tuo modello più espressivo.

È un comune malinteso che gli oggetti Dominio dovrebbero essere basati su qualche "cosa" fisica (cioè Cliente, Ordine, Fornitore). Dobbiamo ricordare che l'obiettivo di DDD è quello di modellare il comportamento di un sistema in modo tale che il modello risultante rappresenti astrazioni utili in base ai requisiti funzionali e alla logica del core business. Poiché i dati degli oggetti del mondo reale forniscono raramente un buon punto di partenza per la modellazione dei requisiti funzionali, è più probabile che gli oggetti del dominio vengano denominati in base al comportamento in cui si impegnano piuttosto che ai dati / agli attributi che contengono.

Molti progetti iniziano con il modello fisico in prima linea nel processo di modellazione che spesso porta a oggetti con troppe responsabilità e preoccupazioni che si sovrappongono (in definitiva si manifestano nel tuo problema sopra con confusione su chi "possiede" cosa). Termini come Cliente, Ordine e Prodotto (oltre a non implicare alcun comportamento) tendono ad essere troppo astratti, comprendono troppa conoscenza e, quindi, probabilmente non sono molto utili per rappresentare la logica di business.

Tenendo presente quanto sopra, diamo un'occhiata ad alcuni possibili oggetti di dominio che potremmo trovare in alcuni contesti diversi:

Shopping

  • Shopper
  • ShoppingCart
  • CartItem
  • Coupon
  • Marca

Fatturazione

  • Cassiere
  • Il compratore
  • Il venditore
  • PurchaseOrder
  • LineItem
  • paymentmethod
  • BuyerInvoice
  • SalesReceipt
  • valuta
  • Denaro

Logistica

  • Produttore
  • Consumer
  • PurchaseRequest
  • prodotto
  • ProductType

Si noti che ciò interrompe il "Cliente" in ruoli più specifici più adatti a enfatizzare il comportamento (acquirente, acquirente, consumatore). Altri contesti possono suddividere ulteriormente un "Cliente" (Visitatore, Utente, Revisore, ecc.). Lo stesso vale per "Ordine" (ShoppingCart, PurchaseOrder, PurchaseRequest), "OrderItem" (CartItem, LineItem, Product) e "Provider" (Marca, Venditore, Produttore).

Sebbene molti di questi oggetti si associno allo stesso modello fisico, i dati vengono suddivisi e gestiti in base a diversi modelli logici. Ad esempio, potremmo voler conoscere l'indirizzo IP degli acquirenti, la cronologia delle transazioni degli acquirenti e l'indirizzo dei consumatori (o i metadati come entrate per l'analisi).

Spero che questo ti guidi nella giusta direzione.

    
risposta data 21.02.2018 - 17:54
fonte
2

Suppongo che tu stia utilizzando un'architettura di microservizi per disaccoppiare la tua applicazione in parti indipendentemente operative / scalabili / sviluppabili / distribuibili.

Mi sembra che "ProviderOrders" e "ConsumerOrders" non siano indipendenti in questo senso. Sono interdipendenti. Hanno bisogno di comunicare in entrambe le direzioni, hanno bisogno di ognuno per adempiere alle proprie responsabilità, hanno una dipendenza circolare. Eventing coprirebbe questo aspetto fino ad un certo punto, ma è ancora lì.

Quindi questo sarebbe un argomento contro opzione 2

Ora puoi ancora mantenere entrambi i concetti e tutti i vantaggi di ciò, e metterlo in un unico servizio. Chiamiamo quella versione 1B. Elimina la dipendenza circolare concettuale e il sovraccarico della comunicazione.

    
risposta data 21.02.2018 - 14:44
fonte
1

Penso che sia un servizio di portineria con più venditori. Non sarai in grado di arrivare alla conclusione in questo modo.

Ci sono molte dipendenze tra consumatori e fornitori. In realtà nessun fornitore possiede un ordine perché un ordine può contenere logicamente molti prodotti dei fornitori ma richiede fisicamente un singolo prodotto particolare, vale a dire un ordine da un consumatore può avere 3 prodotti da 3 diversi fornitori. Quindi ogni fornitore riceve un singolo ordine dall'ordine di quel consumatore.

Devi analizzare fisicamente l'ordine piuttosto dal punto di un consumatore.

    
risposta data 20.02.2018 - 09:36
fonte