SfondoDove definire le interfacce per un repository in un'architettura a livelli?
Sto cercando di creare una semplice applicazione per capire davvero l'intero stack di DDD + TDD + ecc. Il mio obiettivo è quello di iniettare dinamicamente le classi del repository DAL in fase di runtime. Ciò mantiene i miei livelli di dominio e servizi applicativi testabili. Ho intenzione di utilizzare "DI dei poveri" per realizzare questo per ora ... così vorrei fare questo in una semplice applicazione console nei pressi di avvio:
// Poor man's DI, injecting DAL repository classes at runtime var productRepository = new SimpleOrder.Repository.ProductRespository(); var customerRepository = new SimpleOrder.Repository.CustomerRepository(); var orderRepository = new SimpleOrder.Repository.OrderRepository(); // Constructor injection into this class in the Application Services layer, // SimpleOrder.ApplicationFacade OrderEntry oe = new OrderEntry(customerRepository, orderRepository, productRepository);
per raggiungere questo obiettivo l'iniezione di dipendenza, ho creato tre repository interfacce:
-- ICustomerRepository -- IOrderRepository -- IProductRespository
Una tipica applicazione:
namespace SimpleOrder.Domain.Interfaces { public interface ICustomerRepository { Customer GetCustomerById(int customerId); void SaveCustomer(Customer customer); } }
** Si noti che SaveCustomer fa riferimento alla classe del modello cliente definita nella doma a livello. Questo è tipico degli altri repository.
Comunque non sono sicuro di quale progetto/strato di essi dovrebbero essere attuati in Ho 5 progetti in una soluzione:
SimpleOrder.ConsoleClient (presentazione) - voglio iniettare. l'attuazione specifica del dominio da qui l'applicazione
SimpleOrder.ApplicationFacade (servizi applicativi) - grosso di livello superiore, i metodi più grossolani a grana o rchestrating metodi di livello inferiore nel dominio
SimpleOrder.Contracts - classi DTO utilizzati per la comunicazione tra la presentazione e applicazione dei servizi
SimpleOrder.Domain (dominio/BLL) - dominio classi del modello Cliente, ordine, OrderItem, prodotto
SimpleOrder.Repository (dAL) - implementa il repo interfacce sitory
Qui sono le mie opzioni come la vedo io:
Opzione 1: definire le interfacce repository in SimpleOrder.Contracts ...
PRO: è qui che penso dovrebbero appartenere perché l'ho creato per condividere i contratti tra varie preoccupazioni/livelli. ex., DTOs sono definiti qui.
CON: tuttavia, le firme di metodo in ogni interfaccia fanno riferimento a classi di modelli di dominio.
Ciò significa che dovrei aggiungere un riferimento a SimpleOrder.Domain, ma quando ilSimpleOrder.I contratti sono referenziati in un altro progetto, sarà necessario trasportare SimpleOrder.Domain per il viaggio. Questo non mi sembra giusto.
Opzione 2: stesso scenario come sopra, ma ho anche definire le interfacce per ciascun dominio modello di classe nei SimpleOrder.Contracts in modo da poter rompere l'accoppiamento delle interfacce repository alle classi del modello attuale.
Esempio:
namespace SimpleOrder.Domain.Interfaces { public interface ICustomerRepository { ICustomer** GetCustomerById(int customerId); void SaveCustomer(ICustomer customer); } public interface ICustomer { int CustomerId { get; set; } string Name { get; set; } System.Collections.Generic.List Orders { get; } } }
IMPATTO: Ogni classe modello di dominio avrebbe dovuto implementare la sua interfaccia correlata. Ad esempio,
public class Customer : SimpleOrder.Domain.Interfaces.ICustomer { public Customer() { _orders = new List(); } public int CustomerId { get; set; } public string Name { get; set; } private List _orders; public virtual List Orders { get { return _orders; } } }
PRO: risolve il problema dell'opzione 1.
CON: esplode il numero di file (e la complessità percepita) nel progetto perché ogni classe di dominio ha ora un'interfaccia associata.
Opzione 3: Definire le Interfacce repository nel SimpleOrder.Domain
IMPATTO: Al fine di iniettare le classi repository di cemento nello strato servizi applicativi (progetto SimpleOrder.ApplicationFacade) dal SimpleOrder.ConsoleClient in fase di esecuzione , SimpleOder.ConsoleClient avrà anche bisogno di un riferimento a SimpleOrder.Domain.
PRO: Questo risolve anche l'opzione 1
CON: Stavo cercando di evitare di riferimento al livello di dominio dal livello di presentazione direttamente perché ora il livello di presentazione può conoscere troppo circa il livello di dominio. Quando sostituirò l'applicazione console in futuro con un'app WPF o ASP.NET MVC in futuro, rischio che le implementazioni secondarie e successive del livello di presentazione provino a chiamare metodi nel modello anziché nel livello Application Services. (Tuttavia lo considero nell'opzione 4.)
Opzione 4: Inserire le interfacce in SimpleOrder.Domain, quindi fare riferimento a SimpleOrder.Domain da SimpleOrder.ConsoleClient.
PRO: risolve tutti i problemi sopra indicati.
CON: Questo non mi sembra giusto, perché sarei fornire l'accesso dal livello di presentazione direttamente ai metodi di livello inferiore nello strato di dominio quando dovrei solo fornirò l'accesso al livello superiore grosso metodi in SimpleOrder.ApplicationFacade.
DOMANDA Ho provato ciascuno di questi, ma ho optato per l'opzione 4, tuttavia, che lascia l'amaro in bocca su di esso. C'è un'opzione migliore? Sono sulla strada giusta qui?
A un esame più attento ... le opzioni 3 e 4 sono fondamentalmente le stesse. Ops. Dovrei avere una lettura delle prove più da vicino. –