2012-05-04 20 views
15

An interesting thread si avvicinò quando ho digitato questa domanda proprio ora. Non penso che risponda alla mia domanda però.Un "modello di dominio ricco" può violare il Principio di Responsabilità Singola?

Ho lavorato molto con .NET MVC3, dove è preferibile avere un modello anemico. Visualizza modelli e modifica modelli sono i migliori come contenitori di dati stupidi che puoi passare da un controller a una vista. Qualsiasi tipo di flusso di applicazioni dovrebbe provenire dai controller e le visualizzazioni gestiscono i problemi dell'interfaccia utente. In MVC, non vogliamo alcun comportamento nel modello.

Tuttavia non vogliamo alcuna logica di business nei controller. Per le applicazioni più grandi è meglio tenere il codice del dominio separato e indipendente da modelli, viste e controllori (e HTTP in generale per quella materia). Quindi esiste un progetto separato che fornisce, prima di ogni altra cosa, un modello di dominio (con entità e oggetti valore, composti in aggregati secondo DDD).

Ho fatto qualche tentativo di allontanarmi da un modello anemico verso uno più ricco nel codice di dominio, e sto pensando di rinunciare. Mi sembra che avere classi di entità che contengono dati e comportamenti viola l'SRP.

Prendi ad esempio uno scenario molto comune sul web, componendo e-mail. Dato un certo evento, è responsabilità del dominio comporre un oggetto EmailMessage dato un EmailTemplate, EmailAddress e valori personalizzati. Il modello esiste come entità con proprietà e i valori personalizzati vengono forniti come input dall'utente. Diciamo anche per il ragionamento che l'indirizzo FROM di EmailMessage può essere fornito da un servizio esterno (IConfigurationManager.DefaultFromMailAddress). A fronte di tali requisiti, sembra un ricco modello di dominio potrebbe dare l'EmailTemplate la responsabilità di comporre l'EmailMessage:

public class EmailTemplate 
{ 
    public EmailMessage ComposeMessageTo(EmailAddress to, 
     IDictionary<string, string> customValues, IConfigurationManager config) 
    { 
     var emailMessage = new EmailMessage(); // internal constructor 
              // extension method 
     emailMessage.Body = this.BodyFormat.ApplyCustomValues(customValues); 
     emailMessage.From = this.From ?? config.DefaultFromMailAddress; 
     // bla bla bla 
     return emailMessage; 
    } 
} 

Questo è stato uno dei miei tentativi di ricco modello di dominio. Tuttavia, dopo aver aggiunto questo metodo, era responsabilità di EmailTemplate sia contenere le proprietà dei dati di entità che i messaggi di composizione. Era lungo circa 15 righe e sembrava distrarre la classe da ciò che significa realmente essere un EmailTemplate - che, IMO, è solo per memorizzare i dati (formato soggetto, formato del corpo, allegati e indirizzi opzionali da/reply-to).

Ho finito per refactoring questo metodo in una classe dedicata, che è l'unica responsabilità è la composizione di un EmailMessage dato gli argomenti precedenti, e io sono molto più felice con esso. In effetti, sto iniziando a preferire domini anemici perché mi aiuta a mantenere le responsabilità separate, rendendo le lezioni e i test unitari più brevi, più concisi e più mirati. Sembra che rendere entità e altri oggetti dati "privi di comportamento" possano essere utili per separare la responsabilità. O sono fuori pista qui?

+1

Un modello di dominio ricco deve essere ricco appena sufficiente per il contesto in cui è rilevante. –

risposta

19

L'argomento a favore di un modello di dominio ricco anziché di un modello anemico dipende da una delle proposte di valore di OOP, che mantiene il comportamento e i dati uno accanto all'altro. Il vantaggio principale è quello di incapsulamento e coesione che aiuta a ragionare sul codice. Un modello di dominio ricco può anche essere visualizzato come un'istanza del modello information expert. Il valore di tutti questi modelli tuttavia è in gran parte soggettivo. Se è più utile per te tenere separati dati e comportamenti, così sia, anche se potresti anche considerare altre persone che guarderanno il codice. Preferisco incapsulare il più possibile. L'altro vantaggio di un modello di dominio più ricco in questo caso sarebbe la possibilità di rendere certe proprietà private. Se una proprietà viene utilizzata da un solo metodo sulla classe, perché renderla pubblica?

Se un modello di dominio ricco viola l'SRP dipende dalla definizione di responsabilità. Secondo SRP, una responsabilità è un motivo per cambiare, che a sua volta richiede una definizione. Questa definizione dipenderà generalmente dal caso d'uso in questione.È possibile dichiarare che la responsabilità della classe template deve essere un modello, con tutte le implicazioni che si presentano, una delle quali sta generando un messaggio dal modello. Una modifica in una delle proprietà del modello può influire sul metodo ComposeMessageTo, che indica che forse si tratta di una singola responsabilità. Inoltre, il metodo ComposeMessageTo è la parte più interessante del modello. Ai client del modello non interessa come viene implementato il metodo o quali proprietà sono presenti nella classe template. Vogliono solo generare un messaggio basato sul modello. Questo anche a favore del mantenimento dei dati accanto al metodo.

+0

Ottima risposta, grazie. – danludwig

0

Bene, dipende da come si vuole guardarlo.

Un altro modo è: "Il principio di responsabilità singola può violare un modello di dominio ricco?"

Entrambi sono linee guida. Non c'è alcun "principio" da nessuna parte nella progettazione del software. Ci sono, tuttavia, buoni disegni e cattivi disegni. Entrambi questi concetti possono essere utilizzati in modi diversi, per ottenere un buon design.