validar validacion pasar obtener objetos guardar fecha eventos entre actividades java null design-by-contract

java - validacion - Cómo mostrar si un método puede devolver nulo



validacion de fecha en java (11)

¿Has echado un vistazo a Spec # ?

Después de publicar esta pregunta y leer esa, me di cuenta de que es muy importante saber si se supone que un método devolverá nulo, o si se considera una condición de error y se deben lanzar excepciones. También hay una agradable discusión sobre cuándo devolver ''nulo'' o lanzar una excepción .

Estoy escribiendo un método y ya sé si quiero devolver una excepción nula o arrojar una excepción, ¿cuál es la mejor manera de expresar mi decisión, en otras palabras, para documentar mi contrato?

Algunas formas en que puedo pensar:

  • Anótelo en las especificaciones / la documentación (¿alguien lo leerá?)
  • Hazlo parte del nombre del método (como sugerí aquí )
  • Supongamos que todos los métodos que arrojen una excepción no devolverán nulo, y todos los que no lo hagan arrojarán nulo.

Estoy hablando principalmente de Java, pero también puede aplicarse a otros idiomas: ¿por qué hay una forma formal de expresar si se lanzarán excepciones (las palabras clave throws ) pero no hay forma formal de expresar si se puede devolver null?

¿Por qué no hay algo como eso?

public notnull Object methodWhichCannotReturnNull(int i) throws Exception { return null; // this would lead to a compiler error! }

Resumen y conclusión

Hay muchas formas de expresar el contrato:

  • Si su IDE lo admite (como IntelliJ), es mejor usar una anotación como @NotNull porque es visible para el programador y se puede usar para la verificación automatizada en tiempo de compilación. Hay un complemento para Eclipse para agregar soporte para estos, pero no funcionó para mí.
  • Si no se trata de una opción, use tipos personalizados como Option<T> o NotNull<T> , que añaden claridad y, al menos, la comprobación del tiempo de ejecución.
  • De cualquier forma, documentar el contrato en JavaDoc nunca hace daño y, a veces, incluso ayuda.
  • El uso de nombres de métodos para documentar la nulabilidad del valor de retorno no fue propuesto por nadie más que yo, y aunque podría ser muy detallado y no siempre útil, todavía creo que a veces también tiene sus ventajas.

A toda costa, evite confiar en los JavaDocs. Las personas solo las leen si la firma no parece trivial y se explica por sí misma (lo cual es malo para empezar), y aquellos que realmente se molestan en leerlos son menos propensos a cometer un error con los nulos ya que actualmente están siendo más cuidadosos .


En términos generales, supondría que un valor de retorno nulo está en contra del contrato de la API por defecto. Casi siempre es posible diseñar su código de modo que nunca se devuelva un valor nulo de sus API durante el flujo de ejecución "normal". (Por ejemplo, marque foo.contains (obj) en lugar de llamar a foo.get (obj) y tener una rama separada para null. O bien, use el patrón de objeto nulo .

Si no puede diseñar su API de esa manera, yo claramente documentaría cuándo y por qué podría lanzarse un nulo, al menos en el Javadoc, y posiblemente también utilizando una @anotación personalizada tal como lo han sugerido varias de las otras respuestas.


Existe algo de soporte para una anotación @Nullable y @NotNull en IntelliJ IDEA . También se habla de agregar esas anotaciones (o una característica similar) a Java 7. Lamentablemente, no sé hasta dónde llegó eso o si todavía está en buen camino.


Para Java, uno puede usar la descripción Javadoc de un método para documentar el significado del valor devuelto, incluyendo si puede ser nulo. Como se mencionó, las anotaciones también pueden brindar ayuda aquí.

Por otro lado, admito que no veo el nulo como algo temible. Hay situaciones en las que "el hogar de nadie" es una condición significativa (aunque la técnica de Objeto nulo también tiene un valor real aquí).

Es cierto que intentar una invocación de método en un valor nulo provocará una excepción. Pero también intentará dividir por cero. ¡Eso no significa que tengamos que ir a una campaña para eliminar ceros! Simplemente significa que tenemos que entender el contrato en un método y hacer lo correcto con los valores que devuelve.


Puede escribir su propia anotación (Java) o atributo (C #) para indicar que el valor de retorno puede ser nulo. Nada lo comprobará automáticamente (aunque .NET 4.0 tendrá contratos de código para este tipo de cosas), pero al menos actuaría como documentación.


Puede usar el tipo de Option , que se parece mucho a una lista que tiene cero o un elemento. Un tipo de devolución de la Option<Object> indica que el método puede devolver un Object , o puede devolver un valor especial de tipo None . Este tipo reemplaza el uso de null con mejores controles de tipo.

Ejemplo:

public Option<Integer> parseInt(String s) { try { return Option.some(Integer.parseInt(s)); } catch (Exception e) { return Option.none(); } }

Si usa esto de manera consistente, puede activar las advertencias nulas de IDE, o simplemente usar grep para null que no debería aparecer en su código en absoluto si usa Option.none() todas partes donde normalmente usaría un literal null .

Option viene de serie con Scala, y se llama Maybe in Haskell. El enlace de arriba es para una biblioteca llamada Functional Java que lo incluye. Esa versión implementa la interfaz Iterable , y tiene métodos monádicos que le permiten componer las cosas muy bien. Por ejemplo, para proporcionar un valor predeterminado de 0 en el caso de None :

int x = optionalInt.orSome(0);

Y puedes reemplazar esto ...

if (myString != null && !"".equals(myString))

... con esto, si tiene una Option<String> ...

for (String s : myOptionString)


Si está utilizando Java 5+, puede usar una Anotación personalizada, por ej. @MayReturnNull

ACTUALIZAR

Dejando a un lado toda la filosofía de codificación (devolver nulo, usando excepciones, afirmaciones, yada yada), espero que lo anterior responda a su pregunta. Además de las primitivas que tienen valores predeterminados, los tipos complejos pueden ser nulos o no, y su código debe lidiar con ellos.


Tal vez podrías definir una clase genérica llamada "NotNull", para que tu método sea como:

public NotNull<Object> methodWhichCannotReturnNull(int i) throws Exception { // the following would lead to a run-time error thown by the // NotNull constructor, if it''s constructed with a null value return new NotNull<Object>(null); }

Esta sigue siendo una comprobación en tiempo de ejecución (no de tiempo de compilación), pero:

  • Se lanza en la implementación del método (no es un error en el código de llamada)
  • Es autodocumentado (la persona que llama sabe que está NotNull<T> como tipo de devolución)

Una muy buena pregunta de seguimiento. Considero null un valor verdaderamente especial, y si un método puede devolver null , debe documentar claramente en el Javadoc cuando lo haga ( @return some value ..., or null if ... ). Al codificar estoy a la defensiva, y supongo que un método puede devolver null menos que esté convencido de que no puede (por ejemplo, porque el Javadoc lo dice).

La gente se dio cuenta de que esto era un problema, y ​​una solución propuesta es usar anotaciones para expresar la intención de una manera que se pueda verificar automáticamente. Consulte JSR 305: Anotaciones para detección de defectos de software , JSR 308: Anotaciones sobre tipos de Java y cómo hacerlo anulable de JetBrain .

Su ejemplo podría verse así, y rechazado por el IDE, el compilador u otras herramientas de análisis de código.

@NotNull public Object methodWhichCannotReturnNull(int i) throws Exception { return null; // this would lead to a compiler error! }


De hecho, en nuestro marco tenemos un tipo de puntero ''no nulo'', que puede devolverse para indicar que el método siempre devolverá un valor.

Veo tres opciones:

  1. esperar el soporte de idiomas para expresarlo (por ejemplo, la cosa C #?! )
  2. usa Aspect Orientation para construir tus propias extensiones de lenguaje para expresarlo
  3. usa un tipo personalizado para expresarlo
  4. (pero se basa en la cooperación del desarrollador) usa un esquema de nombres para indicarlo