¿Es una buena práctica implementar un manejo de excepciones inútil, en caso de que otra parte del código no esté codificada correctamente?
Ejemplo básico
Una simple, así que no pierdo a todos :).
Digamos que estoy escribiendo una aplicación que mostrará la información de una persona (nombre, dirección, etc.), los datos que se extraen de una base de datos. Digamos que soy yo quien codifica la parte de la interfaz de usuario, y alguien más está escribiendo el código de consulta DB.
Ahora imagine que las especificaciones de su aplicación dicen que si la información de la persona está incompleta (digamos que falta el nombre en la base de datos), la persona que codifica la consulta debe manejar esto devolviendo "NA" para el campo faltante.
¿Qué sucede si la consulta está mal codificada y no maneja este caso? ¿Qué sucede si el tipo que escribió la consulta maneja un resultado incompleto y cuando intenta mostrar la información, todo falla, porque su código no está preparado para mostrar cosas vacías?
Este ejemplo es muy básico. Creo que la mayoría de ustedes dirá "no es su problema, no son responsables de este bloqueo". Pero, sigue siendo tu parte del código la que falla.
Otro ejemplo
Digamos ahora que soy yo quien escribe la consulta. Las especificaciones no dicen lo mismo que arriba, pero el tipo que escribe la consulta "insertar" debe asegurarse de que todos los campos estén completos al agregar una persona a la base de datos para evitar insertar información incompleta. ¿Debo proteger mi consulta "select" para asegurarme de proporcionarle al chico de la interfaz de usuario información completa?
Las preguntas
¿Qué pasa si las especificaciones no dicen explícitamente "este tipo es el encargado de manejar esta situación"? ¿Qué sucede si una tercera persona implementa otra consulta (similar a la primera, pero en otra base de datos) y usa su código de UI para mostrarla, pero no maneja este caso en su código?
¿Debo hacer lo que sea necesario para evitar un posible bloqueo, incluso si no soy yo quien debe manejar el mal caso?
No estoy buscando una respuesta como "(s) él es el responsable del accidente", ya que no estoy resolviendo un conflicto aquí, me gustaría saber, si protejo mi código contra situaciones no es mi responsabilidad ¿manejar? Aquí, un simple "si está vacío hacer algo" sería suficiente.
En general, esta pregunta aborda el manejo de excepciones redundante. Lo pregunto porque cuando trabajo solo en un proyecto, puedo codificar 2-3 veces un manejo de excepciones similar en funciones sucesivas, "por si acaso", hice algo mal y dejé pasar un mal caso.
Respuestas:
De lo que estás hablando aquí es de límites de confianza . ¿Confía en el límite entre su aplicación y la base de datos? ¿La base de datos confía en que los datos de la aplicación siempre se validan previamente?
Esa es una decisión que debe tomarse en cada aplicación y no hay respuestas correctas o incorrectas. Tiendo a equivocarme al llamar a demasiados límites un límite de confianza, otros desarrolladores felizmente confiarán en API de terceros para hacer lo que esperas que hagan, todo el tiempo, siempre.
fuente
El principio de robustez "Sea conservador en lo que envía, sea liberal en lo que acepta" es lo que busca. Es un buen principio: EDITAR: siempre que su aplicación no oculte ningún error grave, pero estoy de acuerdo con @pdr en que siempre depende de la situación si debe aplicarlo o no.
fuente
Depende de lo que esté probando; pero supongamos que el alcance de su prueba es solo su propio código. En ese caso, debe probar:
Para hacer esto, no puede usar el componente de su colega: en su lugar, use burlas , es decir, reemplace el resto de la aplicación con módulos "falsos" que puede controlar desde el marco de prueba. Cómo exactamente hace esto depende de la interfaz de los módulos; puede ser suficiente simplemente llamar a los métodos de su módulo con argumentos codificados, y puede volverse tan complejo como escribir un marco completo que conecte las interfaces públicas de los otros módulos con el entorno de prueba.
Sin embargo, ese es solo el caso de prueba de unidad. También desea pruebas de integración, donde pruebe todos los módulos en concierto. Una vez más, desea probar tanto el caso feliz como los fracasos.
En su caso de "Ejemplo básico", para probar el código de la unidad, escriba una clase simulada que simule la capa de la base de datos. Sin embargo, su clase de prueba realmente no va a la base de datos: simplemente la precarga con las entradas esperadas y las salidas fijas. En pseudocódigo:
Y así es como probaría los campos faltantes que se informan correctamente :
Ahora las cosas se vuelven interesantes. ¿Qué pasa si la clase real de DB se porta mal? Por ejemplo, podría arrojar una excepción por razones poco claras. No sabemos si lo hace, pero queremos que nuestro propio código lo maneje con gracia. No hay problema, solo necesitamos hacer que nuestro MockDB arroje una excepción, por ejemplo, agregando un método como este:
Y luego nuestro caso de prueba se ve así:
Estas son sus pruebas unitarias. Para la prueba de integración, no utiliza la clase MockDB; en su lugar, encadena ambas clases reales juntas. Todavía necesitas accesorios; por ejemplo, debe inicializar la base de datos de prueba a un estado conocido antes de ejecutar la prueba.
Ahora, en lo que respecta a las responsabilidades: su código debe esperar que el resto de la base de código se implemente según la especificación, pero también debe estar preparado para manejar las cosas con gracia cuando el resto se arruina. No es responsable de probar otro código que no sea el suyo, pero es responsable de hacer que su código sea resistente al mal comportamiento del código en el otro extremo, y también es responsable de probar la resistencia de su código. Eso es lo que hace la tercera prueba anterior.
fuente
Hay 3 principios principales que trato de codificar:
SECO
BESO
YAGNI
El problema es que te arriesgas a escribir un código de validación que esté duplicado en otra parte. Si las reglas de validación cambian, éstas deberían actualizarse en varios lugares.
Por supuesto, en algún momento en el futuro, puede volver a formatear su base de datos (sucede) en cuyo caso podría pensar que sería ventajoso tener el código en más de un lugar. Pero ... estás codificando algo que puede no suceder.
Cualquier código adicional (incluso si nunca cambia) está sobrecargado, ya que deberá escribirse, leerse, almacenarse y probarse.
Todo lo anterior es cierto, sería negligente de su parte no hacer ninguna validación en absoluto. Para mostrar un nombre completo en la aplicación, necesitaría algunos datos básicos, incluso si no valida los datos en sí.
fuente
En palabras simples.
No existe tal cosa como "la base de datos" o "la aplicación" .
De nuevo:
fuente