Comezaremos entonces la construcción de nuestra solución, basados en el diseño. ¿Y por dónde comenzar? Recordando las 3 reglas de TDD es simple: no podemos crear código productivo si no es para hacer pasar un test. Así que crearemos un test!
Empezando por la capa de negocio, crearemos un ProvinciaServiceImplTest. A esta clase le agregaremos el primer método de test:
buscarPorId_conIdExistente_retornaProvincia()
Nótese la nomenclatura que usamos para nombrar los metodos de test:
metodoBajoTest_escenario_retornoEsperado()
Comenzaremos comprobando así una llamada con un ID existente.
Así, en el test, deberemos invocar al método correspondiente del Service con un id existente, y realizar un assert para verificar que la provincia devuelta no sea null, y contenga el id buscado... y el test fallará porque no existe la clase! NetBeans (o Eclipse) nos ayudará a crear rápidamente la clase en cuestión (ambos IDE están pensados para ser usados con TDD, y sugerirán crear la falta que falte).
Crearemos el código en el Service de forma tal que si viene un id válido, devuelva una provincia con ese id, y como nombre la palabra "PROVINCIA" seguido del id.
Si el id no existe en la base, devolveremos null.
Seguiremos entonces creando los distintos casos de test para nuestro Service, recordando el contrato planteado.
Tendremos ahora creados el primer Service de la aplicación, con su primer test. Noten la importancia de testear el contrato del Service: futuros cambios a esta implementación estarán siendo controlados por el tests, y se encontrará rápidamente cualquier cambio en el comportamiento de nuestra implementación.
Mejor aún, un buen test sirve como documentación de uso de la clase.
Vamos a mejorar el Service para desacoplar el acceso a datos. Para esto, moveremos la "lógica dummy" de obtener la Provincia a una clase Repository.
El obstáculo más importante para sortear en esta etapa será invocar al Repository. Por ahora, lo construiremos directamente con el ya conocido "new". Nos quedará algo como:
ProvinciaRepository provinciaRepository = new ProvinciaRepositoryImpl();
No te preocupes si el código del Service parece ser sólo un "pasamos": en esta clase se ubica la lógica del negocio, y para esta simple interfaz no realizaremos ninguna otra acción.
Recordá crear el test correspondiente, con los diferentes casos de prueba.
Una vez terminado, tendremos entonces el Service y un Repository funcionales. El Repository es un dummy, pero el servicio de negocio es perfectamente funcional para ser usado. Es decir, un equipo de trabajo de una capa superior podría seguir trabajando con esta implementación hasta que la implementación real y final esté disponible.
Sin embargo, revisemos la implementación reciente de nuestro Service: tiene un problema interesante. Revisemos otra vez cómo estamos obteniendo la instancia de nuestro Repository:
ProvinciaRepository provinciaRepository = new ProvinciaRepositoryImpl();
Esa línea representa un problema serio para nuestro Service. En una arquitectura por capas, se supone que la capa invocante desconoce la implementación de la capa proveedora de servicios (de forma tal de ser independiente de la implementación). Sin embargo, aquí, nuestro Service conoce explícitamente la implementación del Repository de Provincia... de hecho, está haciendo un "new" de esa implementación!
Resumiendo, tenemos 1 problema importante: El Service conoce la implementación del Repository. No se puede cambiar facilmente la implementación en los Service.
¿Cómo se podría solucionar este problema? ¿Qué alternativas se te ocurren?
En las siguientes etapas del curso veremos solución a esta situación.
Con nuestro acceso a datos dummy terminado, podremos enfocarnos en construir nuestro primer Service Object.