Domanda

Appena finito leggi questo post di Greg Young, dove parla di Microsoft che consiglia modelli con oggetti di trasferimento dati stupidi. Ha insinuato che nella comunità Java, le cose stanno andando nella direzione opposta.

La mia domanda è: quanta logica dovrebbe esserci nei tuoi oggetti entità? La nostra filosofia in cui lavoro (negozio C #) è che se non riesci a serializzarlo, non inserirlo nell'entità.

È stato utile?

Soluzione

Matt,

Direi che il tuo negozio sta scrivendo un codice procedurale. Voglio chiarire che non c'è nulla di sbagliato nel fatto che molti sistemi di grandi dimensioni (inclusi molti su cui ho lavorato) sono stati scritti usando un codice procedurale. C'è un tempo e un luogo per questo.

Ora il codice procedurale non ha spazio in un modello di dominio. Se vuoi usare uno stile più procedurale che va bene ma usalo con qualcosa come un modulo da tavolo o un modello di record attivo. Non è la mancanza di OO che sto considerando essere così distruttiva nella guida ma l'uso di un modello di dominio con logica procedurale.

Questo fa sì che si spenda una grande quantità di risorse per costruire il livello del dominio (disadattamento dell'impedenza, tempo del processo di pensiero per costruire aggregati, isolamento, linguaggio onnipresente ecc.) senza ricevere nessuno dei vantaggi che il livello del dominio (generalmente manutenibilità) avrebbe altrimenti fornire. In altre parole, mentre potresti soddisfare i tuoi requisiti funzionali, finisci per spendere una grande quantità del tuo budget con quasi nessun ritorno.

Ora per tornare a ciò che è "comportamento" Vorrei concentrarmi sulla domanda da un oggetto orientato al contrario di un "Domain Driven Design" punto di vista. Un oggetto generalmente incapsulerà un certo stato e in genere esporrà alcuni comportamenti.

reiterazione rapida: incapsulare lo stato, esporre il comportamento

Quindi quali comportamenti dovrebbe avere un oggetto? In parole povere, dovrebbero essere i comportamenti che operano sullo stato in cui si incapsula. In un mondo OO comportamentale ideale lo stato non sarebbe mai esposto solo ai comportamenti oggetto. Metti tatticamente nel codice se iniziamo a vedere codice come:

Customer c = GetCustomerFromRepository();
c.Status = CustomerStatuses.Deleted;
c.LastUpdated = DateTime.Now;
c.UpdatedBy = GetCurrentUser();
CustomerRepository.Save(c);

Abbiamo una violazione di SRP ... Questo codice è un codice che dovrebbe essere un comportamento dell'oggetto cliente perché la "Responsabilità" dell'oggetto cliente è.

Incapsula lo stato di un cliente ed espone comportamenti.

Come tale possiamo vedere che sarebbe meglio avere un metodo Customer.Delete (). (sì, questo è un cattivo esempio, lo so ...)

Ora arriveremmo a questo anche usando TDD. È molto più facile per noi affrontare i test con la cucitura fornita dal comportamento rispetto alle cuciture in cui è esposto tutto lo stato. Il motivo è che non ho bisogno di duplicare la logica nei miei test. Il codice client non si preoccupa del funzionamento di un'eliminazione ... importa solo che il cliente espone il comportamento. Come tale nei nostri test invece di affermare che c.State == CustomerStates.Deleted e c.UpdatedBy == GetCurrentUser () ecc ecc., Affermeremmo semplicemente che il metodo di eliminazione è stato chiamato sulla giuntura del cliente usando un mock.

Ora per tornare al titolo. La quantità di logica che dovrebbe essere in un oggetto business è la quantità di logica che rientra nella sua responsabilità di incapsulare il suo stato. A volte questo è molto, a volte no. Esistono luoghi in cui si desidera utilizzare anche i servizi ... un buon esempio potrebbe essere il coordinamento dell'interazione tra molti oggetti di dominio per un determinato comportamento, ma anche qui il servizio dovrebbe chiamare comportamenti sugli oggetti di dominio .

Questo aiuta a chiarire un po 'le cose?

Greg

Altri suggerimenti

Se li stai chiamando i tuoi " oggetti modello di dominio " quindi presumo che ti riferisci al modello del modello di dominio di Fowler. http://martinfowler.com/eaaCatalog/domainModel.html

Alla luce di tale presupposto, la risposta alla tua domanda è "tutta la logica aziendale" poiché questa è essenzialmente la definizione del modello.

Sfortunatamente il termine "modello di dominio" sembra essere stato annacquato di recente per significare solo un modello a oggetti dei tuoi dati senza comportamento.

Se non l'hai già fatto, ti incoraggio a leggere PoEAA e decidere dove pensi che la logica di dominio appartenga alla tua situazione. Se decidi un modello di dominio, ti incoraggio a leggere il libro DDD di Evan e conoscere le differenze tra entità, oggetti valore e servizi.

Spero che ti aiuti!

Ultimamente, ho giocato con l'idea di creare modelli di dominio che hanno struttura e solo quei comportamenti universali per quel modello (cioè comportamenti che possono essere usati in più contesti limitati) con metodi di estensione per il comportamento specifico a un contesto limitato. Ciò mantiene i modelli di dominio vicini a un DTO (per quelli a cui piace) e limita l'uso di quel modello di dominio solo ai comportamenti consentiti all'interno di un contesto limitato. Quindi potrebbe essere un'opzione per una risposta a metà strada. :)

Il punto principale è come si definisce la logica. Per fare alcuni esempi:

  1. Non classificherei una funzione getFullName () in un'entità Person, che concatena solo alcune stringhe, come logica.
  2. Il calcolo di un valore di un articolo dell'ordine si qualificherebbe molto probabilmente come logico.
  3. Effettuare alcune transazioni di prenotazione direi sicuramente logico.

Il punto 1 e forse 2 andrebbero per me nell'entità. Punto 3 no. Quindi definisco la logica come:

  • qualsiasi operazione che fa qualsiasi cosa relativa alla persistenza (lettura / scrittura)
  • qualsiasi operazione che coinvolga qualsiasi altra entità (non direttamente correlata, ad esempio dettaglio principale)

IMO, nessuna di queste operazioni non appartiene a entità.

Ora, perché / quando non metterei anche le operazioni di tipo punto 1 e 2 in un'entità? È una situazione piuttosto rara, ma non lo farei, non appena i dati archiviati nell'entità devono essere interpretati in qualche modo prima di poter essere utilizzati dall'applicazione (ad es. Se in base all'utente corrente, contenuto del campo X ha un significato diverso), ciò significa che i dati dell'entità stessa producono una certa logica.

Per quanto ho capito, tutte le logiche aziendali relative a un'entità dovrebbero andare in quell'entità. È costituito da qualsiasi logica che definisce il comportamento o la struttura interna dell'entità in base alle regole aziendali del sistema. Ciò non dovrebbe includere la logica di presentazione o la logica di persistenza (l'eccezione evidente è con il modello di progettazione Record attivo) ma dovrebbe includere elementi come la convalida dei dati, le relazioni tra entità, le macchine a stati e altre cose che definiscono il comportamento dell'entità in termini di reale- cosa del mondo che sta cercando di modellare.

Il modo in cui provo a guardarlo è quello di provare a rendere i miei modelli il più affidabili possibile. Cerca sempre di pensare a come il modello verrebbe utilizzato se dovesse essere trasferito su un sistema diverso in cui il codice client (o il codice che utilizza l'entità) potrebbe essere diverso. Se la funzionalità non fa parte dell'entità, si comporterà comunque allo stesso modo seguendo le stesse regole aziendali? Se la risposta è no, allora la funzionalità dovrebbe andare nell'entità.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top