Estoy tratando de reevaluar nuestra arquitectura n-layer y me gustaría obtener algunas sugerencias basadas en sus experiencias. Aquí está nuestro típico diseño .NET n-layer (a veces n-tier).n-layer business/service layer design
Project.UI
Project.Services
Project.Business
Project.Model
Project.DataAccess
DataAccess consiste típicamente en Entity Framework 4
y Repository
clases. Intento seguir el concepto Aggregate Root
para evitar tener un repositorio para la tabla, más fácil decirlo que hacerlo en mi experiencia. Tiendo a tener ~ 70% de coincidencia entre Repositorios y Tablas.
El modelo por lo general consiste de mis entidades Entity Framework 4
, he estado usando entidades EF de auto-seguimiento con éxito.
Los negocios son lo que más me cuesta. Normalmente tengo una clase Manager
por cada Repository
. Esta clase contendrá métodos como .Add() que realizará la validación comercial antes de reenviar a repository.Add().
Servicios, normalmente solo implementaré esto si, de hecho, estoy buscando crear una solución basada en el servicio web. Esta capa tendrá la tarea de ordenar las solicitudes/respuestas entre los DTO y las entidades. Y lo más importante es que proporciona la interfaz más coarse grained
. Por ejemplo, un TradingService.SubmitTrade(), que es realmente un facade
para una transacción comercial que podría incluir AccountManager.ValidateCash(), OrderManager.SubmitOrder(), etc.
Preocupaciones
Mi capa de negocio es muy entidad céntrico, realmente es solo el pegamento entre las entidades y el repositorio, con validación en el medio. He visto muchos diseños donde la capa de servicio es lo que mantiene una referencia a los repositorios (en esencia omitiendo la "capa de negocios"). En esencia, cumple el mismo propósito que mi capa de Negocios, realiza la validación, sin embargo, su "responsabilidad (y denominación) es una transacción comercial de mayor nivel y mayor tamaño. Utilizando el ejemplo anterior, TradingService.submitTrade() no delegará en ninguna clase de gerente de negocio, consultará los repositorios necesarios, realizará toda la validación, etc.
Me gusta mi diseño en el sentido de que puedo reutilizar un negocio método de capa en múltiples llamadas de servicio, sin embargo, odio el hecho de que para cada repositorio tengo un administrador de capas de negocios que coincida, creando toneladas de trabajo extra. Tal vez la solución es un tipo diferente de agrupación en el nivel Business Layer? Por ejemplo, combine clases de administrador individuales como PhoneManager y EmailManager (tenga en cuenta que tengo entidades de teléfono y entidades de correo electrónico) en una clase de administrador lógico como ContactsManager (tenga en cuenta que no tengo un tipo de entidad de "contacto"). Con métodos como ContactManager.GetPhones() y ContactManager.GetEmail(), etc.
Supongo que más que nada me pregunto cómo otros organizan y delegan responsabilidades, ya sea que tengan la capa de Servicio, la capa de Negocio, ambas, etc. Lo que contiene la referencia de contexto de ORM, etc.
¿Alguna vez recibió una llamada de servicio que abarca varias clases de gerente de negocios? En otras palabras, su interfaz de servicio podría ser aún más gruesa que los gerentes de negocios. Por ejemplo ContactService.CreateUser(), delegará (servirá como fachada) a UserManager.CreateUser() y ContactManager.AddEmail(), y ContactManager.AddPhone(), etc. También a pesar de que agrupamos la lógica relacionada con el correo electrónico y el teléfono en ContactsManager , no hay nada de malo en tener PhoneRepository y EmailRepository. Me parece que los repositorios no pueden ser "lógicos" como los gerentes. – e36M3
Raramente, pero ha sucedido. Prefiero mantener la mayor cantidad posible de la lógica en la capa de negocios, porque eso la hace disponible si alguien viene a mí más tarde y quiere una página web que haga algunas de las mismas cosas que hace el servicio (y sí, sucede). La página web puede llamar a la misma lógica de capa de negocios que el servicio, en lugar de llamar al servicio (están en el mismo servidor en mi caso). Entonces, lo que haría en un caso como este es tener un método de gerente de negocios que pueda usar otros gerentes de negocios. Trato de evitarlo, excepto cuando hay una ganancia real en la simplicidad, sin embargo. – Tridus
Sé lo que quiere decir, utilizo DI para crear mis Gerentes para proporcionarles repositorios necesarios a través del constructor. Un Gerente que crea otro Gerente requeriría que los Gerentes conozcan el contenedor DI. Sin embargo, sin esto, parece que a veces estoy duplicando la lógica copiando y pegando. Por ejemplo, DataEntryManager.EnterPrice() y FileManager.UploadPriceFile(). Usted puede imaginar que después de analizar el "archivo de precios" deberíamos insertar precios. Puedo duplicar parte de esa lógica o hacer que FileManager reutilice DataEntryManager. – e36M3