Resumen Clase 3

Resumen de la clase 3

El código de esta clase (que es continuación del de la clase-2) está disponible en:
* http://svn2.xp-dev.com/svn/utn-tadp-projects/obrassociales

Seguimos con el enunciado de las obras sociales, y nos centramos en el requerimiento del módulo de asignaciones externo.

Queremos agregar ese comportamiento código que teníamos la clase pasada, pero nos encontramos con una dificultad: si el módulo de asignaciones lo va a programar otro, ¿cómo pruebo código que no tengo?, ¿cómo me aseguro que mi sistema puede manejar las distintas situaciones?

Preparamos 2 tests en la Ambulancia, uno donde al asignarle un Paciente el módulo externo falla y otro donde funciona correctamente.
Necesitamos entonces tener algún objeto que se haga pasar por ese módulo, a esto llamamos Mock Object

Un objeto Mock cumple una interfaz o hereda de alguna clase y puede hacerse pasar por un objeto "de verdad", además de tener un comportamiento ya conocido (le elimina lo aleatorio al test, haciéndolo repetible).

Con esta idea, armamos 2 Mocks del módulo de asignaciones, una implementación que funciona y otra que tira RuntimeException.

Ahora si, armamos los 2 tests, pero, ¿qué estamos validando es esos tests?:
* No estamos validando el comportamiento del módulo externo, porque no nos pertenece. Aparte ni siquiera tenemos los módulos de en serio!.
* Si estamos validando el comportamiento de la Ambulancia ante las distintas situaciones presentadas por el comportamiento del módulo de asignaciones.

Implementamos en Ambulancia la llamada de notificación al módulo externo, usando un bloque try/catch para poder recuperar nuestro estado interno válido en caso de excepción:

    public void asignar(Paciente paciente) {
        Asignacion asignacion = new Asignacion(paciente);
        this.asignaciones.add(asignacion);
        try {
            this.moduloAsignaciones.notificarAsignacion(asignacion.getPaciente());
        } catch (Exception e) {
            //Debo recuperar mi estado valido antes de salir
            this.asignaciones.remove(asignacion);
            throw new NoSePudoAsignarException("Fallo el modulo externo", e);
        }
    }

Ahora tenemos el problema de que el código de Medico y Ambulancia es muy parecido, y comenzamos unos pequeños refactors dentro de una de las subclases de Unidad Medica, desglosando el método "asignar" en otros métodos mas cohesivos.

Esto nos lleva a notar que existen distintos tipos de métodos:
* A. Los que tienen efecto colateral
* B. Los que pueden tirar excepción
* C. Los que tienen efecto colateral y además pueden tener efecto de lado

La mejor forma de ordenarlos es B, C, A, porque de esta manera nos evita tener que recuperar nuestro estado válido al producirse una excepción en el módulo externo.

    public void asignar(Paciente paciente) {
        this.validarAntesDeAsignar(paciente);
        this.tryNotificarAsignacionAlModuloExterno(paciente);
        this.asignarmeElPacienteDePosta(paciente);
    }

Ojo, por cada cambio que hacemos, volvemos a correr todos los tests, para asegurarnos de que no cambiamos el comportamiento del sistema (por lo menos no el que está cubierto por los tests).

Por último, movemos los métodos que son iguales a la superclase UnidadMedica, y aquellos que son distintos los armamos como abstractos, para que cada subclase decida que hacer.
Esto es lo que se llama el patrón Template Method: un script de comportamiento general, con partes que no estan implementadas, y que son completadas por las subclases.

¿Dónde está el código que se ejecuta ante la llegada del mensaje asignar?

                      Medico         Ambulancia             UnidadMedica
Validar                 -            que esta disponible    default (nada)
Notificar al Modulo     -            -                      lo implementa
Guardar asignacion    lo implementa  lo implementa          abstracto

Clase 3

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License