2011-01-26 20 views
5

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

risposta

2

tendo a fare quello che avete descritto verso la fine delle vostre preoccupazioni, e le cose gruppo strato di business in manager che abbiano un senso più logico da un punto di vista del business.

Utilizzando Contatti ad esempio, non avrei certamente un PhoneManager o EmailManager. "ContactsManager" è un gruppo più utile per me, che realizza praticamente la stessa cosa solo con un numero molto inferiore di manager da gestire. Dal punto di vista del business, i numeri di telefono e le e-mail sono solo piccoli pezzi di un contatto in ogni caso. Solo perché hanno le proprie tabelle ed entità non significa che hanno bisogno del proprio manager. Ciò non significa che non puoi riutilizzarli.Se hai bisogno di lavorare con indirizzi e-mail in più posti, ContactsManager può avere i metodi pertinenti.

Quello che tendiamo ad avere nel nostro ambiente è un livello di database/entità, quindi un livello aziendale che si trova sul server e gestisce le regole di business e la logica di business. Quel livello aziendale è esposto come servizio tramite WCF al client (o almeno, roba rilevante per i clienti).

Sembra che tu sappia già cosa vuoi fare, quindi suggerirei di fare un po 'di lavoro di prototipazione su di esso e vedere come funziona per voi. :)

+0

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

+0

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

+0

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

Problemi correlati