Se la radice aggregata ha una proprietà che non può validare [duplicato]

0

Mi sono imbattuto nella situazione in cui devo decidere se una proprietà appartiene o meno al mio aggregato. La mia logica di dominio è la seguente. Un utente ha un gruppo nella sua organizzazione: IT, SALES, MARKETING. A seconda del gruppo a cui appartiene questo utente, avrà una serie di permessi. La logica di quale gruppo ha quali autorizzazioni sono definite nelle Politiche del sito. Una politica è una mappatura tra un gruppo e un insieme di permessi. ex: il gruppo IT ha le autorizzazioni per visualizzare post, modificare post ed eliminare post.

Ho 2 aggregati: utente e sito Web (gestiamo più siti Web)

La domanda è: le autorizzazioni dovrebbero far parte dell'aggregato utente?

È facile e in qualche modo ha senso avere le autorizzazioni nell'aggregato dell'utente in modo che possa essere richiesto in qualsiasi momento. Ma il problema che vedo con questo è che la radice aggregata dell'utente non sarà in grado di soddisfare questo invariante: "Un utente dovrebbe avere le autorizzazioni che sono definite per i gruppi a cui appartiene" e poiché le autorizzazioni sono dati transitori e non sono persistenti Penso che non dovrebbe far parte della User AR.

L'altra opzione sarebbe avere un servizio di dominio o un metodo nella AR del sito web che restituisce le autorizzazioni per un utente specifico. E quindi utilizzare questo metodo ogni volta che sono necessarie le autorizzazioni.

    
posta Mohamed Bouallegue 01.06.2018 - 16:10
fonte

1 risposta

1

In poche parole, No, un aggregato non dovrebbe dipendere da un pezzo di stato per il quale non è la rappresentazione singola, autorevole e non ambigua. Il vero problema qui è che la domanda che stai ponendo è ortogonale al problema che stai cercando di risolvere.

Potresti riuscire a riorganizzare il tuo dominio attuale in un modo che potrebbe soddisfare i tuoi requisiti introducendo macchine a stati concorrenti in cui ogni stato ( ITGroupMember , ecc.) è l'entità diretta responsabile dell'esecuzione delle tue azioni e ogni User è dati una raccolta Membership o simili, ma questo tipo di soluzione porterà indubbiamente a problemi lungo la strada ed è, francamente, molto più complesso del necessario.

In generale, l'autorizzazione / autenticazione sono preoccupazioni trasversali che non si prestano bene a essere modellate utilizzando i principi DDD. La semplice definizione dei requisiti per un tale sistema dovrebbe chiarire questo:

In termini astratti, per autorizzare qualsiasi comando dato nel tuo dominio, quel comando deve essere 1) iniettato con o 2) avvolto da un ulteriore pezzo di logica, ad esempio un AuthorizationContext , in modo che i dati di Permissions possano essere resi disponibili per quel comando per la convalida. In pratica, la soluzione più adatta è quella di avvolgere i comandi perché porta ad un accoppiamento inferiore (i comandi stessi non devono sapere nulla sull'autorizzazione).

Nei termini DDD, l'autorizzazione potrebbe assumere uno dei moduli sopra. Potresti iniettare ogni entità con il tuo AuthorizationContext in modo che ogni metodo di entità abbia accesso ai dati necessari per l'autorizzazione (che riguarda ciò a cui sei atterrato e che chiedi qui), oppure potresti trattare ogni entità come una macchina di stato in cui ogni stato rappresenta un particolare insieme di permessi (in questo modo avvolge le chiamate al metodo). Nessuna di queste soluzioni è particolarmente elegante e entrambe introducono un accoppiamento extra e spostano l'attenzione del modello dall'esecuzione della logica di business. In quanto tale, non posso raccomandare uno dei due metodi precedenti.

L'approccio più tradizionale sarà semplicemente "aumentare" l'autorizzazione sopra il livello del dominio e autorizzare i comandi prima che vengano eseguiti. Questo può assumere la forma di thin service layer. Questo è di gran lunga il caso più comune. Quasi ogni framework web che ho incontrato esegue un'autorizzazione / autenticazione tramite una sorta di servizio middleware che viene richiamato prima dell'esecuzione di qualsiasi codice di dominio. La maggior parte usa una sorta di annotazione di dati direttamente sui metodi del controllore. Potresti semplicemente prendere una pagina da questo playbook e implementare qualcosa di simile (questo è essenzialmente solo un comando di mappatura della configurazione globale ai ruoli).

Se questo deve essere fatto secondo DDD, abbiamo bisogno di avere una discussione più ampia. Una pietra miliare del DDD è il refactoring verso intuizioni più profonde e l'esplicitazione implicita. Ricorda, l'obiettivo di DDD è quello di modellare i requisiti comportamentali di un sistema tale che il risultato sia un'astrazione utile del dominio aziendale. La chiave è concentrarsi sul comportamento di un sistema, non sui dati. Questo perché i dati di un determinato sistema raramente sono un buon punto di partenza per la modellazione dei requisiti funzionali. Il singolo problema più grande che vedo nel tuo dominio è l'inclusione di un'entità User . Scommetterei il mio nipotino che l'unica ragione per cui esiste un'entità User nel tuo dominio è perché hai una tabella [utente] / documento / qualsiasi cosa nel tuo archivio dati.

User di solito è una scelta sbagliata per un oggetto di dominio perché denota quasi nessun comportamento e probabilmente include troppa conoscenza. Cosa fa il tuo Users ? Commento? %codice%. Vota? %codice%. Revisione? %codice%. Vedi dove vado? È necessario suddividere i dati verticalmente per raggruppare i dati correlati in base al comportamento . Forse un Commenter ha un Rater . Un Reviewer ha bisogno di un Commenter ? No. I confini della normalizzazione sono molto improbabili che siano i confini di tutte le tue entità.

So cosa stai pensando. In che modo il partizionamento dell'entità PastCommentCollection risolve il mio particolare problema riguardante l'autorizzazione? E a questo, lascerò tu con una domanda:

Che cosa succede se Rater genera un PastCommentCollection per ogni User che non può essere correlato alle autorizzazioni appropriate necessarie per valutare qualcosa?

    
risposta data 04.06.2018 - 22:07
fonte