Para quienes hemos estado por muchos años escribiendo código y hemos vivido la evolución de las plataformas y la aparición de Frameworks, así como la sublimación de los patrones, siempre nos queda un lastre, cuando se debe implementar una solución.
Simplemente creemos que sabemos cómo hacerlo, basándonos en lo que sabíamos hacer…
Patrones
Actualmente podemos encontrar soluciones en forma de patrones, que se emplean en los diferentes Framework que hay en el mercado, algunos de estos patrones pueden ser implementados sin importar la plataforma que estemos empleando.
El reto más serio
Dentro del acceso a datos lo más sencillo de codificar es una transacción, pero si cometemos el error de crearlas a la vieja forma Procedural, será lo más complejo y repetitivo de codificar. Los programadores somos animales de costumbres, y pocos nos preocupamos por investigar y descubrir una mejor o más actualizada forma de hacer las cosas.
Las herramientas modernas como LINQ2SQL, Entity Framework, NHibernate, Castle nos ofrecen formas modernas de simplificar nuestro proceso de desarrollo, para que nuestras aplicaciones no presenten problemas en el futuro.
Tal vez deberíamos prestarles un poco mas de atención…no creen?
El patrón Domain Model
En la serie de artículos previos les ejemplifique una forma de implementar capas usando ASP.NET, con la ayuda del patrón Domain Model.
El ejemplo fue muy simple, con fines didácticos, y estoy seguro que una vez que lo vieron funcionar empezaron las dudas: cómo usar esto con entidades con relaciones complejas?
Ejemplo
Toda aplicación administrativa debe llevar registro de los pagos que realiza, así que vamos a implementar una solución para este requerimiento usando la arquitectura de capas que les presente previamente.
1.- Lo primero es crear una aplicación ASP.NET nueva. Tal y como lo hicimos en nuestro ejemplo de capas, empezaremos con la capa de datos.
2.- Para simplificar nuestro código, solo vamos a usar 4 tipos de movimiento: Registro, Depósito, Retiro y Transferencia, aun que en la vida real es más complejo. Para esto crearemos un Enum:
3.- Necesitaremos una entidad para los movimientos en la Cuenta bancaria:
4.- Nuestra última entidad será la cuenta bancara en sí:
Nota: como pueden observar he agregado la propiedad para la CuentaId, sin embargo esta no se inicializa en el constructor.
5.- Vamos a agregar una sobre carga del constructor:
6.- Nuestra clase debe controlar las acciones inmediatas que pueden llevarse a cabo con ella, como son:
Aumentar el Saldo
Disminuir el Saldo
Para aumentar el saldo no existe ninguna regla, sin embargo para poder disminuirlo (por ejemplo: retirar dinero, hacer algún pago, transferir) debe haber fondos suficientes, por lo tanto debemos implementar esta regla de negocio:
Si observan con cuidado podrán ver que en el método de disminuir el saldo, se uso una variable de clase _ultimoMensaje, la cual debe ser expuesta por medio de una propiedad de solo lectura.
7.- Dentro de esta capa se deben ofrecer los métodos conocidos como CRUD, aun que por simplificar el ejemplo solo implementaremos algunos de ellos, para lo cual vamos a crear una interface genérica para que sea implementada por cada repositorio:
Analicemos lo que debemos hacer.
Las entidades que ya hemos creado son clases que representan la información en memoria, en las bases de datos aplican otras reglas, por ejemplo, los movimientos deben estar relacionados de alguna forma con la cuenta o con el cliente; en nuestras entidades, tenemos los movimientos dentro de una colección que es una propiedad de la clase Cuenta.
En la base de datos necesitaremos dos tablas, una con la cuenta y otra con los movimientos, para relacionar ambas usaremos un campo que podría ser el número de cuenta o el identificador del cliente.
Si usáramos el cliente, podríamos tener problemas ya que, ese cliente podría tener otras cuentas y de esa forma se entre mezclarían los movimientos de ambas, así que la mejor opción es usar el identificador o el numero de la cuenta.
Estas son las tablas:
Y este es el diagrama:
Dilema existencial
Para el acceso a datos podemos usar diferentes tecnologías, como son ADO.NET, LINQ2SQL, Entity Framework; además si escogemos ADO, tenernos al menos dos formas de hacerlo, usando Stored Procedures o Escribiendo cadenas de texto con las instrucciones.
Si se atreven a buscar en internet sobre el tema, van a encontrar un número interminable de sitios donde acaloradamente discuten el tema, cada uno con su propio punto de vista.
Para que nuestro ejemplo sea más sencillo de entender voy a usar las cadenas de texto en vez de los Stored Procedures.
Un repositorio o varios
8.- En el ejemplo anterior donde les presente la arquitectura de capas, emplee LINQ2SQL para el acceso a datos, En este ejemplo vamos a usar ADO, Aun que al usar ADO será necesario usar una cadena de Conexión, y requiere que agreguemos una referencia a System.Configuration.
9.- Para nuestro ejemplo crearemos un repositorio para cada tabla; aun que bien podríamos crear un repositorio para la cuenta y este cargar los movimientos.
Hay quienes creen que estaríamos mezclando responsabilidades y quienes creen que es mejor hacer un repositorio por conjunto de entidades relacionadas.
Este es el Repositorio de Cuentas
10.- La implementación de los 4 métodos es esta:
Grabar
ObtenerTodas
BuscarPor
ConvertiraCuentas
11.- Este es el repositorio de Movimientos:
Grabar
ObtenerTodos
ConvertiraMovimientos
Observación: Los movimientos de la cuenta bancaria, no pueden ser modificados una vez que se han registrado, por reglas de contabilidad, solo podrán hacerse inserciones de registros nuevos.
Fin de la primera parte.
En el siguiente articulo vamos a continuar con este ejemplo, hasta el momento tenemos la parte del doman Model.
No hay comentarios:
Publicar un comentario