Seguramente lo que más confunde cuando alguien va a empezar con NHibernate es la gran cantidad de formas, colores y sabores que existen para integrarlo en la infraestructura y arquitectura de nuestra aplicación. A continuación solo una de ellas:
La clase SmtpClient está directamente referenciada por la clase HomeController y está última controla su creación, lo que tiene como consecuencia un fuerte acoplamiento entre estas dos clases.
La clase HomeController es consciente de la clase SmtClient y su funcionamiento, por lo tanto si alguna vez tenemos que realizar algún cambio sobre el envió de correo: como enviarlo por una cola de mensajes o incluso cambiar por una nueva librería, la clase HomeController se verá afectada.
Se dificulta la realización de pruebas sobre la clase HomeController.
La Solución
Si somos capaces de cambiar el control de la creación de la clase SmtpClient a una tercera entidad, podremos ver resuelto nuestro problema. Y esa solución es: Inversion of Control.
Inversion of Control
“Is an abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to traditional architecture of software” Wikipedia
Podemos implementar este patrón de 2 maneras distintas:
Dependency Inyeccion
La idea es tener un objeto en el “mundo exterior” que se encargue de proveer o inyectar la implementación adecuada (EmailSender) a la clase listener (HomeController)
Service Locator
La idea es tener una entidad “dentro de la clase” que conozca cómo obtener la implementación adecuada que esta clase podría necesitar.
Ahora veamos cómo estas cosas se utilizan en nuestra aplicación de ejemplo y adicionalmente veremos como podemos configurarla para que levante y ejecute.
Le llego el turno al Controlador y al Modelo ViewModel.
Para una mejor calidad también podemos verlo en HD.
Controlador.- Es el encargado de recibir y manejar las peticiones realizadas por los usuarios, y mostrar la vista adecuada.
ViewModel.- Es aquí donde viene el dilema. Comúnmente existe el problema en decidir cuál es la “M” dentro de nuestro modelo MVC. Es una entidad ?, un DTO ? , algo más ?.
Para algunos la “M” se refiere a una clase que ha sido diseñada para satisfacer las necesidades específicas de una vista en particular - “ViewModel”. Pero cuales son las razones que nos llevan a optar en utilizar una nueva clase únicamente para una vista, ya que esto supone un mayor esfuerzo (aparentemente):
A medida que las vistas se vuelven más complicadas es difícil mantener una sincronización entre las clases del dominio y las necesidades de la vista. Imaginemos una vista con un wizard que envía información sobre el paso al cual quiere ir el usuario, definitivamente no vamos a querer agregar esa información a una entidad del dominio ya que es únicamente de interés de la vista.
Muchas veces escribimos lógica innecesaria dentro de una vista, esto se puede representar en algo tan simple como: Html.Hidden(“id”,Model!=null?Model.ID:0) .Debido a que las vistas son difíciles de probar es recomendable mover esta lógica a otra clase que facilite esta tarea.
Al utilizar las entidades como “Model”, la vista tendrá conocimiento detallado de parte de dominio, lo cual para algunos puede significar que se daña de cierta manera la estructura y la arquitectura de la aplicación. Creo que esto no es más que otra decisión de diseño y esto lo podemos ver en varias aplicaciones antiguas, en especial aquellas que tienen a la base de datos relacional como centro de la aplicación y utilizan a las “entidades” como simples transmisores de datos. Después de vivir tantos años con estas aplicaciones podemos decir que las bases de datos relacionales no lo son todo en esta vida.
Los siguientes links tienen bastante información de los patrones que podemos utilizar para diseñar un ViewModel y las ventajas y desventajas de estos.
Para una mejor calidad también podemos verlo en HD.
A continuación tenemos una explicación de algunas de las cosas que hemos visto:
¿Cuál es la estructura de un test? Un Test tiene comúnmente la siguiente estructura:
Arrange: Creamos todas las precondiciones y entradas necesarias.
Act: Realizamos la acción en el objeto que estamos probando.
Assert: Verificamos que los resultados que esperamos se han producido.
¿Qué es lo primero que hacemos para agregar alguna funcionalidad? Sin duda alguna, lo primero es realizar el Test.
¿Cómo nombramos al Test? Tener un estándar para los nombres de los test resulta importante ya que nos brinda un descripción entendible por propios y extraños sobre lo que realiza el test. Recuerden los Test son Documentación. La convención de nombre Método_Escenario_ComportamientoEsperado nos ayuda bastante a lograr lo anteriormente mencionado.
¿Qué es lo que probamos primero? De todas las opciones que tenemos, probamos la más simple, pero que cree funcionalidad real o valor.
Se acuerdan del Kata de Números Primos, la primera prueba que realizamos fue verificar que el número 1 nos devolvía una lista vacía. No comenzamos probando que el número 9 nos devolviera 2 primos, ni tampoco que un número menor a uno 1 arrojara una excepción.
Pero, ¿porqué comenzamos con la más simple?… Imaginen que hubiéramos comenzado probando cuales son los números primos de 9, la cantidad de código escrito habría sido mucho mayor en relación a una prueba de los números primos de 1 y por lo tanto habría transcurrido mucho más tiempo en completarse el ciclo de TDD ( Red – Green – Refactor) y en obtener el feedback que nos aporta el mismo.
Espérate un momento!, en el video no todas las pruebas han comenzado con la opción más simple….Tomemos como ejemplo un método que suma 2 números (x, y), entonces según lo dicho anteriormente el camino más simple sería crear un test que verifique 0+0=0 y en el código de producción retornamos 0, nuestro siguiente test podría ser que 1+0=1 y en el código de producción retornamos x, por ultimo probar que 2+1=3 y en el código retornamos x+y. (este camino se parece bastante a nuestro Kata verdad). Pero creo que todos sabemos que la implementación a un método de suma es x+y. Entonces en estos casos donde la implementación es un poco obvia, no tenemos que pedir permiso a varios test para poder escribir el código de producción.
Algo parecido sucede en nuestro ejemplo, ya que de alguna manera se tiene una noción de como los servicios y repositorios interactúan juntos; de igual manera, tampoco nos preocupamos de temas más complejos como validaciones ni reglas de negocios. Por lo tanto nos sentimos con cierto nivel de confianza para dar pasos ligeramente más grandes pero de manera muy rápida.
Como sabemos que podemos optar por esto, una pista muy simple la encontramos al escribir el test, si en ese momento nos ponemos a pensar mucho en los detalles (nombre, entradas, salidas) es una señal de que la implementación no es tan simple como parece. Asimismo si nos sentimos seguros de dar pasos más grandes y observamos que los test se rompen muy seguido, quizás debamos hacer pasos más pequeños.
¿Qué es lo primero que escribimos en el test? De abajo para arriba, lo primero es el Assert. Esta es una práctica que he encontrado muy útil, ya que al realizar el test, nuestro cerebro se pone a pensar muchas cosas al mismo tiempo: ¿cómo nombramos los elementos?, ¿cómo lo voy a verificar?, ¿qué me sugieren hacer los otros test?, etc.
Entonces al realizar el Assert primero, aislamos uno de los problemas del resto: ¿cómo lo voy a verificar?, y en base a esto construimos el resto del test:
¿Cómo lo voy a verificar? Probando que se llame al método Agregar del Repositorio.
¿Dónde se llama al método Agregar? Desde el método Registrar de la clase AdministrarEmpresa.
¿Qué se requiere para llamar al método Registrar? Pasarle un objeto Empresa.
Está práctica junto con la anterior convención de nombres son una combinación muy buena. Asimismo te permite aprovechar bastante las herramientas que te otorga el entorno de desarrollo (Resharper Rulz!).
Volvamos por un momento al post anterior, ahí hemos observado el uso de tests para construir una clase que no depende internamente de ninguna otra.
Pero en la cruel realidad no todo es tan bonito y simple. Las clases dentro de nuestras aplicaciones tienen dependencias para poder funcionar (bases de datos, web services, etc)
Y esto se pone peor, ya que esas dependencias tienen también sus dependencias, y estas dependencias tienen más dependencias y así sucesivamente. Entonces crear un test puede parecer que se vuelve en una tarea complejísima y posiblemente imposible.
¿Cuál es la solución? Eliminar esas dependencias, pero sin esas dependencias nuestra clase no va a funcionar, reemplacemos esas dependencias por algo más simple; y como hacemos para que la clase utilice esas nuevas dependencias, hagamos que el test sea quien controle esas dependencias:
Aquí es donde entran los famosos Test Doubles (“Generic term for any kind of pretend object used in place of a real object for testing purposes” – Martin Fowler ).
En nuestro ejemplo hemos usado 2 Test Doubles (Other Simple Class), esto debido a que necesitamos probar nuestras clases RegistrarEmpresa (Class Under Test) y ReclutarPersonal (Class Under Test), y ambas clases dependen de un implementación de IEmpresaRepository(Other Class) para persistir la información.
Estos Test Doubles los podemos identificar fácilmente ya que son los objetos que tienen los nombres más raros de todo el ejemplo: mockEmpresaRepository y stubEmpresaRepository.
Pero, ¿porqué uno se llama mock y el otro stub ? Para darnos cuenta entre la diferencia que tienen, podríamos definirlos de manera muy simple:
Mock: Es el Test Double sobre el cuál realizamos un Assert. Ejm: mockEmpresaRepository.AssertWasCalled(x => x.Agregar(empresa)); Estamos verificamos que el método Agregar del IEmpresaRepository se ha llamado dentro del método que estamos probando.
Stub: Es el Test Double que nos permite poder realizar el test. Ejm: stubEmpresaRepository.Expect(x => x.Obtener(idEmpresa)).Return(empresa); Estamos indicando que cuando se llame el método Obtener del IEmpresaRepository nos devuelva una empresa cualquiera y así la prueba del método pueda continuar.
Bueno, hasta aquí hemos visto algunos temas del video, pero aún nos falta otros que dejaremos para un siguiente post. Espero les sirva de algo mi pequeño granito de arena. Y les prometo mejorar mi redacción.
Después de buscar un programa decente para grabar diferente a Camtasia (al final terminé con Camtasia), descubrir que mi tarjeta de video no graba sonidos, 4 intentos para grabar el KATA, varias decenas de intentos tratando de subir del video a Viddler con buena calidad, al fin esta listo xD.
This thought might not have occurred to you before; but it’s self-evidently true. Professional musicians practice. Professional dancers practice. Doctors practice. Soldiers practice. Indeed, any kind of professional craftsman or artisan must practice their adopted trade in order to execute it well when it counts.
Dave’s point was that professional programmers need to practice like any other professional. He set forth a number of simple exercises and problems that programmers could solve during their practice time. He also suggested that practice time needs to be scheduled and protected as part of the normal routine of a software developer.
El siguiente video es un KATA para encontrar los primos de un número cualquiera, sin más palabras que decir ahí les va el video:
Después de un largo tiempo dando soporte a un cliente, regreso un mañana a la empresa y recibo la sorpresa de que tenía que realizar una breve exposición por la tarde sobre Metodologías Ágiles. Al final terminé dándole un enfoque ligeramente diferente. Ahí les va los slides: