2010-05-18 10 views
67

Sto cercando di capire i modelli di dominio anemico e il motivo per cui si suppone siano un anti-modello.Evitare il modello di dominio anemico - un esempio reale

Ecco un esempio reale.

Ho un classe Employee, che ha un sacco di proprietà - nome, sesso, nome utente, ecc

public class Employee 
{ 
    public string Name { get; set; } 
    public string Gender { get; set; } 
    public string Username { get; set; } 
    // Etc.. mostly getters and setters 
} 

successivo abbiamo un sistema che coinvolge a rotazione le chiamate in arrivo e richieste di informazioni del sito web (noto come 'lead ') uniformemente tra il personale di vendita. Questo sistema è piuttosto complesso in quanto prevede richieste di round-robining, controllo delle vacanze, preferenze dei dipendenti, ecc. Quindi questo sistema è attualmente separato in un servizio: EmployeeLeadRotationService.

public class EmployeeLeadRotationService : IEmployeeLeadRotationService 
{ 
    private IEmployeeRepository _employeeRepository; 
    // ...plus lots of other injected repositories and services 

    public void SelectEmployee(ILead lead) 
    { 
     // Etc. lots of complex logic 
    } 
} 

Poi sul retro del nostro modulo di richiesta web abbiamo codice come questo:

public void SubmitForm() 
{ 
    var lead = CreateLeadFromFormInput(); 

    var selectedEmployee = Kernel.Get<IEmployeeLeadRotationService>() 
           .SelectEmployee(lead); 

    Response.Write(employee.Name + " will handle your enquiry. Thanks."); 
} 

Non mi incontrano molti problemi con questo approccio, ma presumibilmente questo è qualcosa che avrei dovuto correre urlando perché è un modello di dominio anemico .

Ma per me non è chiaro dove dovrebbe andare la logica nel servizio di rotazione di piombo. Dovrebbe andare in testa? Dovrebbe andare nel dipendente?

E che dire di tutti i repository iniettati ecc. Che il servizio di rotazione richiede - come verrebbero iniettati nel dipendente, dato che la maggior parte delle volte quando ci occupiamo di un dipendente non abbiamo bisogno di nessuno di questi repository?

+0

+1 ottima domanda! – mdma

+0

Quindi, come appare un 'ILead', se non è ovvio inserire .SelectEmployee() in esso? –

+0

Beh, in questo caso il lead è un'inchiesta web, quindi avrà una proprietà Comments, ecc. Ma abbiamo anche richieste telefoniche, applicazioni, preventivi ecc. Che sono tutti leggermente diversi. L'interfaccia di ILead avrebbe proprietà come LocationOfLead, TimeOfLead ecc. – cbp

risposta

49

In questo caso, questo non costituisce un modello di dominio anemico. Un modello di dominio anemico è specifically about validating and transforming the objects. Quindi un esempio di ciò sarebbe se una funzione esterna avesse effettivamente cambiato lo stato dei Dipendenti o aggiornato i loro dettagli.

ciò che sta accadendo in questo caso è che si stanno prendendo tutti i dipendenti e facendo una selezione di uno di loro in base alle loro informazioni. Va bene avere un oggetto separato che esamina gli altri e prende decisioni riguardo a ciò che trova. NON è ok avere un oggetto che viene utilizzato per la transizione di un oggetto da uno stato all'altro.

Un esempio di un modello di dominio anemico nel tuo caso sarebbe quello di avere un metodo esterno

updateHours(Employee emp) // updates the working hours for the employee 

che prende un oggetto Employee e aggiorna le sue ore lavorate per settimana, facendo in modo che le bandiere sono sollevate se il le ore superano un certo limite. Il problema con questo è che se si dispone solo di oggetti Employee non si ha alcuna conoscenza di come modificare le loro ore entro i vincoli corretti.In questo caso, il modo per gestirlo sarebbe spostare il metodo updateHours nella classe Employee. Questo è il punto cruciale del modello anti-modello del dominio anemico.

+0

Ma cosa succede se il Dipendente è un Oggetto Persistente per il database. Perché dovrei mettere un metodo lì dentro? La stessa domanda è valida per DTO's in cui non si inseriscono i metodi. Dove poi metteresti il ​​metodo updateHours? – Pascal

+0

'updateHours' appartiene alla classe Employee. Si dovrebbe passare qualsiasi dato necessario per aggiornare le ore, ad esempio l'attività che è stata completata. Anche gli oggetti del collaboratore vanno bene, ma preferibilmente non ci sono servizi. – MauganRa

29

Penso che il tuo progetto vada bene qui. Come sapete, l'anti-pattern del modello di dominio anemico è una reazione contro la tendenza di evitare qualsiasi comportamento codificato negli oggetti del dominio. Al contrario, non significa che lo del comportamento di relativo a un oggetto dominio debba essere incapsulato da quell'oggetto.

Come regola generale, il comportamento che è intrinsecamente legato all'oggetto dominio e definito interamente in termini di tale istanza di un oggetto dominio può essere incluso nell'oggetto dominio. Altrimenti, per mantenere le responsabilità chiare, è meglio metterlo esternamente in un collaboratore/servizio come hai fatto tu.

+5

esattamente. Questo è veramente un modulo esterno (LeadQueueManager o qualsiasi altra cosa) con molta logica interna - questo non è assolutamente un modello di dominio anemico. Che cosa sa un dipendente sulla programmazione della coda di chiamata? Nulla;) – TomTom

13

È tutto nella tua testa: considera il servizio di rotazione come parte del modello di dominio e il problema si dissolve.

La rotazione deve mantenere le informazioni su molti dipendenti, quindi non appartiene né al lead né a un singolo oggetto dipendente. Lo fa per meritare di essere un oggetto dominio in sé.

Basta rinominare "RotationService" in qualcosa come "Organization.UserSupportDepartment" rende ovvio.

0

Se il modello di dominio contiene solo ruoli e cose, non attività come comportamento, è anemico. Tuttavia, sto parlando di un comportamento relativo a un modello non . Parlo della differenza tra di loro in un'altra risposta ... https://stackoverflow.com/a/31780937/116442

Dalla tua domanda, è rompere il mio prime regole analisi di modellazione due domini: -

  1. Comportamento modellata come attività (registrate) sono al centro di un modello di dominio. Aggiungili prima
  2. Attività del dominio del modello come classi, non metodi.

Vorrei aggiungere un'attività "Richiesta" al modello. Con esso il modello ha un comportamento e può combinare e lavorare come un gruppo di oggetti senza un controller esterno o uno script.

EnquiryHandlerModel

Problemi correlati