2010-11-15 13 views
28

que tengo dos opciones (que técnicamente son los mismos, según entiendo) para declarar una clase de excepción personalizada lanzado sólo de una clase particular com.XXX.Foo:excepciones como clases públicas frente a las clases internas estáticas públicas

  • como clase pública en el paquete: com.XXX.CustomException
  • como una clase interna estática pública: com.XXX.Foo.CustomException

¿Qué opción es mejor?

+1

La misma pregunta y las mismas opciones se podrían aplicar a cualquier clase. ¿Hay alguna característica de excepciones que los haga especialmente adecuados para la anidación, o simplemente pregunta [cuándo utilizar clases anidadas?] (Https://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html) – jaco0646

Respuesta

15

En caso de que la excepción sea muy específica para la clase Foo, no me importa mantenerla como una clase anidada public. Y siempre que parezca un momento para extraer eso, simplemente sáquelo.

En general, nunca he visto ninguna clase anidada definida para Exception. Tampoco sé si existe uno en la API de Java.

3

Preferiría la clase (no necesariamente pública) dentro del mismo paquete, ya que un paquete es un grupo lógico de clases que representa un modelo comercial, al que la excepción pertenece como parte técnica.

Un usuario verá inmediatamente que hay una excepción cuando mira el paquete y no necesita leer el archivo de la clase foo, que es mejor para el mantenimiento y la claridad/legibilidad/motivos comprensivos. ¡Es muy bueno definir excepciones personalizadas y decirle al usuario de la API al respecto!

Solo usaría una clase interna cuando claramente es algo privado de la clase en cuestión.

Sin embargo, estamos hablando de un problema principalmente convencional.

+0

¿Qué tal una clase que extienda 'javax.swing.RowFilter.Entry'? –

+2

Los paquetes se usan para agrupar modelos lógicos, por lo que en mi equipo acordamos la convención de que cada clase obtenga su propio archivo.Es muy probable que el modelo de negocio en el paquete esté muy ajustado, por lo que no veo ningún beneficio en el uso de una clase anidada. La clase anidada es más o menos expresiva: pertenezco inseparablemente a esta otra clase. Para algunas API, puede ser bueno diseñarlo de esa manera, por ejemplo, si todo el modelo dentro del paquete está acoplado un poco flojo. – Falcon

+2

PUEDE ampliar las clases internas estáticas. –

9

En mis más de 10 años de experiencia con Java, no recuerdo haber encontrado una API donde una clase de excepción pública se haya definido como una clase interna estática. No puedo darle una razón específica por la cual sería una mala idea hacer esto, pero sin duda haría que su código sea inusual.

¿Por qué crees que es necesario hacer esto, dado que (al parecer) nadie más lo hace? Espero que no solo lo hagas para ser "innovador".

(Por cierto, sé que algunas APIs Java conocidos utilizan las clases internas estáticas públicas e interfaces para otras cosas. Estoy hablando específicamente sobre el caso de clases de excepción aquí.)

+2

Echa un vistazo a esta clase de Apache Lucene 3.5: [org.apache.lucene.search.BooleanQuery.TooManyClauses] (http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/api/all/org/ apache/lucene/search/BooleanQuery.TooManyClauses.html) – yegor256

+1

OK. Un ejemplo en más de 10 años. (¿Pero por qué lo hicieron?) –

+2

Bueno, creo que tiene sentido cuando se lanza una excepción _sólo de una clase_. En ese caso, debe definirse como una clase interna estática. Cuando eliminas la clase, la excepción también se activa. En otras palabras, estarán "estrechamente unidos". – yegor256

-3

excepciones como las clases internas está una mala idea en general porque por naturaleza pueden elevarse a través de varios niveles, incluso en arquitecturas simples. La clase de excepción que se está generando debe referenciarse desde su clase contenedora, y si esa clase es desconocida para el classpath, algo malo probablemente ocurriría como una ClassCastException.

8

Definitivamente puedo pensar en situaciones en las que preferiría preferir la excepción de ser una clase interna estática que simplemente una clase en el mismo paquete.

Las razones para no hacerlo parecen ser:

  • El acoplamiento de la excepción a la clase que lo tira hace inadecuado para reutilizar en otros contextos
  • nadie más lo hace es

No creo que ninguno de esos argumentos sea convincente.

Para el primer punto, ¿por qué debería surgir esta hipotética oportunidad futura de reutilización en el mismo paquete? Este argumento lleva a la conclusión de que debemos colocar todas las clases de excepciones lo más alto posible en la jerarquía de paquetes para que cuando descubramos una oportunidad futura de reutilizar la misma excepción no tengamos que introducir una dependencia en donde se definió originalmente.

Pero incluso sin el punto "llevado a extremos", considere una excepción destinada a comunicar que la clase Foo recibió una entrada incorrecta. Si lo llamo Foo.InvalidInput, el nombre es corto y la asociación con Foo es imposible de perder. Si lo coloco fuera de la clase Foo y lo llamo FooInvalidCriteria, entonces no puedo reutilizarlo de la clase Bar de todos modos, sin cambiar su nombre (equivalente a cambiar su ubicación).

Pero lo peor es si lo dejo fuera Foo y mantengo su nombre general como InvalidInput. Luego, cuando más tarde me doy cuenta de que Bar también podría tener una entrada no válida y hacer que comience a arrojar esta excepción. Todo compila y funciona bien, solo que ahora todos los lugares que estaban capturando InvalidInput y asumiendo que estaban manejando errores de Foo ahora podrían estar manejando errores de Bar si Foo usa internamente el Bar de una manera que podría causar esta excepción. Esto podría causar la rotura del código fácilmente.

La realidad es que la adopción de una excepción que anteriormente se concibe como específicamente lo que indica una situación que se presente en una clase y re-usando como una clase de error general es un cambio en la interfaz , no sólo un cambio de implementación interna. Para hacerlo correctamente, en general, debe volver a visitar todos los sitios donde se captura la excepción y asegurarse de que siguen siendo correctos, por lo que el compilador le informará sobre todos los sitios de uso (porque debe cambiar el nombre y/o ruta de importación) es una buena cosa. Cualquier excepción que podría hacer crear una clase interna estática no es apropiada para su reutilización en otros contextos, sin importar si realmente la convierte en una clase interna o no.

Y en cuanto al segundo punto de punto ... "nadie más lo hace" nunca se sostiene en nada. O bien, realmente es lo incorrecto, por lo que habrá otras razones para no hacerlo, por lo que el argumento de "nadie más lo hace" es innecesario. O no lo es. Y no es que este ejemplo en particular sea terriblemente complicado y difícil de entender, por lo que ni siquiera el argumento "es inesperado para que la gente tenga problemas para seguirlo aunque sea una buena idea en teoría" es muy fuerte.

Cuestiones relacionadas