Domain Model: ok, fucilatemi...

rated by 0 users
This post has 3 Replies | 2 Followers

Top 10 Partecipanti
Post 183
Punteggio 3.383
petrux Posted: 06-07-2010 18.56
...ma io ancora non ho capito la differenza tra un DomainModel e un
banale modello delle entità con la business logic implementata dai vari
I*Service (anche se ho letto il libro di Andrea :-p). Qualche link?

Ciao e grazie,
Giulio
--
  • | Punteggio Post: 20
Top 10 Partecipanti
Maschio
Post 48
Punteggio 1.090

Semplificando, in DDD:

  • le entità non sono anemiche ma contengono anche tutta l'algebra che le riguarda direttamente
  • la logica che coinvolge più entità sta dentro servizi 

I servizi sono:

  • "domain services" se la logica è usata "tale e quale" indipendentemente dal caso d'uso
  • "application services" (application layer) se servono a casi d'uso specifici
  • "infrastructure services" se sono ad uso e consumo di tutti (es: messaging, logging, ...)

ti "torna"?

 

.A

Top 10 Partecipanti
Post 183
Punteggio 3.383
Ciao andysal,

andysal wrote:
> ti "torna"?

A parole torna tutto magnificamente, non c'è che dire. Mi manca un
esempio concreto (magari comparativo).

> Semplificando, in DDD:
>
> * le entità non sono anemiche ma contengono anche tutta l'algebra
> che le riguarda direttamente

Esempio:

class Foo {
protected Foo(string l) { this.Label = l; }
string Label { get; private set; }
public static Foo CreateFoo(string label) { ... }
}

se ho il vincolo che la label sia unica, dove va "cablato"? Nella
factory di Foo?

> * la logica che coinvolge più entità sta dentro servizi

più entità della stessa classe o tipi diversi di entità?
(Ti sto prendendo sullo sfinimento, eh? )

> I servizi sono:
>
> * "domain services" se la logica è usata "tale e quale"
> indipendentemente dal caso d'uso
> * "application services" (application layer) se servono a casi d'uso
> specifici
> * "infrastructure services" se sono ad uso e consumo di tutti (es:
> messaging, logging, ...)

Qui siamo chiarissimi. :-)

Ciao e grazie,
petrux

--
  • | Punteggio Post: 5
Top 10 Partecipanti
Post 183
Punteggio 3.383
Ciao andysal,

riguardo all'altra mia risposta, un esempio facile facile per iniziare
te lo propongo io.

andysal wrote:
> Semplificando, in DDD:
>
> * le entità non sono anemiche ma contengono anche tutta l'algebra
> che le riguarda direttamente
> * la logica che coinvolge più entità sta dentro servizi

Supponiamo di avere:

enum ActivityStatus
{
Unstarted,
InProgress,
Postponed,
Reassigned,
Complete,
Canceled,
}

class Activity
{
ActivityStatus Status { get; set; }
}


la logica intrinseca alla classe Activity prevede che:
a) quando una Activity viene creata il suo status è posto a Unstarted;
b) una volta cambiato lo stato da Unstarted -> * non è più possibile
ri-assegnare Unstarted;
c) una volta assegnato Complete/Canceled non è più possibile cambiare
status;
d) la transizione Unstarted --> Canceled è *PROIBITA* (questo mi serve
per incasinare un po' le cose ed arrivare al punto).

A occhio mi verrebbe da dire che in un ottica DDD la logica per la
verifica di questi vincoli vada cablata nel setter della property
Status; in questo modo avrei una cosa del tipo:

class Activity
{
private ActivityStatus status = ActivityStatus.Unstarted;
public virtual ActivityStatus Status
{
get { ... }
set { ...logica... }
}
}

Ragionando sui 4 vincoli sopra esposti:
a) la prima idea che mi viene in mente è di esporre un unico costruttore
(o factory che richiama un .ctor() protected) che abbia questa logica qui:

public/protected Activity()
{
status = ActivityStatus.Unstarted;
}

ovviamente nel repository/servizio docuto ci dovrà essere un controllo
sul metodo Add() per cui, se lo status è diverso da Unstarted viene
sollevata una ArgumentException.

b/c) non presentano particolari problemi: quando l'entità viene letta
dalla persistenza viene invocato il ctor() che setta lo status a
unstarted, poi viene assegnato un valore che sarà comunque possibile
tranne ne caso in cui...

d) ...tranne nel caso in cui il valore di destinazione sia Canceled.

I problemi sono questi:
1) Qualora esponessi un metodo SetStatus() e rendessi private il setter
della property, il mio DAL (ottenuto con NHibernate, EF) potrebbe
settare il valore di status 'as is' richiamando il setter privato della
peoperty via reflection?
2) oppure bisogna necessariamente esporre un altro costruttore/factory
method per la creazione di una entity con un dato status?
3) riguardo alla risoluzione del punto 'a' sopra proposta, il fatto di
avere un controllo sull'Add() del repo/service non causa uno
"sparpagliamento" della logica in più punti (un po' qui e il resto nel
setter della property o metodo SetStatus())?

Spero di essere stato chiaro.
Ciao e grazie,
petrux

--
  • | Punteggio Post: 5
Pagina 1 di 1 (4 elementi) | RSS
Powered by Community Server (Commercial Edition), by Telligent Systems