Sto provando a rivalutare la nostra architettura n-layer e mi piacerebbe ricevere alcuni suggerimenti in base alle vostre esperienze. Ecco il tipico design .NET n-layer (a volte n-tier).Progettazione livello di servizio/servizio a livello n.
Project.UI
Project.Services
Project.Business
Project.Model
Project.DataAccess
DataAccess consiste tipicamente di Entity Framework 4
e Repository
classi. Cerco di seguire il concetto Aggregate Root
per evitare di avere un repository per la tabella, più facile a dirsi che a farsi nella mia esperienza. Tendo ad avere il 70% di corrispondenza tra i repository e le tabelle.
Il modello di solito consiste delle mie entità Entity Framework 4
, ho utilizzato con successo le entità EF di auto-localizzazione.
Il business è quello che faccio più fatica. Di solito ho una classe Manager
per ogni Repository
. Questa classe conterrà metodi come .Add() che eseguiranno la convalida aziendale prima di inoltrare a repository.Add().
Servizi, in genere lo implementerò solo se in effetti sto cercando di creare una soluzione basata sul servizio web. Questo livello sarà incaricato di eseguire il marshalling di richieste/risposte tra DTO ed entità. E, soprattutto, fornire l'interfaccia più coarse grained
. Ad esempio, un TradingService.SubmitTrade(), che è davvero un facade
per una transazione commerciale che potrebbe includere AccountManager.ValidateCash(), OrderManager.SubmitOrder(), ecc
preoccupazioni
Il mio livello di business è molto entità centrico, in realtà è solo la colla tra le entità e il repository, con la convalida in mezzo. Ho visto molti progetti in cui il Service Layer è ciò che detiene un riferimento ai repository (in sostanza salta il "livello aziendale"). In sostanza serve allo stesso scopo del mio livello Business, lo fa la validazione, tuttavia la sua responsabilità (e denominazione) è un livello superiore, una transazione commerciale a grana più grossa. Utilizzando l'esempio sopra TradingService.submitTrade() non delegherà a nessuna classe di business manager, essa stessa interrogherà i repository necessari, eseguirà tutte le convalide ecc.
Mi piace il mio design nel senso che posso riutilizzare un'azienda metodo layer in più chiamate di servizio, tuttavia odio il fatto che per ogni repository disponga di un gestore del livello aziendale corrispondente, creando tonnellate di lavoro extra. Forse la soluzione è un diverso tipo di raggruppamento a livello di Business Layer? Ad esempio, combinare singole classi Manager come PhoneManager ed EmailManager (nota che ho entità Phone ed entità Email) in una classe Manager logica come ContactsManager (nota che non ho un tipo di entità "Contatto"). Con metodi come ContactManager.GetPhones() e ContactManager.GetEmail(), ecc.
Immagino più che altro mi chiedo come gli altri organizzano e delegano le responsabilità, se hanno il livello di servizio, il livello aziendale, entrambi, ecc. . ciò che contiene il riferimento ORM contesto, ecc
Hai mai ricevuto una chiamata di servizio che si estende su più classi di Business Manager? In altre parole, l'interfaccia di servizio potrebbe essere ancora più grossa dei responsabili aziendali. Ad esempio ContactService.CreateUser(), delegherà (funge da facciata) a UserManager.CreateUser() e ContactManager.AddEmail() e ContactManager.AddPhone(), ecc. Anche se abbiamo raggruppato la logica relativa all'e-mail e al telefono in ContactsManager , non c'è niente di sbagliato nell'avere PhoneRepository e EmailRepository. Mi sembra che i Repository non possano essere "logici" come i Manager. – e36M3
Raramente, ma è successo. Preferisco mantenere la maggior parte della logica nel livello aziendale che posso, perché ciò lo rende disponibile se qualcuno viene da me più tardi e vuole una pagina web che faccia alcune delle stesse cose che fa il servizio (e sì, succede). La pagina Web può richiamare la stessa logica del livello aziendale utilizzata dal servizio, piuttosto che chiamare il servizio (sono nel mio caso sullo stesso server). Quindi quello che farei in un caso come questo è avere un metodo di business manager che può usare da solo altri business manager. Cerco di evitarlo tranne quando c'è un vero guadagno in semplicità, però. – Tridus
So cosa intendi, utilizzo DI per creare i miei manager per fornire loro i repository richiesti tramite il costruttore. Un Manager che crea un altro Manager richiede che i Manager siano a conoscenza del contenitore DI. Tuttavia senza questo sembra che a volte sto duplicando la logica copiando e incollando. Ad esempio DataEntryManager.EnterPrice() e FileManager.UploadPriceFile(). Si può immaginare che dopo aver analizzato il suddetto "file di prezzo" dovremmo inserire i prezzi. Posso duplicare parte di quella logica o fare in modo che FileManager riutilizzi DataEntryManager. – e36M3