Tengo algunos métodos que realizan algunos cambios de datos en una base de datos (insertar, actualizar y eliminar). El ORM que estoy usando devuelve los valores int afectados por la fila para ese tipo de método. ¿Qué debo devolver para "mi método", para indicar el estado de éxito / fracaso de la operación?
Considere el código que está devolviendo un int
:
A.1
public int myLowerLevelMethod(int id) {
...
int affectedRows = myOrm.deleteById(id)
...
return affectedRows;
}
Entonces uso:
A.2
public void myOtherMethod() {
...
int affectedRows = myLowerLevelMethod(id)
if(affectedRows > 0) {
// Success
} else {
// Fail
}
}
Compare con el uso de boolean:
B.1
public boolean myLowerLevelMethod(int id) {
...
int affectedRows = myOrm.deleteById(id)
...
return affectedRows > 0;
}
Entonces uso:
B.2
public void myOtherMethod() {
...
boolean isSuccess = myLowerLevelMethod(id)
if(isSuccess) {
// Success
} else {
// Fail
}
}
¿Cuál (A o B) es mejor? O pros / contras de cada uno?
design
error-handling
methods
Hoang Tran
fuente
fuente
Respuestas:
Otra opción es devolver un objeto de resultado en lugar de tipos básicos. Por ejemplo:
Con esto, si por alguna razón necesita devolver el número de filas afectadas, simplemente puede agregar un método en OperationResult:
Este diseño permite que su sistema crezca e incluya una nueva funcionalidad (conocer las filas afectadas) sin modificar el código existente.
fuente
Es mejor devolver el número de filas afectadas porque proporciona información adicional sobre cómo se realizó la operación.
Ningún programador lo culpará porque él / ella tiene que escribir esto para verificar si tuvieron algunos cambios durante la operación:
pero te culparán cuando tengan que saber el número de filas afectadas y se darán cuenta de que no hay ningún método para obtener ese número.
Por cierto: si por "falla" te refieres a un error de consulta sintáctica (en cuyo caso el número de filas afectadas es obviamente 0), entonces lanzar la excepción sería más apropiado.
fuente
update t set category = 'default' where category IS NULL
incluso 0 filas afectadas sería un éxito, porque ahora no hay ningún elemento sin categoría, ¡incluso si no hay filas afectadas!No recomendaría ninguno de ellos. En cambio, no devuelva nada (nulo) en caso de éxito y arroje una excepción en caso de error.
Esto es exactamente por la misma razón por la que elijo declarar ciertos miembros de la clase privados. También hace que la función sea más fácil de usar. Más contexto operativo no siempre significa mejor, pero ciertamente significa más complejo. Cuanto menos prometas, más abstraes, más fácil es para el cliente entender y más libertad tienes para elegir cómo implementarlo.
La pregunta es cómo indicar éxito / error. En este caso, es suficiente para señalar el fallo lanzando una excepción y no devolver nada en caso de éxito. ¿Por qué debo proporcionar más de lo que el usuario necesita?
Pueden ocurrir fallas / situaciones excepcionales y luego tendrá que lidiar con ellas. Si usa try / catch para hacerlo o examina los códigos de retorno, es una cuestión de estilo / preferencia personal. Las ideas detrás de try / catch son: separar el flujo normal del flujo excepcional y dejar que las excepciones burbujeen hasta la capa donde se pueden manejar de la manera más adecuada. Entonces, como muchos ya han señalado, depende de si la falla es realmente excepcional o no.
fuente
"¿Es esto mejor que eso?" No es una pregunta útil cuando las dos alternativas no hacen lo mismo.
Si necesita conocer el recuento de filas afectadas, debe usar la versión A. Si no tiene que hacerlo, puede usar la versión B, pero cualquier ventaja que pueda obtener en términos de menos esfuerzo de escritura de código ya ha desaparecido desde te tomaste la molestia de publicar ambas versiones en un foro en línea!
Mi punto es: qué solución es mejor depende completamente de cuáles son sus requisitos específicos para esta aplicación, y usted conoce esas circunstancias mucho mejor que nosotros. No existe una opción para toda la industria, segura de usar, de mejores prácticas, que no sea despedido, que sea mejor en general ; tienes que pensarlo tú mismo. Y para una decisión tan fácil de revisar como esta, tampoco necesita pasar tanto tiempo pensando.
fuente
Dos de los principios más importantes en el diseño de software mantenible son KISS y YAGNI .
Casi nunca es una buena idea poner en lógica que no necesita de inmediato en este momento . Entre muchas otras personas, Jeff Atwood (cofundador de StackExchange) escribió sobre esto , y en mi experiencia él y otros defensores de estos conceptos tienen toda la razón.
Cualquier complejidad que agregue a un programa tiene un costo, pagado durante un largo período de tiempo. El programa se vuelve más difícil de leer, más complejo de cambiar y más fácil de introducir los errores. No caigas en la trampa de agregar cosas "por si acaso". Es una falsa sensación de seguridad.
Rara vez obtendrá un código correcto la primera vez. Los cambios son inevitables; agregar lógica especulativa para prepararse defensivamente para futuras contingencias desconocidas no lo protegerá de tener que refactorizar su código cuando el futuro sea diferente de lo que esperaba. El mantenimiento de la lógica innecesaria / contingente es más un problema de mantenimiento que la refactorización posterior para agregar la funcionalidad que falta.
Por lo tanto, dado que parece que todo lo que su programa necesita por ahora es saber si la operación tuvo éxito o no, su solución B propuesta (devolver un solo booleano) es el enfoque correcto. Siempre puede refactorizarlo más tarde si cambia el requisito. Esta solución es la más simple y tiene la menor complejidad (KISS) y hace justo lo que necesita y nada más (YAGNI).
fuente
Las filas completas o un estado de error
Considere devolver las filas completas, al menos como una opción de tiempo de ejecución. En las inserciones de DB puede que necesite inspeccionar los datos que se insertaron, ya que a menudo serán diferentes de lo que envió a la DB; Los ejemplos comunes incluyen ID de fila autogenerados (que la aplicación probablemente necesitará de inmediato), valores predeterminados determinados por DB y resultados de desencadenantes si los usa.
Por otro lado, si no necesita los datos devueltos, tampoco necesita el recuento de filas afectado, ya que no es útil para el resultado de 0. Si hay errores, debe devolver qué tipo de ocurrió un error, de una manera consistente con los principios de manejo de errores de su proyecto (excepciones, códigos numéricos de error, lo que sea); pero hay consultas válidas que afectarán correctamente 0 filas (es decir, "eliminar todos los pedidos caducados" si en realidad no hay ninguno).
fuente