2009-07-13 14 views
8

estoy trabajando en portar una base de código Java a Cocoa/Objective-C para su uso en el escritorio código de Mac OS X. El Java tiene mucha y mucha de métodos con excepciones comprobadas como:Al transferir código Java a ObjC, ¿cuál es la mejor forma de representar las excepciones marcadas?

double asNumber() throws FooException { 
    ... 
} 

Lo que es la mejor manera de representarlos en Objective-C? ¿Excepciones o errores de parámetros?

- (CGFloat)asNumber { 
    ... // possibly [FooException raise:format:]; 
} 

o

- (CGFloat)asNumberError:(NSError **)outError { 
    ... 
} 

tengo la sensación de que fuera errores son generalmente la mejor solución para Objective-C, pero como se puede ver ... una gran cantidad de métodos como el anterior se ser bastante incómodo. Y nuevamente, hay lotes de estos.

Por supuesto que tener en cuenta que, dado que estos son comprobado excepciones en Java, que tendrá que añadir ya sea @try bloques o if (*outError) {...} cheques siempre que se llaman estos métodos ( un montón de lugares).

Recuerdo que al entrar en @try bloques era una vez costoso en Objective-C, es barato en 64 bits o SL o algún otro env nuevo (no recuerdo exactamente). No estoy para nada preocupado por la compatibilidad con versiones anteriores, así que estoy definitivamente dispuesto a diseñar solo para el nuevo hotness.

+1

para quienes me sigan en casa, he decidido incluir errores y seguir los consejos NSScanner de Quinn. entonces este método particular sería algo como: '- (BOOL) getNumber: (CGFloat *) outNum error: (NSError **) outErr;' –

+0

@olliej señala correctamente que los bloques @try son de "costo cero" en el tiempo de ejecución Moderno (64 bits y iPhone), pero las excepciones aún cuestan cuando las lanzas. Además, puede usar 'double' en lugar de' CGFloat' si lo desea. Vaya con las mejores prácticas para el entorno en el que se encuentra y el código con el que se integra. –

Respuesta

16

Debe evitar definitivamente evite las excepciones para cosas como el análisis de números de cadenas. En Objective-C, las excepciones representan un error del programador, no un error de ingreso del usuario, o incluso archivos no disponibles. (Parte de la razón es que el manejo de excepciones siempre es más costoso y complejo que el manejo de errores más "convencional". Independientemente del hecho de que entering @try blocks is "zero cost" in 64-bit, todavía es lento cada vez que se produce una excepción.) Por supuesto, está autorizado a usar excepciones como quieras, pero no es la manera Cocoa, y te encontrarás en desacuerdo con otro código Objective-C. Las personas que usan su código se sentirán increíblemente molestas de que arroje excepciones en casos que simplemente deberían generar un error.

De Apple's own docs:

"In many environments, use of exceptions is fairly commonplace. For example, you might throw an exception to signal that a routine could not execute normally—such as when a file is missing or data could not be parsed correctly. Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors. Instead you should use the return value of a method or function to indicate that an error has occurred, and provide information about the problem in an error object."

vistazo a la forma integrada en las clases de cacao controlar los errores de este tipo. Por ejemplo, NSString tiene métodos como -floatValue que devuelven 0 si falla.Una mejor solución para su situación particular podría ser cómo lo hace NSScanner, como en -scanFloat: - acepte un puntero al campo donde se debe almacenar el resultado, y devuelva YES o NO según si el análisis fue exitoso.

Además de las convenciones y mejores prácticas de Obejctive-C, NSError es mucho más robusto y flexible que NSException, y permite que la persona que llama ignore el problema si lo desea. Sugiero leer a través del Error Handling Programming Guide For Cocoa. Nota: Si acepta un parámetro de NSError**, le sugiero que también diseñe para permitir que el cliente pase NULL si no desea recibir ningún error de información. Cada clase de Cocoa que conozco hace esto por errores, incluido NSString.

Aunque el código portado puede terminar pareciendo totalmente diferente del código de Java, reconozca que será utilizado por el código Objective-C, no por los mismos clientes del equivalente de Java. Definitivamente coinciden con las expresiones idiomáticas del idioma. El puerto no será una imagen espejo del código de Java, pero será mucho más correcto (para Objective-C) como resultado.

+0

Gracias por su opinión Quinn –

+1

Me gusta especialmente el consejo 'NSScanner' ... que ayudará a limpiar un poco estos nombres de métodos y hacerlos más naturales en ObjC. –

-1

Las excepciones son probablemente el mejor enfoque, ya que el Obj-C ABI (tiempo de ejecución) de 64 bits utiliza excepciones de costo cero, por lo que obtiene un código más limpio sin costo real. Por supuesto, en 32 bits las antiguas excepciones setjmp/longjmp todavía están en uso y no interactúan con C++, por lo que si ese es un objetivo, entonces usted tiene un problema.

+0

gracias por la gran respuesta oliver. y para el registro, no. No mezclaré esta base de código con C++ de ninguna manera. –

+0

-1 Disculpa, pero este es un consejo TERRIBLE para Objective-C. No todas las excepciones son de "costo cero", solo aquellas que en realidad nunca ocurren son (como bloqueos no vigilados cuando se programa con concurrencia). En el momento en que plantea ("tira") una excepción, paga el precio. Afirmar que da como resultado un "código más limpio" es una pista falsa, porque aunque el código de la biblioteca solo puede generar una excepción, cada cliente debe lidiar con la excepción usando @try y @catch. La "manera Cocoa" es usar errores y códigos de retorno para tales situaciones. Si desea que el puerto sea un buen código Objective-C, NO USE EXCEPCIONES. –

+1

@Quinn: las excepciones de "costo cero" son un término bien entendido que significa específicamente costo cero si no se emite la excepción.El Obj-C ABI de 32 bits usa setjmp y longjmp para implementar excepciones, lo que significa que @ try/@ catch tiene un costo elevado ya sea que se genere la excepción o no. – olliej

3

Tiene razón en que "los errores de salida son generalmente la mejor solución para ObjC". Muy rara vez encontrará una API en Cocoa que arroje una excepción (a menos que no haya satisfecho las condiciones previas para la API, pero en ese caso, el comportamiento no está definido por defecto).

Si espera que este código viva más allá de usted y sea adoptado por otros desarrolladores de Cocoa, le recomendaría usar los errores. Trabajo en código que fue creado por personas que no estaban familiarizadas con Cocoa y que usaban las excepciones liberalmente, y que son un verdadero problema para solucionarlo.

7

En Cocoa, se supone que las excepciones se usan para "errores de programación"; la filosofía es dejar que la aplicación los atrape, darle al usuario la opción de guardar lo que está haciendo y renunciar. Por un lado, no todos los marcos o rutas de código pueden ser 100% a prueba de excepciones, por lo que este puede ser el único curso de acción seguro. Para los errores que pueden anticiparse y recuperarse, debe usar NSError, generalmente a través de un parámetro de salida.

+1

Así que las excepciones de Objective-C son similares a cómo se define Error en Java: no se espera que las maneje, sino que las cierre correctamente. –

2

Soy un gran admirador del enfoque de error que utiliza Objective-C. TIENE que manejar excepciones, pero puede optar por ignorar los errores si lo desea. Todo encaja con la actitud de Objective-C de que "el programador sabe lo que está haciendo". También hace que Objective-C sea un lenguaje muy limpio, porque tu código no está lleno de bloques try-catch.

Dicho esto, es posible que desee considerar: ¿Hay situaciones en las que se ignoran las excepciones? Son las excepciones que lanzas realmente crítica? ¿Te encuentras escribiendo bloques de captura simples que limpian variables y continúan? Me inclinaría hacia los errores porque me gusta la sintaxis y Objective-C reserva excepciones solo para los errores más críticos.

+0

hrm, bueno en la fuente de Java, estas son * excepciones *, por lo que con el diseño actual, sí, deben ser manejadas de manera absoluta. en cuanto a si son realmente críticos, supongo que es una pregunta más difícil. Tal vez no sean realmente críticos, y el autor original solo estaba aprovechando una buena característica del lenguaje original (Java). Diré ... tengo el mayor respeto por el autor original. definitivamente conoce sus cosas (al menos en Java). –

+0

+1 Para estar seguro, no falta la falta de respeto al autor original. Cuando escribo en Java, sigo las convenciones (tanto del idioma como de mi equipo) y a menudo arrojo excepciones comprobadas en casos similares. Es más una consideración del contexto y lo que se adapta mejor a un contexto dado. También es bueno dejar que el cliente decida cuándo es realmente crítico manejar un error, en lugar de tener que defenderse siempre de una excepción NumberFormatException, NullPointerException, etc. –

2

Se parece a estas excepciones comprobadas mapas más limpios a errores. Las excepciones aún pueden ser utilizadas, pero deben reservarse para circunstancias excepcionales.

Cuestiones relacionadas