2.12.2012

¿Qué es un micro ORM?

Muchos de nosotros hemos utilizado herramientas para mapear del mundo relacional al mundo orientado a objetos tales como el Entity Framework y NHibernate. Sin duda el uso de estas herramientas esta motivado por la facilidad que se logra para trabajar con el acceso a datos. Sin embargo, a muchos de nosotros siempre nos queda una espinita acerca del uso de estas herramientas ya que a ratos quedan sensaciones un poco diferentes respecto a la eficiencia de las mismas. En mi caso personal, hasta antes del modelo Code First del Entity Framework no estaba del todo convencido de utilizar este ORM –> aunque Microsoft le quiera llamar de otra forma –> en un proyecto enterprise, ya que considero que los POCOS son parte fundamental en cualquier arquitectura que vayamos a utilizar por su eficiencia y porque podemos utilizarlos como “transportador” de objetos neutral, ya que al final estos objetos se serializan en tipos SOAP estándar que nos van a permitir que sean consumidos de forma simple desde otras tecnologías tales como Java y PHP –> claro, siempre y cuando usemos tipos estándar.

Definición

Sin embargo, desde hace un tiempo atrás me di a la tarea de buscar algo intermedio, que me permitiera tener algunas de las abstracciones de lo ORM, pero que no me castigara en desempeño y me encontré el término Micro ORM. Un micro ORM es por lo general una librería pequeña que abstrae la funcionalidad principal de ADO.NET a través de un uso extensivo de los tipos dinámicos. Esto permite tener la misma funcionalidad que con ADO.NET tradicional, pero con mucho menos código; todo esto sin perder desempeño.

Ejemplo

Para ilustrar el concepto vamos a crear un ejemplo sencillo en el cual vamos a agregar, buscar y eliminar un registro desde una tabla en una base de datos SQL Server, este ejemplo lo vamos a desarrollar con Dapper.NET. La tabla que vamos a utilizar es la siguiente:

image

Como comenté anteriormente, los Micro ORM basan su funcionalidad en los POCOS, por lo tanto vamos a crear una librería que será nuestra capa de entidades –> siempre importante separar el estado del comportamiento. EL POCO para la tabla empresa es el siguiente:

image

Ahora procedemos con la capa de acceso a datos. En esta capa vamos a crear métodos estáticos para Agregar, Obtener y Eliminar empresas. Recuerden que en esta capa utilizamos métodos estáticos porque no existe razón alguna para mantener estado en estas invocaciones. Nótese que la hilera de conexión está en el archivo, algo que no es una recomendación pero un “abuso” propio para poder desarrollar el ejemplo de una manera más sencilla.

image

En el código anterior se puede ver que para hacer un select sobre una tabla utilizamos el método de extensión genérico Query, el cual recibe un arreglo de parámetros –> aunque esta sobre cargado para recibir más parámetros tales como transacciones –> y retorna un conjunto de datos tipificado en base al tipo enviado por parámetro en el método query –> en el generic.

image

Igualmente para ejecutar sentencias SQL que no retornan conjuntos de datos pero que llevan a cabo acciones sobre las tablas como el eliminar o el agregar vamos a utilizar el método Execute. Este método al igual que el Query, es un método de extensión que para este ejemplo, recibe una colección de parámetros los cuales por orden son asignados a los parametros definidos con @ dentro de la sentencia SQL; por ejemplo @Nombre –> Nombre = pEmpresa.Nombre.

image

Ahora procedemos a crear una capa de negocios que simplemente tiene las llamadas respectivas a la capa de acceso a datos.

image

Si queremos exponer estos métodos de lógica de negocio, vamos a tener que marcar como serializables los campos del POCO y el POCO utilizando el serializador de WCF.

image

Luego procedemos a crear el servicio. El primer paso es crear una librería WCF y definir el contrato del servicios

image

Después procedemos a implementar el contrato del servicio

image

Si queremos consumir el servicio desde cualquier interface, simplemente agregamos la referencia al servicio recién creado y a través del proxy se generarán los tipos necesarios para ejecutar nuestra aplicación.

Etiquetas de Technorati: ,,,

2.04.2012

La importancia de las pruebas unitarias –> Unit Tests

Los desarrolladores de software hablamos constantemente de como desarrollar software, como crear una arquitectura nueva para nuestra aplicación, que tipo de tecnología utilizaremos en el “front end”, el tipo de la base de datos a utilizar, etc. Sin embargo, es muy extraño encontrarse un desarrollador de software y más extraño aún encontrarse un arquitecto de software hablando de las pruebas que se le van a aplicar al software. En general probar software es un tema que siempre se ha dejado para el final en donde por falta de tiempo termina siendo una tarea hecha a la carrera y sin mucho empeño. Además, los desarrolladores tienden a pensar que esa tarea es de otros compañeros los cuales en el mejor de los casos son los “testers” y en el peor de los casos son los clientes del sistema.

Sin embargo, desde el punto de vista de la arquitectura de software, garantizar el funcionamiento correcto tanto desde el punto de vista estructural como funcional es una tarea tan importante como diseñar el software. Las pruebas funcionales están relacionadas con que el software desarrollado haga las cosas como el usuario espera y las pruebas estructurales son los unit test o pruebas unitarias. Las pruebas funcionales por lo general las llevan a cabo “testers” o usuarios finales que prueban y garantizan el buen funcionamiento del software. Por otro lado, las pruebas estructurales o pruebas unitarias buscan garantizar que el sistema no se quiebra cuando recibe cambios o nuevas características; estas pruebas la realizan los desarrolladores de software.

Los desarrolladores y las pruebas unitarias

Aunque para nosotros los desarrolladores las dos formas de hacer pruebas deberían ser igual de importantes, debemos estar más involucrados en las pruebas unitarias ya que es algo que debemos de programar nosotros mismos. Estas pruebas nos van a permitir validar aspectos tales como:

  • Si hago un cambio en el módulo A no voy a quebrar algo en el módulo B –> esto se da porque las pruebas unitarias se ejecutan cada vez que voy a subir el código como listo a mi repositorio de código, y si mi cambio en A va a quebrar B, las pruebas unitarias de B no serían exitosas.
  • Cuando trabajo en equipo evita que yo modifique con un error un código que ya esta probado y funcionando, ya que para que yo pueda subir el código al repositorio compartido tengo que ejecutar todas las pruebas unitarias –> tanto las mías como las de mis compañeros –> y si alguna falla no debo subir el código.
  • Las pruebas unitarias me permiten hace refactorización del código para permitir que mi código pueda ser más legible y más reutilizable, ya que cuando se desarrollan se observan oportunidades de mejora que no se distinguen cuando estamos desarrollando –> por ejemplo el uso amplio del polimorfismo.

Al hablar de pruebas unitarias e involucrar a los desarrolladores en este tema, surgen muchos mitos y resistencia de parte de estos últimos ya que por lo general a el desarrollador no le gusta probar. Los mitos más comunes son:

  • Las pruebas no las hago yo, le tocan al tester: FALSO. Desde todo punto de vista esta afirmación no tiene sentido ya que nadie más que le propio desarrollador conoce la estructura de su programa y nadie más que el sabe que se debe de probar para mantener al sistema estable y sin caídas inesperadas. Es tan importante que el desarrollador haga sus pruebas ya que con esto eliminamos en un porcentaje muy alto – depende del porcentaje de cobertura – la posibilidad de que nuestro sistema tenga caídas inesperadas no controladas. Además el construir estas pruebas le permite al desarrollador encontrar vacíos de diseño y oportunidades de mejora utilizando el refactoring –> algo de lo que hablaremos en otro post.
  • Si tengo que programar los unit test necesito más tiempo de desarrollo: FALSO. Esta más que demostrado que cuando uno utiliza pruebas unitarias reduce el tiempo de desarrollo de los proyectos, esto por cuanto se disminuye la mayoría del re trabajo en los proyectos de desarrollo. Por lo general el re trabajo es algo que no se toma en cuenta a la hora de hacer los planes de proyecto y al final es el rubro que se termina comiendo el cronograma y el presupuesto.
  • Los unit test son difíciles de programar y llevan mucho código: FALSO. Al contrario, las pruebas unitarias para que estén bien hechas deben de ser sencillas, rápidas, y fáciles de programar. De acuerdo a Roy Osherove en su libro “El arte de las pruebas unitarias” –> muy muy recomendado –> una prueba unitaria debe de ser escrita de forma tal que en 10 minutos tengamos algo para probar; y es totalmente cierto, en muy raras ocasiones toma más de 10 minutos el pensar y programar una prueba unitaria –> aunque al principio cuando se está aprendiendo puede que tome más.

En próximos post voy a enfocarme en cómo trabajar con pruebas unitarias en .NET y en Visual Studio.

Etiquetas de Technorati: