2015-07-21 6 views
5

Quando ho iniziato a utilizzare DDD, ho creato i metodi Equals() nelle mie entità che hanno confrontato l'ID dell'entità. Quindi due oggetti entità con lo stesso ID sarebbero considerati uguali.Le entità DDD dovrebbero essere confrontate per riferimento o per ID?

A un certo punto ho pensato a questo e ho scoperto che due entità in stati diversi non dovrebbero essere considerate uguali, anche quando descrivono la stessa cosa (cioè hanno lo stesso ID). Quindi ora utilizzo l'uguaglianza di riferimento per le mie entità.

Ho poi inciampò this answer da Mark Seemann, dove scrive

entità sono uguali se i loro ID uguali tra loro.

Ora, ovviamente, mi piacerebbe sapere quale approccio è migliore.

Modifica: Si noti che la domanda non è se avere due istanze della stessa entità allo stesso tempo è una buona idea. Sono consapevole che nella maggior parte delle situazioni probabilmente non lo è.

+0

Perché hai la stessa entità in due stati diversi? –

+1

Come può la stessa istanza essere in uno stato diverso allo stesso tempo? –

+0

@ marianoc84 Ciò potrebbe accadere ad es. in un'applicazione desktop in cui gli oggetti in genere vivono più a lungo rispetto a un'app Web. L'utente può aggiornare un'entità in memoria e leggerlo di nuovo dal DB restituisce la vecchia versione. – theDmi

risposta

4

La domanda è duplice. Innanzitutto, quello che vuoi veramente sapere è

Come gestire i termini imposti dal linguaggio X (o dal framework Y) quando codifico un modello di dominio con esso?

C# per esempio ti impone che qualsiasi nuovo concetto definito eredita uno certain set of public methods. Java include even more methods.

Non ho mai sentito un esperto di dominio che parla di codici hash o di uguaglianza delle istanze, ma questa è una di quelle situazioni in cui si applica la citazione (spesso non compresa) "non combattere il framework" di Evans: basta insegnare agli sviluppatori a non li usa quando non appartengono alle interfacce del dominio.

Quindi, ciò che si vuole sapere è

Qual è un'entità? Come si relaziona con la propria identità?

Inizia con perché! Sai che le entità sono termini del linguaggio ubiquitario che sono identificabili.

Ma PERCHÉ?

Plain semplice: entità descrivono concetti la cui evoluzione nel tempo è rilevante nel contesto del problema che stiamo risolvendo!

È la rilevanza dell'evoluzione che definisce l'entità, non il contrario! L'identità è solo uno strumento di comunicazione per tenere traccia dell'evoluzione, per parlarne.

Per esempio pensa a te: sei una persona con un nome; usiamo il tuo nome per comunicare le tue interazioni con il resto del mondo durante la tua vita; ancora, non sei quel nome.

Chiediti: perché ho bisogno di confrontare le entità di dominio? L'esperto di dominio parla in questo modo? Oppure sto usando un linguaggio DDD per descrivere un'applicazione CRUD che interagisce con un database relazionale?
Per me, la necessità di implementare effettivamente Equals(object) o GetHashCode() in un'entità sembra un odore di un'infrastruttura inadeguata.

+0

Ora questa risposta contiene un ragionamento completo, questo è quello che stavo cercando! – theDmi

+0

+1, potresti spiegare cosa intendi con: "un odore di infrastruttura inadeguata"? Ho posto una domanda simile qui se vuoi rispondere: "https://softwareengineering.stackexchange.com/questions/364895/entity-and-value-object-are-not-part-of-the-ubiqtious-language -should-this-stop " – w0051977

+0

@ w0051977 [questa risposta] (https://softwareengineering.stackexchange.com/a/364909/83461) riassume bene la mia opinione. Distinguo i contratti (interfacce delle entità, eccezioni, oggetti valore, interfacce dei servizi di dominio) in una DLL, implementazioni (poco/pojo delle entità) in un'altra e infrastruttura (mappature orm, archivi eventi e implementazioni di servizi di dominio spesso) in un'altra . Questo per ogni contesto limitato. Se vuoi qualche informazione sui miei metodi dare un'occhiata al [Manuale di Epic] (http://epic.tesio.it/doc/manual/manual.html). –

4

Penso che sia una cattiva idea avere le due istanze separate della stessa entità in stati diversi. Non riesco a pensare a uno scenario in cui sarebbe auspicabile. Forse ce n'è uno? Credo che ci dovrebbe essere sempre un'istanza di una data entità con un ID particolare.

In generale confronterei la loro uguaglianza usando i loro ID.

Ma se si voleva verificare se sono lo stesso riferimento all'oggetto, allora si potrebbe utilizzare:

 if (Object.ReferenceEquals(entityA, entityB)) 
     { 
      DoSomething(); 
     } 
+0

Sono d'accordo che non è una situazione desiderabile avere due istanze della stessa entità. Ma allora, perché preoccuparsi e creare un'implementazione Equals che si confronta per ID? – theDmi

+0

Penso che la ragione per farlo sia fare una distinzione tra oggetti di valore ed entità quando li si confronta.Ad esempio, quando confronti oggetti di valore come: "if (vo1 == vo2)", allora dovrebbe comparare i valori delle loro proprietà. Ma se hai fatto lo stesso per le entità: 'if (e1 == e2)' allora dovrebbe controllare gli ID. Se non hai implementato le sovrascrizioni di uguali, lo sviluppatore chiamante dovrebbe sapere se controllare manualmente gli ID oi valori delle proprietà a seconda del tipo di oggetto (entità o valore). Ma implementando gli override, non devono preoccuparsi. –

6

Le entità non devono essere confrontati in quel modo, in primo luogo. Non esiste un caso d'uso valido (al di fuori del test, ma di nuovo la libreria di asserzione dovrebbe gestirlo per voi) per vedere se 2 entità sono uguali usando il metodo Equals dell'oggetto.

Ciò che rende unica un'entità è il suo ID. Lo scopo dell'ID è di dire "questa stessa entità è diversa dalle altre entità pur avendo proprietà/valori identici".

Detto questo, in un dominio potrebbe essere necessario confrontare un concetto un'istanza con un'altra istanza. Il confronto viene eseguito in base allo specifico Contesto limitato (o anche Aggregato) Regole di dominio. Non importa che un'entità sia coinvolta, potrebbe anche essere un oggetto di valore.

Fondamentalmente il "confronto" dovrebbe essere un caso di utilizzo del dominio che sarà probabilmente implementato come un servizio. Questo non ha alcuna relazione con il metodo Equals di un oggetto, che è un aspetto tecnico.

Quando si esegue DDD, non pensare come un programmatore (vale a dire gli aspetti tecnici) pensa come un architetto (alto livello). Codice, linguaggio di programmazione ecc. È solo un dettaglio di implementazione.