Fail vs. raise en Ruby: ¿Deberíamos realmente creer la guía de estilo?


Ruby ofrece dos posibilidades para causar una excepción mediante programación: raise y fail, siendo ambos métodos Kernel. Según los documentos, son absolutamente equivalentes.

Por un hábito, usé solo raise hasta ahora. Ahora he encontrado varias recomendaciones (por ejemplo aquí), para usar raise para las excepciones a ser capturados, y fail para errores graves que no están destinados a ser manejados.

Pero, ¿realmente tiene sentido? Cuando estás escribiendo una clase o módulo, y causar un problema en el fondo, que señalas por fail, tus colegas de programación que están revisando el código, podrían felizmente entender tus intenciones, pero la persona que está usando mi código probablemente no mirará mi código y no tiene forma de saber, si la excepción fue causada por un raise o por fail. Por lo tanto, mi uso cuidadoso de raise o fail no puede tener ninguna influencia en su decisión, ya sea que ella deba o no manejarlo.

¿Podría alguien ver defectos en mi ¿discusiones? ¿O hay otros criterios, que podría querer usar fail en lugar de raise?

Author: ndn, 2015-08-11

2 answers

Use ' raise 'para detectar excepciones y' fail ' para errores graves que no están destinados a ser manejados

Esto no es lo que la guía oficial de estilo o el enlace que proporcionaste dicen sobre el asunto.

Lo que se quiere decir aquí es usar raise solo en rescue bloques. Aka use fail cuando quieres decir algo es fallando y use raise cuando repensando una excepción.

En cuanto a la parte "¿importa?" - no es una de el más hardcore siguió estrictamente las reglas, pero usted podría hacer el mismo argumento para cualquier convención. Usted debe seguir en ese orden:

  1. Tu guía de estilo de proyecto
  2. Su guía de estilo de empresa
  3. La guía de estilo de la comunidad

Idealmente, los tres deberían ser los mismos.


Actualización : A partir de este PR (diciembre de 2015), la convención debe usar siempre raise.

 38
Author: ndn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-19 08:42:32

Una vez tuve una conversación con Jim Weirich sobre esta misma cosa, desde entonces siempre he utilizado fail cuando mi método está fallando explícitamente por alguna razón y raise para volver a lanzar excepciones.

Aquí hay un post con un mensaje de Jim (casi literal a lo que me dijo en persona): http://www.virtuouscode.com/2014/05/21/jim-weirich-on-exceptions /

Aquí está el texto relevante del post, una cita atribuida a Jim: {[18]]}

Aquí está mi filosofía básica (y otros pensamientos aleatorios) sobre las excepciones.

Cuando llamas a un método, tienes ciertas expectativas sobre lo que el método logrará. Formalmente, estas expectativas se llaman post-condiciones. Un método debe lanzar una excepción cuando no cumple con sus postcondiciones.

Para utilizar eficazmente esta estrategia, implica que debe tener una pequeña comprensión del Diseño por Contrato y el significado de pre y post - condiciones. Creo que es una buena lo que hay que saber de todos modos.

He aquí algunos ejemplos concretos. El modelo Rails save método:

model.save!
-- post-condition: The model object is saved.

Si el modelo no se guarda por alguna razón, entonces se debe generar una excepción porque no se cumple la condición post.

model.save
-- post-condition: (the model is saved && result == true) ||
                   (the model is not saved && result == false)

Si save no guarda realmente, entonces el resultado devuelto será false , pero la condición post sigue cumpliéndose, por lo tanto no hay excepción.

Me parece interesante que el método save! tiene una post-condición mucho más simple.

Sobre el tema del rescate de excepciones, creo que una aplicación debe tener puntos estratégicos donde se rescatan las excepciones. Hay poca necesidad de rescate/vuelve a generar la mayor parte. La única vez que querrías rescatar y repensar es cuando tienes un trabajo a medio camino hecho y quieres deshacer algo para evitar un estado parcialmente completo. Sus puntos de rescate estratégicos deben elegirse cuidadosamente para que el programa pueda continuar con otros trabajos incluso si la operación actual falló. Los programas de procesamiento de transacciones deben pasar a la siguiente transacción. Una aplicación Rails debe recuperarse y estar lista para manejar la siguiente solicitud http.

La mayoría de los manejadores de excepciones deben ser genéricos. Dado que las excepciones indican una falla de algún tipo, entonces el controlador solo necesita tomar una decisión sobre qué hacer en caso de falla. Las operaciones de recuperación detalladas para excepciones muy específicas generalmente se desaconsejan a menos que el controlador esté muy cerca (en cuanto al gráfico de llamadas) del punto de salvedad.

Las excepciones no deben utilizarse para el control de flujo, utilice throw/catch para ello. Esto reserva excepciones para condiciones de fallo verdadero.

(Aparte, porque uso excepciones para indicar errores, casi siempre uso la palabra clave fail en lugar de la palabra clave raise en Ruby. Fail y raise son sinónimos, por lo que no hay diferencia, excepto que fail comunica más claramente que el método ha fallado. La única vez que uso raise es cuando estoy atrapando una excepción y volver a plantearlo, porque aquí estoy no fallando, sino planteando explícita y deliberadamente una excepción. Este es un tema estilístico que sigo, pero dudo que muchas otras personas lo hagan).

Ahí lo tienen, un volcado de memoria bastante laberíntico sobre mis pensamientos sobre las excepciones.

Sé que hay muchas guías de estilo que no están de acuerdo (la guía de estilo utilizada por RoboCop, por ejemplo). No me importa. Jim me convenció.

 2
Author: Karl Wilbur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-17 10:08:50