6

Quindi, ho esaminato alcuni post sul Modello di specifica qui e non ho ancora trovato una risposta a questo.In quale livello gli oggetti Modello di specifica dovrebbero essere "nuovi"?

La mia domanda è, in un'architettura a più livelli, in cui esattamente le specifiche devono essere "aggiornate"?

  1. ho potuto mettere nel mio livello di servizio (aka, livello di applicazione è talvolta chiamato ... in fondo, qualcosa di un aspx code-behind sarebbe parlare), ma mi sento come così facendo, I' lasciare che le regole aziendali fuoriescano dal dominio. Se si accede agli oggetti Dominio in qualche altro modo (oltre al Livello di servizio), gli oggetti Dominio non possono applicare le proprie regole aziendali.

  2. È possibile inserire la specifica nella classe del modello tramite iniezione del costruttore. Ma ancora, questo sembra "sbagliato". Mi sento come se l'unica cosa che dovrebbe essere iniettata nelle classi del Modello siano i "servizi", come il Caching, il Log, il tracking di bandiera sporca, ecc ... E se puoi evitarlo, usare Aspects invece di sporcare i costruttori del Modello classi con tonnellate di interfacce di servizio.

  3. Posso inserire la specifica tramite l'iniezione del metodo (a volte indicato come "Double Dispatch" ???), e in modo esplicito il metodo incapsula la specifica iniettata per applicare la sua regola aziendale.

  4. Creare una classe "Servizi di dominio", che richiederebbe una (e) specifica (e) tramite l'iniezione del costruttore e quindi consente al Livello servizio di utilizzare il servizio di dominio per coordinare l'oggetto Dominio. Questo mi sembra OK, poiché la regola applicata dalla Specifica è ancora nel "Dominio" e la classe del Servizio di dominio può essere chiamata molto simile all'oggetto Dominio che sta coordinando. La cosa qui è che mi sento come se stessi scrivendo un sacco di classi e codice, solo per "correttamente" implementare il modello di specifica.

Aggiungete a ciò che la Specifica in questione richiede un Deposito per determinare se è "soddisfatto" o meno.

Ciò potrebbe causare problemi di prestazioni, esp. se uso il constructor injection b/c, il codice che consuma potrebbe chiamare una proprietà che forse avvolge la specifica e che, a sua volta, sta chiamando il database.

Quindi qualsiasi idea/pensiero/link ad articoli?

Dove è il posto migliore per il rinnovo e l'uso delle specifiche?

risposta

6

Risposta breve:

Si utilizza Specifiche principalmente nel vostro livello di servizio, quindi non c'è.

Risposta lunga: Prima di tutto, ci sono due domande qui:

Dove dovrebbero le caratteristiche del tuo vivere, e dove dovrebbero essere new'd up?

Proprio come le interfacce del repository, le vostre specifiche dovrebbero vivere nel livello del dominio, in quanto sono, dopo tutto, specifiche del dominio. C'è uno question on SO che discute questo sulle interfacce del repository.

Dove dovrebbero essere nuovi? Beh, io uso LinqSpecs sul mio repository e soprattutto mai avere tre metodi sul mio repository:

public interface ILinqSpecsRepository<T> 
{ 
    IEnumerable<T> FindAll(Specification<T> specification); 
    IEnumerable<T> FindAll<TRelated>(Specification<T> specification, Expression<Func<T, TRelated>> fetchExpression); 
    T FindOne(Specification<T> specification); 
} 

Il resto delle mie domande sono costruiti nel mio livello di servizio. Ciò evita che i repository diventino gonfiati con metodi come GetUserByEmail, GetUserById, GetUserByStatus, ecc. Nel mio servizio, ho aggiornato le mie specifiche e le ho passate ai metodi FindAll o FindOne del mio repository. Per esempio:

public User GetUserByEmail(string email) 
{ 
    var withEmail = new UserByEmail(email); // the specification 
    return userRepository.FindOne(withEmail); 
} 

e qui è la specifica:

public class UserByEmail : Specification<User> 
{ 
    private readonly string email; 

    public UserByEmail(string email) 
    { 
     this.email = email; 
    } 

    #region Overrides of Specification<User> 

    public override Expression<Func<User, bool>> IsSatisfiedBy() 
    { 
     return x => x.Email == email; 
    } 

    #endregion 
} 

Quindi, per rispondere alla tua domanda, le specifiche sono new'd nel livello di servizio (nel mio libro).

mi sento come l'unica cosa che dovrebbe essere iniettato in classi del modello sono "servizi"

IMO non si dovrebbe essere l'iniezione di qualsiasi cosa in entità di dominio.

Aggiungere a questo, che la specifica in questione richiede un repository per determinare se è "soddisfatto" o meno.

Questo è un code smell. Vorrei rivedere il tuo codice lì. Una specifica non dovrebbe assolutamente richiedere un repository.

+0

Non troppo sicuro se l'iniezione di un deposito in una specifica è un odore di codice o no. Controlla questa discussione su StackOverflow: [link] (http://stackoverflow.com/questions/5818898/where-to-put-global-rules-validation-in-ddd). Le somiglianze tra una specifica e un servizio di dominio possono essere molto simili, specialmente se la regola che si sta tentando di applicare/dimostrare si basa sull'ottenimento di informazioni tramite un repository prima. –

+2

Si passa una specifica a un repository, ad es. tramite FindOne (specifica) o FindAll (specifica).Se si inserisce un repository in una specifica, si rischia di creare un riferimento circolare che potrebbe causare problemi. – autonomatt

5

Una specifica è una verifica dell'implementazione di una regola aziendale. Deve esistere nel livello dominio completo.

È difficile fornire informazioni specifiche su come lo si fa in quanto ogni base di codice è diverso, ma qualsiasi logica aziendale, a mio parere, deve essere nel livello dominio e da nessun'altra parte. Questa logica di business deve essere completamente testabile e accoppiata liberamente da UI, database, servizi esterni e altre dipendenze non di dominio. Quindi escluderei sicuramente 1, 2 e 3 sopra.

4 è un'opzione, almeno la specifica vivrà nel livello del dominio. Tuttavia, il rinnovo delle specifiche dipende davvero di nuovo dall'implementazione. Di solito usiamo l'iniezione di dipendenza, quindi la nuova creazione di praticamente tutti i nostri oggetti viene eseguita tramite un contenitore di IOC e il corrispondente codice di bootstrap (ad esempio, di solito leghiamo l'applicazione in modo fluido). Tuttavia, non collegheremo mai direttamente la logica di business direttamente ad es. Classi di modelli dell'interfaccia utente e simili. Di solito abbiamo contorni/confini tra cose come l'interfaccia utente e il dominio.Di solito definiamo i contratti di servizio del dominio, che possono essere utilizzati da strati esterni come l'interfaccia utente, ecc.

Infine, la mia risposta è che si presuma che il sistema su cui si sta lavorando sia almeno in qualche modo complesso. Se si tratta di un sistema molto semplice, il design basato sul dominio come concetto è probabilmente troppo esagerato. Tuttavia alcuni concetti come testabilità, leggibilità, SoC ecc. Dovrebbero essere rispettati a prescindere dal codice base secondo me.