2011-03-23 16 views
22

¿Por qué no podemos usar assertion para métodos públicos?¿Por qué no podemos usar assertion para métodos públicos?

He leído en alguna parte

"una aserción es inadecuado en métodos públicos debido a que el método garantiza que siempre va a hacer cumplir las cheques de argumento. Un método público debe comprobar sus argumentos sean o no Las aserciones están habilitadas. Además, la construcción de aserción no arroja una excepción del tipo especificado. Es puede lanzar solo un AssertionError ".

Entonces, ¿no es aplicable también para métodos privados?
No entendí la declaración anterior claramente

+10

Hay una diferencia entre "no puedo" y "no debería" –

+3

¿Tiene la fuente de esta cita? – jmg

+0

@jmg - He añadido la fuente y la cita precisa en mi respuesta a continuación. Prohíbe las afirmaciones en métodos públicos solo para la comprobación de argumentos. –

Respuesta

24

La distinción importante es si usted cree que un valor incorrecto es el resultado de

a) Un error de programación que debe fijarse en el código.

b) Un error de entrada que no se puede evitar en el código y que en su lugar debe manejarse en tiempo de ejecución.

Para el primer caso, debe usar una afirmación, ya que el código del programa deberá corregirse. Si es el caso posterior, debe usar una excepción apropiada de Runtime o Check.


Las afirmaciones de IMHO son para detectar errores de programación y no entradas de usuario/externas. Quizás el autor esté confundiendo los métodos públicos como un insumo externo cuando tendrá un método público que no es llamado por una entrada externa.

Utilizaría las aserciones para verificar los argumentos para detectar errores de programación. En mi humilde opinión, este es a menudo el mejor uso para ellos. En comparación, el método privado solo debe llamarse por código en la misma clase y se espera que sean pruebas unitarias correctas y que tengan un acceso/uso limitado.

Me parece que es mucho más probable que tenga un error de programación a través de interfaces públicas porque diferentes personas hacen suposiciones diferentes (las aserciones son una buena manera de documentar y verificar suposiciones) Las comprobaciones internas no son tan útiles como cabría esperar del mismo programador tener acceso al código interno si no se ha escrito toda la base de código interna.

1

En general, parece sonido. Aunque hay algunas ocasiones en que esto podría ser útil.

Considere que es posible que deseemos realizar una operación database update para un elemento que sabemos que existe. Entonces podría ser útil para ver si la rutina tuvo éxito, por ejemplo,:

public void update(Object o) { 
    int nUpdatedObjects = dao.update(o); 
    assert(nUpdatedObjects == 1) 
} 

En este caso sirve para validate la capa dao usando el fail fast principle.

+1

De acuerdo en que este caso tiene sentido; Creo que la parte citada probablemente se refería al uso de 'assert()' para verificar que los parámetros de los métodos estén en buen estado. (Lo cual es útil, pero solo es un subconjunto de lo que 'assert()' es bueno, como lo ha señalado :) :) – sarnold

1

Las afirmaciones son para la depuración; los métodos públicos generalmente no deberían validar las cosas mediante afirmaciones de depuración, sino haciendo verificaciones de argumentos adecuadas y lanzando las excepciones apropiadas. Está bien usarlo si quiere validar el estado interno del objeto, pero no para validar los parámetros.

+3

-1 para "Las afirmaciones son para depurar". – Ingo

+1

@Ingo: teniendo en cuenta que las aserciones suelen estar deshabilitadas en las compilaciones de producción, es una afirmación razonable. – geekosaur

+2

No estoy de acuerdo. Las afirmaciones son para garantizar invariantes, en mi humilde opinión. Por supuesto, en el código de producción uno debería haber estado bastante seguro de que nunca se violara ninguna invariante. – Ingo

0

La idea es que no se sabe quién utilizará su método público. Por lo tanto, debe defenderse contra el uso inadecuado con controles normales.

Los métodos privados, por otro lado, deben ser utilizados únicamente por los desarrolladores en su equipo actual, por lo que los cheques no son (eso) obligatorios (pero aún así se recomiendan en mi humilde opinión).

Por lo tanto, para verificar la validez de los argumentos en los métodos privados, las afirmaciones deberían ser suficientes.

3

Tal como está, la frase que citó es absurda, creo.

Para estar seguro, assert no es para la validación de parámetros.

Pero en cada programa no trivial hay (o debería haber) una serie de invariantes, y este es el lugar donde las aserciones pueden ser útiles. Si puede expresar el invariante en una afirmación, hágalo, sin importar si el método es público o no.

Entonces, uno de sucederá lo siguiente:

a) todo está bien.
b) En tiempo de ejecución, el programa falla con una afirmación no cumplida. Si la afirmación es correcta, se infringe el invariante y tienes la oportunidad de descubrir por qué y corregir el error (o repensar tu diseño).

15

Las afirmaciones no deben ser utilizados para la comprobación de argumentos a los métodos públicos por las siguientes razones:

  • afirmaciones pueden ser desactivados y los cheques argumento debe Nunca ser desactivados, ya que son parte del contrato del método con sus llamadores
  • fallas de aserción no lanzan una excepción apropiada para argumentos inválidos.

Ejemplo:

/** 
    * @throws ArithmeticException if divisor is zero 
    */ 
    public void int divide(int divisor) { 
     if (divisor == 0) { 
      throw new ArithmeticException("Cannot divide by zero"); 
     } 
     ... 
    } 

Si utilizó una afirmación aquí podría estar apagado, y sería lanzar una AssertionFailedException, que es inútil y poco informativo.

1

Ofrezco una respuesta que no está exactamente en el punto. Por supuesto, puedes usar assert en métodos públicos (o donde quieras).

El punto es más sobre lo que debe hacer o no. Yo mismo entiendo perfectamente la respuesta de otras personas sobre cuándo debería o no debería usar la afirmación.

Pero debo admitir que NUNCA uso aserciones, y que casi nunca veo aserciones en el código. Trabajé solo por unos años, pero en las 4 compañías totalmente diferentes para las que trabajé, no había aserciones en el código. Ya sea la línea de más de 10 millones de aplicaciones web codificadas para reservar vuelos, un centro de control de naves espaciales, un software para administrar hipermercados o un rastreador de errores. Ninguno de ellos utilizó aseveraciones. Todas las empresas tenían diferentes necesidades y métodos. Ninguno usado afirma.

Para mí el motivo es simple. La gente aquí dice que las afirmaciones son para la depuración. Esta bien. Y que puedes desactivarlos para mejorar la velocidad. Eso también ... al principio. Cuanto más complejo sea el programa, más pasarás depuración de tiempo. Y algunos errores, incluso con una cobertura de código del 100%, incluso con extensas pruebas de integración y validación, los encontrará solo en producción.Simplemente porque tus usuarios terminan usando tu aplicación más que tú. Y no lo usarán de la misma manera que tú.

Es curioso, porque en los registros de producción, seguimos viendo stacktraces de código como este:

catch (MyException e) { 
    logger.war("This should never happen",e); 
} 

Lo que esto significa es que nunca se sabe lo que podría ocurrir en la producción.

Y eso si tienes la oportunidad de hacer un control, hazlo. Por supuesto, el comentario de registro es más divertido que útil aquí y sería mejor dejar la excepción emergente.

En todos los casos, no haga una afirmación que se desactivará en la producción. Porque será inútil. Haga que el código normal genere una excepción. Asegúrese de que esté registrado, si corresponde. Asegúrese de que se muestre un error en la IU. Y asegúrese de que pueda obtener la excepción y los registros para investigar.

Lo importante es que un día u otro, algunos usuarios harán cosas que hagan que aparezca la advertencia. Ya sea por un código mal escrito o algo así, lo verás. Y eso significa que en lugar de pasar 2 días buscando por qué diablos el programa tiene este comportamiento extraño, podrás usar la pila completa en un punto de partida y corregir el problema en 2 horas.

Una verificación con una afirmación desactivada es lo mismo que ningún control. Es código que debes escribir, leer y mantener ... Por nada. Entiendo todo el argumento del rendimiento donde las aserciones en la producción disminuyen la velocidad. Sí, en algunos casos, hay un problema de rendimiento. En la mayoría de los casos, no ganarás casi nada y perderás pistas valiosas.

+0

Respeto lo que dices. Sin embargo, las aserciones se pueden rociar rápidamente a través del código sin preocuparse por el rendimiento o el efecto en la cobertura del código. Me preocupa que el uso solo de excepciones para invariantes pueda dar lugar a que se expresen menos invariantes. Y expresar invariantes es valioso, incluso si se pueden desactivar. –

1

Esta es probablemente la fuente original, de la guía de Java SE "Programming with assertions."

No utilizar afirmaciones para comprobar los parámetros de un método público. Una afirmación de es inapropiada porque el método garantiza que siempre se aplicará las comprobaciones de los argumentos. Debe verificar sus argumentos independientemente de si las aserciones están habilitadas. Además, el constructo assert no lanza una excepción del tipo especificado. Es puede lanzar solo un AssertionError.

Esto no proscribe aserciones en métodos públicos. Los proscribe solo para verificar argumentos de método público.

Assertions test invariantes. Una clase controla los argumentos reales enviados a sus métodos privados y puede garantizar invariantes. Una clase no controla los argumentos reales enviados a los métodos públicos, y debe lanzar excepciones si se infringen las condiciones previas, incluso si las aserciones están desactivadas.

Más detalles sobre cuándo usar las afirmaciones son here.

0

Esta prohibición solo se aplica a las interfaces públicas.

De http://download.oracle.com/javase/6/docs/technotes/guides/language/assert.html#preconditions:

Por convención, las condiciones previas sobre los métodos públicos se hacen cumplir mediante comprobaciones explícitas que arrojan particulares, excepciones especificadas.

Básicamente, la convención es que las interfaces públicas están garantizando comprobar las condiciones previas y lanzar excepciones específicas en lugar de AssertionError.

Para todos los demás casos, las afirmaciones son muy valiosas y son una piedra angular para "programar por contrato". Vea http://java.sun.com/developer/technicalArticles/JavaLP/assertions para una buena introducción.

  1. Java tiene excepciones sin verificar por una razón: estos son muchos fallos catastróficos que generalmente no deberían ser detectados. Cualquier asignación de memoria puede arrojar OutOfMemoryError. Una afirmación fallida (un error en el código del cliente que proporcionó un argumento inválido a nuestra API) no es menos catastrófica.

  2. Es cierto que las aserciones pueden estar desactivadas. Esto nunca debería hacerse, sin embargo. Solo no lo hagas. Si tiene dudas de que alguien que está ejecutando su código desactivará las afirmaciones, siempre puede crear una clase de aserciones triviales que no pueda ser desactivada. El principio de usar aserciones no se modifica.

  3. Lo único que debe considerar sobre las aserciones es el contrato de rendimiento en sus interfaces. Tenga en cuenta que esto también podría ser un contrato "implícito" (es decir, cuando una implementación obvia debería ser muy rápida, tomarse un minuto está fuera del contrato de rendimiento implícito). Por lo tanto, asegúrese de verificar sus afirmaciones aceptables en virtud del contrato de desempeño.

1

No hay nada de malo en usar una aserción en un método público. Podrían usarse para verificar que ciertas invariantes (cosas que usted cree que son ciertas), sobre el objeto o la clase a la que llama el método de - de hecho sean ciertas.

Por ejemplo, podría utilizar una aserción como lo he hecho, en el método public build() de un constructor, para asegurarse de que el constructor fue inicializado correctamente por mi propio código interno en esa clase (ya que tengo un número de constructores sobrecargados para ello).

Pero lo que NUNCA debes hacer, es usar afirmaciones para verificar los ARGUMENTOS de los métodos públicos. Una distinción importante. Creo que las otras respuestas aquí ya han explicado las razones con suficiente claridad, así que no voy a repetir nada.

0

Cualquier persona puede llamar a los métodos públicos y no hay control sobre lo que se puede pasar como valores de argumento.

Supongamos que en el método público hemos validado los valores del argumento de entrada utilizando aserciones, entonces existe la posibilidad de que estas verificaciones (validaciones) no se puedan realizar (o ejecutar) si las aserciones están deshabilitadas y obtendremos resultados indeseables del ejecución del método. Para evitar dichos resultados no deseados, no deberíamos usar aserciones para validar los valores del argumento del método público.

Ahora la pregunta que puede surgir en su mente es ¿por qué usar las aserciones para validar los valores del argumento del método privado?

Bueno, la razón es que los métodos privados se pueden llamar desde dentro de la clase que se define (ya sea desde el método de instancia o desde el método principal estático). El desarrollador de la clase de hecho conoce todo sobre el método privado: qué sí, cómo llamarlo y qué valores de parámetro pasar. Por lo tanto, los valores de argumento de método privado se pueden validar de forma segura utilizando aserciones.

Cuestiones relacionadas