Para evitar todas las respuestas estándar que podría haber buscado en Google, proporcionaré un ejemplo que todos pueden atacar a voluntad.
C # y Java (y muchos otros) tienen muchos tipos de comportamiento de 'desbordamiento' que no me gusta en absoluto (por type.MaxValue + type.SmallestValue == type.MinValue
ejemplo, por ejemplo int.MaxValue + 1 == int.MinValue
).
Pero, visto mi naturaleza viciosa, agregaré un insulto a esta lesión al expandir este comportamiento a, digamos un DateTime
tipo Anulado . (Sé que DateTime
está sellado en .NET, pero por el bien de este ejemplo, estoy usando un pseudo lenguaje que es exactamente como C #, excepto por el hecho de que DateTime no está sellado).
El Add
método anulado :
/// <summary>
/// Increments this date with a timespan, but loops when
/// the maximum value for datetime is exceeded.
/// </summary>
/// <param name="ts">The timespan to (try to) add</param>
/// <returns>The Date, incremented with the given timespan.
/// If DateTime.MaxValue is exceeded, the sum wil 'overflow' and
/// continue from DateTime.MinValue.
/// </returns>
public DateTime override Add(TimeSpan ts)
{
try
{
return base.Add(ts);
}
catch (ArgumentOutOfRangeException nb)
{
// calculate how much the MaxValue is exceeded
// regular program flow
TimeSpan saldo = ts - (base.MaxValue - this);
return DateTime.MinValue.Add(saldo)
}
catch(Exception anyOther)
{
// 'real' exception handling.
}
}
Por supuesto, un if podría resolver esto con la misma facilidad, pero el hecho es que no puedo ver por qué no se pueden usar excepciones (lógicamente, puedo ver que cuando el rendimiento es un problema que en ciertos casos se deben evitar las excepciones) )
Creo que en muchos casos son más claros que las estructuras if y no rompen ningún contrato que el método esté haciendo.
En mi humilde opinión, la reacción de "Nunca los use para el flujo regular del programa" que todo el mundo parece tener no está tan mal construida como la fuerza de esa reacción puede justificar.
¿O me equivoco?
He leído otras publicaciones que tratan todo tipo de casos especiales, pero mi punto es que no hay nada de malo si ambos son:
- Claro
- Honra el contrato de tu método
Dispararme.
fuente
if
declaración mucho más breve y autodocumentada . Encontrarás esto muy difícil. En otras palabras: su premisa es defectuosa y, por lo tanto, las conclusiones que saca de ella son erróneas.Respuestas:
¿Alguna vez ha intentado depurar un programa que genera cinco excepciones por segundo en el curso normal de operación?
Yo tengo.
El programa era bastante complejo (era un servidor de cálculo distribuido), y una ligera modificación en un lado del programa podría romper fácilmente algo en un lugar totalmente diferente.
Ojalá pudiera haber lanzado el programa y esperar a que ocurran excepciones, pero hubo alrededor de 200 excepciones durante el inicio en el curso normal de las operaciones
Mi punto: si usa excepciones para situaciones normales, ¿cómo ubica situaciones inusuales (es decir, excepcionales )?
Por supuesto, hay otras razones importantes para no usar demasiado las excepciones, especialmente en cuanto al rendimiento.
fuente
Las excepciones son básicamente
goto
declaraciones no locales con todas las consecuencias de este último. El uso de excepciones para el control de flujo viola un principio de mínimo asombro , hace que los programas sean difíciles de leer (recuerde que los programas están escritos primero para programadores).Además, esto no es lo que los vendedores de compiladores esperan. Esperan que rara vez se produzcan excepciones, y generalmente dejan que el
throw
código sea bastante ineficiente. Lanzar excepciones es una de las operaciones más caras en .NET.Sin embargo, algunos lenguajes (especialmente Python) usan excepciones como construcciones de control de flujo. Por ejemplo, los iteradores generan una
StopIteration
excepción si no hay más elementos. Incluso las construcciones de lenguaje estándar (comofor
) se basan en esto.fuente
goto
, por supuesto, las excepciones interactúan correctamente con su pila de llamadas y con el alcance léxico, y no dejan la pila o los ámbitos en un lío.Mi regla de oro es:
El problema que veo con excepciones es desde un punto de vista puramente sintáctico (estoy bastante seguro de que la sobrecarga de rendimiento es mínima). No me gustan los try-blocks por todas partes.
Toma este ejemplo:
.. Otro ejemplo podría ser cuando necesita asignar algo a un controlador usando una fábrica, y esa fábrica podría lanzar una excepción:
Entonces, personalmente, creo que debería mantener excepciones para condiciones de error raras (sin memoria, etc.) y usar valores de retorno (clases de valor, estructuras o enumeraciones) para hacer su verificación de errores.
Espero haber entendido su pregunta correcta :)
fuente
Una primera reacción a muchas respuestas:
¡Por supuesto! Pero un if simplemente no está más claro todo el tiempo.
No debería ser sorprendente, por ejemplo: divide (1 / x) catch (divisionByZero) es más claro que ninguno para mí (en Conrad y otros). El hecho de que no se espere este tipo de programación es puramente convencional y, de hecho, sigue siendo relevante. Quizás en mi ejemplo un if sería más claro.
Pero DivisionByZero y FileNotFound para el caso son más claros que ifs.
Por supuesto, si es menos eficiente y necesita un trillón de tiempo por segundo, debería evitarlo, pero aún no he leído ninguna buena razón para evitar el diseño general.
En cuanto al principio de menor asombro: hay un peligro de razonamiento circular aquí: supongamos que toda una comunidad usa un mal diseño, ¡este diseño será esperado! Por lo tanto, el principio no puede ser un grial y debe considerarse cuidadosamente.
En muchas reacciones algo. como este brilla a través. Solo atraparlos, ¿no? Su método debe ser claro, estar bien documentado y cumplir con su contrato. No entiendo esa pregunta, debo admitir.
Depuración de todas las excepciones: lo mismo, eso solo se hace a veces porque el diseño para no usar excepciones es común. Mi pregunta fue: ¿por qué es común en primer lugar?
fuente
x
antes de llamar1/x
? 2) ¿Envuelve cada operación de división en un bloque try-catch para atraparDivideByZeroException
? 3) ¿De qué lógica pones el bloque catch para recuperarteDivideByZeroException
?openConfigFile();
puede ser seguido por un FileNotFound capturado con{ createDefaultConfigFile(); setFirstAppRun(); }
FileNotFound excepción manejado con gracia; sin bloqueo, hagamos que la experiencia del usuario final sea mejor, no peor. Usted puede decir "¿Pero qué pasa si esta no fue realmente la primera carrera y la obtienen siempre?" ¡Al menos la aplicación se ejecuta cada vez y no se bloquea cada inicio! En un 1 a 10 "esto es terrible": "primera ejecución" cada inicio = 3 o 4, bloquee cada inicio = 10.x
antes de llamar1/x
, porque generalmente está bien. El caso excepcional es el caso donde no está bien. No estamos hablando de hacer temblar la tierra aquí, pero por ejemplo, para un número entero básico dado al azarx
, solo 1 de cada 4294967296 no lograría hacer la división. Eso es excepcional y las excepciones son una buena manera de lidiar con eso. Sin embargo, podría usar excepciones para implementar el equivalente de unaswitch
declaración, pero sería bastante tonto.Antes de las excepciones, en C, había
setjmp
ylongjmp
podría usarse para lograr un desenrollado similar del marco de la pila.Luego se le dio un nombre a la misma construcción: "Excepción". Y la mayoría de las respuestas se basan en el significado de este nombre para discutir sobre su uso, alegando que las excepciones están destinadas a ser utilizadas en condiciones excepcionales. Esa nunca fue la intención en el original
longjmp
. Solo hubo situaciones en las que necesitaba romper el flujo de control en muchos marcos de pila.Las excepciones son un poco más generales, ya que también puedes usarlas dentro del mismo marco de pila. Esto plantea analogías con las
goto
que creo que están mal. Gotos son un par fuertemente acoplado (y también lo sonsetjmp
ylongjmp
). ¡Las excepciones siguen a una publicación / suscripción débilmente acoplada que es mucho más limpia! Por lo tanto, usarlos dentro del mismo marco de pila no es lo mismo que usargoto
s.La tercera fuente de confusión se relaciona con si son excepciones marcadas o no. Por supuesto, las excepciones no verificadas parecen particularmente horribles de usar para el flujo de control y quizás muchas otras cosas.
Sin embargo, las excepciones marcadas son excelentes para controlar el flujo, una vez que superas todos los problemas de Victoria y vives un poco.
Mi uso favorito es una secuencia de
throw new Success()
un largo fragmento de código que intenta una cosa tras otra hasta que encuentra lo que está buscando. Cada cosa, cada pieza de lógica, puede tener un anidamiento arbitrario, por lo quebreak
están fuera como cualquier tipo de prueba de condición. Elif-else
patrón es frágil. Si editoelse
o estropeo la sintaxis de alguna otra manera, entonces hay un error peludo.Utilizando
throw new Success()
linealiza el flujo de código. UtilizoSuccess
clasesdefinidas localmente, marcadas, por supuesto, de modo que si me olvido de atraparlo, el código no se compilará. Y no capto otro métodoSuccess
.A veces mi código busca una cosa tras otra y solo tiene éxito si todo está bien. En este caso tengo una linealización similar usando
throw new Failure()
.El uso de una función separada interfiere con el nivel natural de compartimentación. Entonces la
return
solución no es óptima. Prefiero tener una o dos páginas de código en un solo lugar por razones cognitivas. No creo en el código dividido ultra finamente.Lo que hacen los JVM o los compiladores es menos relevante para mí a menos que haya un punto de acceso. No puedo creer que haya una razón fundamental para que los compiladores no detecten Excepciones lanzadas y capturadas localmente y simplemente las traten como muy eficientes.
goto
a nivel de código de máquina.En cuanto a su uso a través de las funciones para el flujo de control, es decir, para casos comunes en lugar de excepcionales, no puedo ver cómo serían menos eficientes que las interrupciones múltiples, las pruebas de condición, los retornos para atravesar tres marcos de pila en lugar de simplemente restaurar El puntero de la pila.
Personalmente, no uso el patrón en los marcos de pila y puedo ver cómo requeriría sofisticación de diseño para hacerlo con elegancia. Pero usado con moderación, debería estar bien.
Por último, con respecto a los sorprendentes programadores vírgenes, no es una razón convincente. Si los presentas suavemente a la práctica, aprenderán a amarla. Recuerdo que C ++ solía sorprender y asustar a los programadores de C.
fuente
return
alternativa -pattern requeriría dos funciones para cada función. Una externa para preparar la respuesta del servlet u otras acciones similares, y una interna para hacer el cálculo. PD: Un profesor de inglés probablemente sugiera que use "sorprendente" en lugar de "sorprendente" en el último párrafo :-)La respuesta estándar es que las excepciones no son regulares y deben usarse en casos excepcionales.
Una razón, que es importante para mí, es que cuando leo un
try-catch
estructura de control en un software que mantengo o depuro, trato de averiguar por qué el codificador original utilizó un manejo de excepciones en lugar de unaif-else
estructura. Y espero encontrar una buena respuesta.Recuerda que escribes código no solo para la computadora sino también para otros codificadores. Hay una semántica asociada a un controlador de excepciones que no puede descartar solo porque a la máquina no le importa.
fuente
¿Qué tal el rendimiento? Durante la prueba de carga de una aplicación web .NET, superamos los 100 usuarios simulados por servidor web hasta que solucionamos una excepción común y ese número aumentó a 500 usuarios.
fuente
Josh Bloch trata este tema ampliamente en Java efectivo. Sus sugerencias son esclarecedoras y deberían aplicarse también a .Net (a excepción de los detalles).
En particular, las excepciones deben usarse para circunstancias excepcionales. Las razones de esto están relacionadas principalmente con la usabilidad. Para que un método dado sea utilizable al máximo, sus condiciones de entrada y salida deben estar limitadas al máximo.
Por ejemplo, el segundo método es más fácil de usar que el primero:
En cualquier caso, debe verificar para asegurarse de que la persona que llama está utilizando su API adecuadamente. Pero en el segundo caso, lo necesita (implícitamente). Las excepciones suaves aún se generarán si el usuario no leyó el javadoc, pero:
El punto a nivel del suelo es que las excepciones no deben deben usarse como códigos de retorno, en gran parte porque ha complicado no solo SU API, sino también la API de la persona que llama.
Hacer lo correcto tiene un costo, por supuesto. El costo es que todos deben comprender que necesitan leer y seguir la documentación. Esperemos que ese sea el caso de todos modos.
fuente
Creo que puede usar Excepciones para el control de flujo. Sin embargo, hay una otra cara de esta técnica. Crear excepciones es algo costoso, ya que tienen que crear un seguimiento de la pila. Por lo tanto, si desea utilizar Excepciones con más frecuencia que solo para señalar una situación excepcional, debe asegurarse de que la creación de trazas de la pila no influya negativamente en su rendimiento.
La mejor manera de reducir el costo de crear excepciones es anular el método fillInStackTrace () de esta manera:
Dicha excepción no tendrá trazados de pila completados.
fuente
Realmente no veo cómo está controlando el flujo del programa en el código que citó. Nunca verá otra excepción además de la excepción ArgumentOutOfRange. (Por lo tanto, su segunda cláusula catch nunca se verá afectada). Todo lo que está haciendo es usar un lanzamiento extremadamente costoso para imitar una declaración if.
Además, no está realizando las operaciones más siniestras en las que simplemente lanza una excepción simplemente para que sea atrapada en otro lugar para realizar el control de flujo. En realidad estás manejando un caso excepcional.
fuente
Estas son las mejores prácticas que describí en mi publicación de blog :
fuente
Debido a que el código es difícil de leer, es posible que tenga problemas para depurarlo, introducirá nuevos errores al corregir errores después de mucho tiempo, es más costoso en términos de recursos y tiempo, y le molesta si está depurando su código y el depurador se detiene al producirse cada excepción;)
fuente
Además de las razones indicadas, una razón para no usar excepciones para el control de flujo es que puede complicar en gran medida el proceso de depuración.
Por ejemplo, cuando estoy tratando de localizar un error en VS, normalmente activaré "romper todas las excepciones". Si está usando excepciones para el control de flujo, entonces voy a interrumpir el depurador de forma regular y tendré que seguir ignorando estas excepciones no excepcionales hasta que llegue al problema real. ¡Es probable que esto vuelva loco a alguien!
fuente
Supongamos que tiene un método que hace algunos cálculos. Hay muchos parámetros de entrada que tiene que validar y luego devolver un número mayor que 0.
El uso de valores de retorno para señalar el error de validación es simple: si el método devolvió un número menor que 0, se produjo un error. ¿Cómo saber entonces cuál parámetro no se validó?
Recuerdo de mis días C que muchas funciones devolvían códigos de error como este:
etc.
¿Es realmente menos legible que lanzar y atrapar una excepción?
fuente
Puede usar la garra de un martillo para girar un tornillo, al igual que puede usar excepciones para controlar el flujo. Eso no significa que sea el uso previsto de la función. La
if
declaración expresa condiciones, cuyo uso previsto es controlar el flujo.Si está utilizando una función de manera no intencional mientras elige no utilizar la función diseñada para ese propósito, habrá un costo asociado. En este caso, la claridad y el rendimiento no tienen valor agregado real. ¿Qué te hace usar excepciones usando la
if
declaración ampliamente aceptada ?Dicho de otra manera: solo porque puedas no significa que debas hacerlo .
fuente
if
el uso normal o el uso de las ejecuciones no está previsto porque no está destinado (argumento circular)?public class ExitHelper{ public static void cleanExit() { cleanup(); System.exit(1); } }
Entonces simplemente llame a eso en lugar de lanzar:ExitHelper.cleanExit();
Si su argumento fuera sólido, este sería el enfoque preferido y no habría excepciones. Básicamente estás diciendo "La única razón para las excepciones es bloquearse de una manera diferente".if
.Como otros han mencionado en numerosas ocasiones, el principio de menos asombro prohibirá que uses excepciones excesivamente para propósitos de control de flujo solamente. Por otro lado, ninguna regla es 100% correcta, y siempre hay casos en los que una excepción es "la herramienta correcta", muy parecida a
goto
sí misma, por cierto, que se envía en forma debreak
ycontinue
en lenguajes como Java, que A menudo son la forma perfecta de saltar de bucles muy anidados, que no siempre son evitables.La siguiente publicación de blog explica un caso de uso bastante complejo pero también bastante interesante para un no local
ControlFlowException
:Explica cómo dentro de jOOQ (una biblioteca de abstracción SQL para Java) , tales excepciones se usan ocasionalmente para abortar el proceso de representación SQL temprano cuando se cumple alguna condición "rara".
Ejemplos de tales condiciones son:
Se encuentran demasiados valores de enlace. Algunas bases de datos no admiten números arbitrarios de valores de enlace en sus instrucciones SQL (SQLite: 999, Ingres 10.1.0: 1024, Sybase ASE 15.5: 2000, SQL Server 2008: 2100). En esos casos, jOOQ aborta la fase de representación de SQL y vuelve a representar la instrucción SQL con valores de enlace en línea. Ejemplo:
Si extrajéramos explícitamente los valores de enlace de la consulta AST para contarlos cada vez, perderíamos valiosos ciclos de CPU para el 99.9% de las consultas que no sufren este problema.
Parte de la lógica está disponible solo indirectamente a través de una API que queremos ejecutar solo "parcialmente". El
UpdatableRecord.store()
método genera una declaraciónINSERT
oUPDATE
, dependiendo de losRecord
indicadores internos de. Desde el "exterior", no sabemos qué tipo de lógica está contenidastore()
(por ejemplo, bloqueo optimista, manejo de escucha de eventos, etc.), por lo que no queremos repetir esa lógica cuando almacenamos varios registros en una declaración por lotes, donde nos gustaría tenerstore()
solo generar la instrucción SQL, no ejecutarla realmente. Ejemplo:Si hubiéramos externalizado la
store()
lógica en una API "reutilizable" que se puede personalizar para que opcionalmente no ejecute el SQL, estaríamos buscando crear una API bastante difícil de mantener y difícilmente reutilizable.Conclusión
En esencia, nuestro uso de estos mensajes no locales
goto
es similar a lo que dijo [Mason Wheeler] [5] en su respuesta:Ambos usos de
ControlFlowExceptions
fueron bastante fáciles de implementar en comparación con sus alternativas, lo que nos permitió reutilizar una amplia gama de lógica sin refactorizarla de las partes internas relevantes.Pero la sensación de que esto sea una sorpresa para los futuros mantenedores permanece. El código se siente bastante delicado y, si bien fue la elección correcta en este caso, siempre preferimos no usar excepciones para el flujo de control local , donde es fácil evitar el uso de ramificaciones ordinarias
if - else
.fuente
Por lo general, no hay nada malo, per se, con el manejo de una excepción en un nivel bajo. Una excepción ES un mensaje válido que proporciona muchos detalles de por qué no se puede realizar una operación. Y si puedes manejarlo, deberías hacerlo.
En general, si sabe que hay una alta probabilidad de falla que puede verificar ... debe hacer la verificación ... es decir, si (obj! = Null) obj.method ()
En su caso, no estoy lo suficientemente familiarizado con la biblioteca C # para saber si la fecha y hora tiene una manera fácil de verificar si una marca de tiempo está fuera de los límites. Si lo hace, solo llame a if (.isvalid (ts)) de lo contrario, su código está básicamente bien.
Entonces, básicamente se reduce a cualquier forma que cree un código más limpio ... si la operación para protegerse contra una excepción esperada es más compleja que simplemente manejar la excepción; entonces tienes mi permiso para manejar la excepción en lugar de crear guardias complejos en todas partes
fuente
Si está utilizando controladores de excepciones para el flujo de control, está siendo demasiado general y vago. Como alguien más mencionó, usted sabe que algo sucedió si está manejando el procesamiento en el controlador, pero ¿qué es exactamente? Esencialmente, está utilizando la excepción para una instrucción else, si la está utilizando para el flujo de control.
Si no sabe qué estado podría ocurrir, puede usar un controlador de excepciones para estados inesperados, por ejemplo, cuando tiene que usar una biblioteca de terceros, o debe atrapar todo en la interfaz de usuario para mostrar un buen error mensaje y registrar la excepción.
Sin embargo, si sabe qué podría salir mal y no pone una declaración if o algo para verificarlo, entonces está siendo flojo. Permitir que el controlador de excepciones sea el complemento para todo lo que sabe que podría suceder es perezoso, y volverá a perseguirlo más tarde, porque intentará solucionar una situación en su controlador de excepciones en función de una suposición posiblemente falsa.
Si coloca la lógica en su controlador de excepciones para determinar qué sucedió exactamente, entonces sería bastante estúpido por no poner esa lógica dentro del bloque try.
Los manejadores de excepciones son el último recurso, porque cuando te quedas sin ideas / formas de evitar que algo salga mal, o las cosas están más allá de tu capacidad de control. Como, el servidor está caído y se agota el tiempo de espera y no puede evitar que se lance esa excepción.
Finalmente, hacer todas las comprobaciones por adelantado muestra lo que sabe o espera que ocurra y lo hace explícito. El código debe ser claro en su intención. ¿Qué preferirías leer?
fuente
Es posible que le interese echar un vistazo al sistema de condición de Common Lisp, que es una especie de generalización de excepciones bien hecha. Debido a que puede desenrollar la pila o no de forma controlada, también obtiene "reinicios", que son extremadamente útiles.
Esto no tiene mucho que ver con las mejores prácticas en otros idiomas, pero muestra lo que se puede hacer con un diseño pensado (aproximadamente) en la dirección en la que está pensando.
Por supuesto, todavía hay consideraciones de rendimiento si rebota arriba y abajo de la pila como un yoyo, pero es una idea mucho más general que el enfoque de tipo "oh mierda, vamos a rescatar" que la mayoría de los sistemas de excepción de captura / lanzamiento incorporan.
fuente
No creo que haya nada de malo en usar Excepciones para el control de flujo. Las excepciones son algo similares a las continuaciones y en lenguajes estáticamente tipados, las excepciones son más poderosas que las continuaciones, por lo tanto, si necesita continuaciones pero su idioma no las tiene, puede usar Excepciones para implementarlas.
Bueno, en realidad, si necesita continuaciones y su idioma no las tiene, eligió el idioma equivocado y debería usar uno diferente. Pero a veces no tiene otra opción: la programación web del lado del cliente es el mejor ejemplo, simplemente no hay forma de evitar JavaScript.
Un ejemplo: Microsoft Volta es un proyecto que permite escribir aplicaciones web en .NET directo, y permite que el marco se encargue de averiguar qué bits deben ejecutarse en cada lugar. Una consecuencia de esto es que Volta necesita poder compilar CIL a JavaScript, para que pueda ejecutar código en el cliente. Sin embargo, hay un problema: .NET tiene subprocesos múltiples, JavaScript no. Entonces, Volta implementa continuaciones en JavaScript usando Excepciones de JavaScript, luego implementa .NET Threads usando esas continuaciones. De esa manera, las aplicaciones Volta que usan hilos pueden compilarse para ejecutarse en un navegador no modificado, no se necesita Silverlight.
fuente
Una razón estética:
Un intento siempre viene con una trampa, mientras que un if no tiene que venir con otro
Con try / catch, se vuelve mucho más detallado.
Son 6 líneas de código demasiadas.
fuente
Pero no siempre sabrá lo que sucede en los métodos que llama. No sabrá exactamente dónde se produjo la excepción. Sin examinar el objeto de excepción con mayor detalle ...
fuente
Siento que no hay nada malo con tu ejemplo. Por el contrario, sería un pecado ignorar la excepción lanzada por la función llamada.
En la JVM, lanzar una excepción no es tan costoso, solo crea la excepción con la nueva xyzException (...), porque esta última implica una caminata de la pila. Entonces, si tiene algunas excepciones creadas de antemano, puede lanzarlas muchas veces sin costo. Por supuesto, de esta manera no puede pasar datos junto con la excepción, pero creo que es algo malo de todos modos.
fuente
Existen algunos mecanismos generales a través de los cuales un lenguaje podría permitir que un método salga sin devolver un valor y relajarse al siguiente bloque "catch":
Haga que el método examine el marco de la pila para determinar el sitio de la llamada y utilice los metadatos del sitio de la llamada para encontrar información sobre un
try
bloque dentro del método de llamada o la ubicación donde el método de llamada almacenó la dirección de su interlocutor; en la última situación, examine los metadatos de la persona que llama para determinar de la misma manera que la persona que llama inmediatamente, repitiendo hasta que encuentre untry
bloque o la pila esté vacía. Este enfoque agrega muy poca sobrecarga al caso de no excepción (excluye algunas optimizaciones) pero es costoso cuando ocurre una excepción.Haga que el método devuelva un indicador "oculto" que distingue un retorno normal de una excepción, y haga que la persona que llama verifique ese indicador y se bifurque a una rutina de "excepción" si está configurado. Esta rutina agrega 1-2 instrucciones al caso sin excepción, pero relativamente poca sobrecarga cuando ocurre una excepción.
Haga que la persona que llama coloque la información o código de manejo de excepciones en una dirección fija relativa a la dirección de retorno apilada. Por ejemplo, con el ARM, en lugar de usar la instrucción "subrutina BL", se podría usar la secuencia:
Para salir normalmente, la subrutina simplemente haría
bx lr
opop {pc}
; en caso de una salida anormal, la subrutina restaría 4 de LR antes de realizar la devolución o el usosub lr,#4,pc
(dependiendo de la variación de ARM, modo de ejecución, etc.) Este enfoque funcionará muy mal si la persona que llama no está diseñada para acomodarlo.Un lenguaje o marco que utiliza excepciones marcadas podría beneficiarse si se manejan con un mecanismo como el n. ° 2 o n. ° 3 anterior, mientras que las excepciones no marcadas se manejan con el n. ° 1. Aunque la implementación de excepciones marcadas en Java es bastante molesta, no sería un mal concepto si hubiera un medio por el cual un sitio de llamadas pudiera decir, esencialmente, "Este método se declara como arrojando XX, pero no lo espero siempre que lo haga; si lo hace, vuelva a considerarlo como una excepción "no verificada". En un marco donde las excepciones verificadas se manejan de tal manera, podrían ser un medio eficaz de control de flujo para cosas como métodos de análisis que en algunos contextos pueden tener alta probabilidad de falla, pero donde la falla debería devolver información fundamentalmente diferente al éxito. Sin embargo, no conozco ningún marco que utilice dicho patrón. En cambio, el patrón más común es utilizar el primer enfoque anterior (costo mínimo para el caso sin excepción, pero alto costo cuando se lanzan excepciones) para todas las excepciones.
fuente