Mostrando las entradas con la etiqueta bajo acoplamiento. Mostrar todas las entradas
Mostrando las entradas con la etiqueta bajo acoplamiento. Mostrar todas las entradas

Castle.Windsor Fluent Registration API

Ya vimos en un post anterior como podemos configurar el container de Castle con Fluent Registration API al igual que con xml. Ahora vamos a ver algunas cosas que podemos hacer con Fluent donde, quizás, empiece a sacar ventaja. Espero que el siguiente código sea suficientemente claro.

Creamos nuestro container

IWindsorContainer container = new WindsorContainer();
Registramos todos los DAOs
container.Register(
AllTypes.Of<IDAO>()
.From(typeof(InvoiceDAO).Assembly.GetTypes())
.WithService.FromInterface()
.Configure(cr => cr.LifeStyle.Singleton));

“registramos en el container” (línea 1), “todos los types que implementan IDAO” (línea 2), “del assembly al que pertenece InvoiceDAO (en este caso DMS.DAOs.NH” (línea 3), “como servicio tomamos la interface que implementan” (línea 4) y “los configuramos como singleton” (línea 5).

Registramos todos los models
container.Register(
AllTypes.Of<IModel>()
.From(typeof (InvoiceViewModel).Assembly.GetTypes())
.WithService.FromInterface());

creo que ya no hace falta “leerles” lo que dice el código. La diferencia con la registración de los DAOs es que en este caso registramos todas las implementaciones de IModel en el assembly DMS.Models.Impl.

Registramos todos los services
container.Register(
AllTypes.Of<IService>()
.From(typeof(InvoiceService).Assembly.GetTypes())
.WithService.FromInterface()
.Configure(cr => cr.Interceptors<SessionInterceptor>()));
Igual que antes, salvo por que les configuramos el interceptor (SessionInterceptor).

Conclusión

Por si no quedó claro, la ventaja que intento mostrarles es que no necesitamos declarar cada componente (existente o que existirá), sino que con esta configuración y si seguimos implementando las interfaces correspondientes (IDAO, IModel e IService) automáticamente se agregarán al container y se inyectaran las dependencias.

Arquitectura de bajo acoplamiento

Pensar una arquitectura de bajo acoplamiento
Para esto podemos dividir la aplicación en varios componentes, hacer referencia a los contratos (interfaces) y no a las implementaciones y asignarle sólo una responsabilidad a cada componente. Esto nos permitirá cambiar la implementación de dicho componente sin afectar los otros.

Por ejemplo DAOs tiene la responsabilidad del acceso a datos, no representa las entidades del dominio (que es responsabilidad de BEs), no tiene lógica de negocio (que es responsabilidad de Models), sólo se encarga de la persistencia de nuestro dominio (BEs). Quienes usan los DAOs, en realidad hacen referencia al contrato de DAOs, no a su implementación.

Arquitectura de nuestro ejemplo
Nuestro ejemplo se divide en tres grupos: Testing, Core e Implementations.
Grupo Testing:
Aquí están los test de nuestra aplicación, podríamos decir que estos tests son los que definen qué hace la aplicación en un modo verificable. Sólo podemos asegurar que funcione correctamente aquella característica que tenga su correspondiente test.
Los tests se dividen en tests unitarios (como Models.Testing) y tests de comportamiento o integración (como Integration.Testing).

Grupo Core:
- BEs: son las entidades que representan nuestro dominio.
- DTOs: son objetos serializables para la transferencia de información entre capas (físicas).
- DAOs: es el contrato que debe cumplir cualquier implementación de acceso a datos.
- Mappers: es el contrato que debe cumplir un conversor de BE a DTO y de DTO a BE.
- Models: es el contrato que debe cumplir cualquier implementación de lógica de negocios.
- Services: es el contrato que debe cumplir cualquier implementación de servicios de nuestra aplicación.

Como podemos ver, en el core de nuestra aplicación tenemos las definiciones de los componentes y no la lógica de los mismos (implementaciones). Aquí definimos los límites entre las piezas de nuestra aplicación y no cómo se va a resolver cada problemática en particular. Ésto nos permitirá cambiar las implementaciones cuando encontremos mejores alternativas.

Grupo Implementations:
Aquí encontramos las implementaciones de cada contrato, al momento de redactar este articulo hay una de cada uno. La implementación de Mappers está dividido en dos proyectos, uno implementa la transformación de DTO a BE (Mappers.AutoMapper) y otra de BE a DTO (Mappers.Reload).

Como podemos ver en el diagrama, las implementaciones sólo conocen los contratos de los otros componentes, esto es lo que nos va a garantizar que hay un bajo acoplamiento.