¿Es mejor devolver valores NULL o vacíos de funciones / métodos donde el valor de retorno no está presente?

135

Estoy buscando una recomendación aquí. Estoy luchando con si es mejor devolver NULL o un valor vacío de un método cuando el valor de retorno no está presente o no se puede determinar.

Tome los siguientes dos métodos como ejemplos:

string ReverseString(string stringToReverse) // takes a string and reverses it.
Person FindPerson(int personID)    // finds a Person with a matching personID.

En ReverseString(), diría que devuelve una cadena vacía porque el tipo de retorno es una cadena, por lo que la persona que llama está esperando eso. Además, de esta manera, la persona que llama no tendría que verificar si se devolvió un NULL.

En FindPerson(), regresar NULL parece un mejor ajuste. Independientemente de si new Person()se devuelve o no NULL o un Objeto de persona vacío ( ), la persona que llama tendrá que verificar si el Objeto de persona está NULO o vacío antes de hacerle algo (como llamar UpdateName()). Entonces, ¿por qué no simplemente devolver NULL aquí y luego la persona que llama solo tiene que verificar NULL?

¿Alguien más lucha con esto? Cualquier ayuda o idea es apreciada.

PB
fuente
2
Variará También podría argumentar que el método debería detener los valores que son incorrectos por adelantado, por ejemplo, su parámetro stringToReverse se pasa como vacío o nulo. Si realizó esa verificación (arrojó una excepción), siempre devolverá algo que no sea nulo.
Aaron McIver
Fowler POEAA - pág. 496 Patrones base - Caso especial (objeto nulo) Bloch Java efectivo, 2a edición Artículo 43: Devolver matrices o colecciones vacías, no nulas
Boris Treukhov
1
@ Boris No vi tu comentario. De hecho, acabo de publicar un caso especial como respuesta.
Thomas Owens
@Thomas No veo ningún problema en eso :). En cuanto a la pregunta, es una cuestión de sentido común de todos modos.
Boris Treukhov
Un comentario interesante es que en las bases de datos Oracle NULL y la cadena vacía son lo mismo
WuHoUnited

Respuestas:

77

StackOverflow tiene una buena discusión sobre este tema exacto en estas preguntas y respuestas . En la pregunta mejor calificada, kronoz señala:

Por lo general, la mejor idea es devolver nulo si tiene la intención de indicar que no hay datos disponibles.

Un objeto vacío implica que se han devuelto datos, mientras que devolver nulo indica claramente que no se ha devuelto nada.

Además, devolver un valor nulo dará como resultado una excepción nula si intenta acceder a los miembros en el objeto, lo que puede ser útil para resaltar el código defectuoso; intentar acceder a un miembro de la nada no tiene sentido. El acceso a los miembros de un objeto vacío no fallará, lo que significa que los errores pueden quedar sin descubrir.

Personalmente, me gusta devolver cadenas vacías para funciones que devuelven cadenas para minimizar la cantidad de manejo de errores que debe implementarse. Sin embargo, deberá asegurarse de que el grupo con el que está trabajando seguirá la misma convención; de lo contrario, no se lograrán los beneficios de esta decisión.

Sin embargo, como señaló el póster en la respuesta SO, los valores nulos probablemente deberían devolverse si se espera un objeto para que no haya dudas sobre si se están devolviendo datos.

Al final, no hay una mejor manera de hacer las cosas. Construir un consenso de equipo conducirá en última instancia las mejores prácticas de su equipo.

JW8
fuente
8
Personalmente, me gusta devolver cadenas vacías para funciones que devuelven cadenas para minimizar la cantidad de manejo de errores que debe implementarse. Nunca entendí este argumento. El cheque nulo es qué, a lo sumo <10 caracteres? ¿Por qué actuamos como si esto fuera a doblar la mano de obra?
Aaron McIver
19
Nadie dijo que había vuelto a doblar la mano de obra. Pero es trabajo. Agrega un caso especial al código que significa una rama más para probar. Además, interrumpe el flujo del código. for x in list_of_things() {...}podría decirse que es más rápido que asimilarlol = list_of_things(); if l != null {...}
Bryan Oakley
55
@Bryan: hay una gran diferencia entre una lista vacía de valores y una cadena vacía. Una cadena rara vez representa una lista de caracteres.
Kevin Cline
3
@kevin cline: por supuesto. Pero en el caso de una cadena, es posible que desee que esa cadena aparezca en un registro, ya sea nula o no. Tener que verificar si es nulo para poder imprimir una cadena vacía ofusca la intención real. O tal vez es algo así como un campo de base de datos que contiene contenido aportado por el usuario que desea agregar a una página web. Es más fácil de hacer emit(user.hometown)queif user.hometown == null { emit("") else {emit(user.hometown)}
Bryan Oakley
1
No solo es un tipeo adicional (no es un gran problema), sino que afecta la legibilidad. Personalmente encuentro que el código con un montón de cheques nulos me distrae.
ToddR
82

En todo el código que escribo, evito regresar nullde una función. Lo leí en Clean Code .

El problema con el uso nulles que la persona que usa la interfaz no sabe si nulles un posible resultado y si tiene que verificarlo, porque no hay un not nulltipo de referencia.

En F # puede devolver un optiontipo, que puede ser some(Person)o none, por lo que es obvio para la persona que llama que tienen que verificar.

El patrón análogo de C # (anti-) es el Try...método:

public bool TryFindPerson(int personId, out Person result);

Ahora sé que las personas han dicho que odian el Try...patrón porque tener un parámetro de salida rompe las ideas de una función pura, pero en realidad no es diferente de:

class FindResult<T>
{
   public FindResult(bool found, T result)
   {
       this.Found = found;
       this.Result = result;
   }

   public bool Found { get; private set; }
   // Only valid if Found is true
   public T Result { get; private set;
}

public FindResult<Person> FindPerson(int personId);

... y para ser sincero, puede suponer que todos los programadores .NET conocen el Try...patrón porque el marco .NET lo utiliza internamente. Eso significa que no tienen que leer la documentación para comprender lo que hace, lo cual es más importante para mí que apegarse a la visión de las funciones de algunos puristas (entender que resultes un outparámetro, no un refparámetro).

Así que iría TryFindPersonporque pareces indicar que es perfectamente normal no poder encontrarlo.

Si, por otro lado, no hay una razón lógica para que la persona que llama alguna vez proporcione un mensaje personIdque no existe, probablemente haría esto:

public Person GetPerson(int personId);

... y luego lanzaría una excepción si no fuera válida. El Get...prefijo implica que la persona que llama sabe que debe tener éxito.

Scott Whitlock
fuente
28
+1, respondería esta pregunta con una referencia a Clean Code si aún no lo hubiera hecho. Me gusta el mantra: "SI TU FUNCIÓN NO PUEDE HACER LO QUE NOMBRE DICE, LUEGO LANZA UNA EXCEPCIÓN". Muuuch mejor que comprobar nulo cada docena de líneas más o menos ...
Graham
13
He renunciado a asumir cualquier cosa sobre el conocimiento de las personas.
CaffGeek
55
"El problema con el uso de nulo es que la persona que usa la interfaz no sabe si nulo es un posible resultado y si tiene que verificarlo, porque no hay un tipo de referencia nulo". Dado que los tipos de referencia pueden ser nulos, ¿no puede suponer siempre que nulo es un resultado posible?
Tommy Carlier
44
Si una función devuelve un puntero (C / C ++) o una referencia a un objeto (Java), siempre supongo que puede devolver nulo.
Giorgio
77
"El problema con el uso de nulo es que la persona que usa la interfaz no sabe si nulo es un resultado posible, y si tiene que verificarlo, [...]" Si un método puede devolver nulo, debería ser explícitamente mencionado como parte del contrato API.
Zsolt Török
28

Puede probar el patrón de casos especiales de Martin Fowler , de Paterns of Enterprise Application Architecture :

Los nulos son cosas incómodas en los programas orientados a objetos porque derrotan el polimorfismo. Por lo general, puede invocar foo libremente en una referencia variable de un tipo determinado sin preocuparse de si el elemento es el tipo exacto o una subclase. Con un lenguaje fuertemente tipado, incluso puede hacer que el compilador verifique que la llamada sea correcta. Sin embargo, dado que una variable puede contener nulo, puede encontrarse con un error de tiempo de ejecución invocando un mensaje en nulo, lo que le dará un buen y amigable seguimiento de la pila.

Si es posible que una variable sea nula, debe recordar rodearla con un código de prueba nulo para que haga lo correcto si hay una nula presente. A menudo, lo correcto es lo mismo en muchos contextos, por lo que terminas escribiendo código similar en muchos lugares, cometiendo el pecado de la duplicación de código.

Los nulos son un ejemplo común de tales problemas y otros surgen regularmente. En los sistemas de números tienes que lidiar con el infinito, que tiene reglas especiales para cosas como la suma que rompen los invariantes habituales de los números reales. Una de mis primeras experiencias en software de negocios fue con un cliente de servicios públicos que no era completamente conocido, conocido como "ocupante". Todo esto implica alterar el comportamiento habitual del tipo.

En lugar de devolver nulo, o algún valor impar, devuelva un caso especial que tenga la misma interfaz que lo que espera la persona que llama.

Thomas Owens
fuente
Me encontré con este escenario, pero solo después de que se lanzó el software. Mis datos de prueba nunca lo activaron, por lo que fue un poco inesperado y fue un problema depurarlo. Aunque no lo resolví con el patrón de Caso especial, es bueno ser consciente de ello.
samis
14

Creo ReverseString()que devolvería la cadena invertida y arrojaría un IllegalArgumentExceptionsi se pasara en a Null.

Creo que FindPerson()debería seguir el Patrón NullObject o generar una excepción no verificada sobre no encontrar algo si siempre debe poder encontrar algo.

Tener que lidiar Nulles algo que debe evitarse. ¡Tener Nullen idiomas ha sido llamado un error de mil millones de dólares por su inventor!

Lo llamo mi error de mil millones de dólares. Fue la invención de la referencia nula en 1965. En ese momento, estaba diseñando el primer sistema de tipo integral para referencias en un lenguaje orientado a objetos (ALGOL W).

Mi objetivo era asegurar que todo uso de referencias debería ser absolutamente seguro, con una verificación realizada automáticamente por el compilador. Pero no pude resistir la tentación de poner una referencia nula, simplemente porque era muy fácil de implementar.

Esto ha llevado a innumerables errores, vulnerabilidades y fallas en el sistema, lo que probablemente ha causado miles de millones de dólares de dolor y daños en los últimos cuarenta años.

En los últimos años, se han utilizado varios analizadores de programas como PREfix y PREfast en Microsoft para verificar referencias y dar advertencias si existe el riesgo de que no sean nulos. Los lenguajes de programación más recientes como Spec # han introducido declaraciones para referencias no nulas. Esta es la solución, que rechacé en 1965.

Tony Hoare


fuente
11

Devolver una opción . Todos los beneficios de devolver un valor no válido diferente (como poder tener valores vacíos en sus colecciones) sin ningún riesgo de NullPointerException.

hugomg
fuente
1
Interesante. ¿Cómo implementar una opción en Java? ¿Y en C ++?
Giorgio
1
@Giorgio, para Java, las bibliotecas Guava, de Google, tienen una clase llamada Opcional .
Otavio Macedo
1
Para C ++, hayboost::optional<T>
MSalters
8

Veo ambos lados de este argumento, y me doy cuenta de que algunas voces bastante influyentes (por ejemplo, Fowler) abogan por no devolver nulos para mantener el código limpio, evitar bloques adicionales de manejo de errores, etc.

Sin embargo, tiendo a ponerme del lado de los defensores de volver nulo. Encuentro que hay una distinción importante al invocar un método y al responder con no tengo ningún dato y al responder con esta cadena vacía .

Como he visto parte de la discusión que hace referencia a una clase de Persona, considere el escenario en el que intenta buscar una instancia de la clase. Si pasa algún atributo del buscador (por ejemplo, una ID), un cliente puede verificar inmediatamente si hay valores nulos para ver si no se encontró ningún valor. Esto no es necesariamente excepcional (por lo tanto, no necesita excepciones), pero también debe documentarse claramente. Sí, esto requiere un poco de rigor por parte del cliente, y no, no creo que sea algo malo en absoluto.

Ahora considere la alternativa donde devuelve un objeto Persona válido ... que no tiene nada. ¿Pones nulos en todos sus valores (nombre, dirección, bebida favorita), o ahora llenas esos con objetos válidos pero vacíos? ¿Cómo puede determinar ahora su cliente que no se encontró ninguna persona real? ¿Necesitan verificar si el nombre es una cadena vacía en lugar de nula? ¿Acaso este tipo de cosas en realidad no conducirá a un desorden de código o más declaraciones condicionales que si simplemente hubiéramos verificado si era nulo y continuamos?

Una vez más, hay puntos a cada lado de este argumento con los que podría estar de acuerdo, pero creo que esto tiene más sentido para la mayoría de las personas (haciendo que el código sea más fácil de mantener).

RonU
fuente
La diferencia es, "no FindPerson, o GetPersondevolver un valor nulo o una excepción si no existe la clave?" Como usuario de la API simplemente no lo sé y tengo que verificar la documentación. Por otro lado, bool TryGetPerson(Guid key, out Person person)no requiere que verifique la documentación y sé que no se produce una excepción en lo que equivale a una circunstancia no excepcional. Ese es el punto que estoy tratando de hacer en mi respuesta.
Scott Whitlock
44
Creo que la gente se apegó demasiado a las excepciones. Las excepciones son malas y consumen muchos recursos. Sin mencionar que las personas intentan atrapar declaraciones sin resolver nada. Las excepciones son una clara señal de que algo salió fundamentalmente mal. Por ejemplo, las referencias nulas arrojan una excepción, porque es claramente incorrecto hacer referencia a objetos nulos. Es incorrecto usarlo para verificar si se encontró o no a una persona.
Vladimir Kocjancic
1
@VladimirKocjancic: Estoy totalmente de acuerdo: las excepciones deben usarse para situaciones excepcionales, como errores de software, fallas de hardware, configuración incorrecta del sistema. Si está calculando una función parcial (como findPerson), es absolutamente normal no obtener ningún resultado. Esto no debería conducir a una excepción.
Giorgio
6

Devuelva nulo si necesita saber si el artículo existe o no. De lo contrario, devuelva el tipo de datos esperado. Esto es especialmente cierto si devuelve una lista de elementos. Por lo general, es seguro asumir que si la persona que llama desea una lista, querrá iterar sobre la lista. Muchos (¿la mayoría? ¿Todos?) Fallan si intenta iterar sobre nulo pero no cuando itera sobre una lista que está vacía.

Me resulta frustrante intentar usar un código como este, solo para que falle:

for thing in get_list_of_things() {
    do_something_clever(thing)
}

No debería tener que agregar un caso especial para el caso cuando no hay cosas .

Bryan Oakley
fuente
77
En los casos en que se espera una lista u otro grupo de valores, siempre elijo devolver una lista vacía, exactamente por esta razón. La acción predeterminada (iterar en una lista vacía) casi siempre es correcta, y si no es así, la persona que llama puede verificar explícitamente si la lista está vacía.
TMN
5

Depende de la semántica del método. Posiblemente podría especificar, su método solo acepta "No nulo". En Java puede declarar que usando algunas anotaciones de metadatos:

string ReverseString(@NotNull String stringToReverse)

De alguna manera, debe especificar el valor de retorno. Si declara, acepta solo valores NotNull, está obligado a devolver una cadena vacía (si la entrada también era una cadena vacía).

El segundo caso es un poco complicado en su semántica. Si este método es devolver a alguna persona por su clave principal (y se espera que la persona exista), la mejor manera es lanzar una excepción.

Person FindPerson(int personID)

Si busca a una persona por alguna identificación adivinada (lo cual me parece extraño), será mejor que declare ese método como @Nullable.

Martin Vejmelka
fuente
3

Recomendaría usar el patrón de objeto nulo siempre que sea posible. Simplifica el código al llamar a sus métodos, y no puede leer código feo como

if (someObject != null && someObject.someMethod () != whateverValue)

Por ejemplo, si un método devuelve una colección de objetos que se ajustan a algún patrón, entonces devolver una colección vacía tiene más sentido que regresar null, e iterar sobre esta colección vacía prácticamente no tendrá penalización de rendimiento. Otro caso sería un método que devuelve la instancia de clase utilizada para registrar datos, devolviendo un objeto nulo en lugar de nullpreferible en mi opinión, ya que no obliga a los usuarios a verificar siempre si la referencia devuelta es null.

En los casos en que regresar nulltiene sentido (llamando al findPerson ()método, por ejemplo), trataría de proporcionar al menos un método que devuelva si el objeto está presente ( personExists (int personId)por ejemplo), otro ejemplo sería el containsKey ()método en a Mapen Java). Limpia el código de las personas que llaman, ya que puede ver fácilmente que existe la posibilidad de que el objeto deseado no esté disponible (la persona no existe, la clave no está presente en el mapa). Comprobar constantemente si una referencia está nullofusca el código en mi opinión.

Laf
fuente
3

nulo es lo mejor para devolver si y solo si se aplican las siguientes condiciones:

  • Se espera el resultado nulo en funcionamiento normal . Podría esperarse que no pueda encontrar a una persona en algunas circunstancias razonables, por lo tanto, findPerson () devuelve nulo está bien. Sin embargo, si se trata de una falla genuinamente inesperada (por ejemplo, en una función llamada saveMyImportantData ()), entonces debería lanzar una excepción. Hay una pista en el nombre: ¡las excepciones son para circunstancias excepcionales!
  • nulo se usa para significar "no encontrado / sin valor" . Si quieres decir algo más, ¡entonces devuelve algo más! Un buen ejemplo serían las operaciones de coma flotante que devuelven Infinity o NaN; estos son valores con significados específicos, por lo que sería muy confuso si devuelve nulo aquí.
  • La función está destinada a devolver un valor único , como findPerson (). Si se diseñó para devolver una colección, por ejemplo, findAllOldPeople (), lo mejor es una colección vacía. Un corolario de esto es que una función que devuelve una colección nunca debe devolver nulo .

Además, asegúrese de documentar el hecho de que la función puede devolver nulo.

Si sigue estas reglas, los nulos son en su mayoría inofensivos. Tenga en cuenta que si olvida verificar nulo, normalmente obtendrá una NullPointerException inmediatamente después, que generalmente es un error bastante fácil de solucionar. Este enfoque de falla rápida es mucho mejor que tener un valor de retorno falso (por ejemplo, una cadena vacía) que se propaga silenciosamente por su sistema, posiblemente corrompiendo datos, sin lanzar una excepción.

Finalmente, si aplica estas reglas a las dos funciones enumeradas en la pregunta:

  • FindPerson : sería apropiado que esta función devuelva nulo si no se encuentra a la persona
  • ReverseString : parece que nunca fallaría en encontrar un resultado si se pasa una cadena (ya que todas las cadenas se pueden revertir, incluida la cadena vacía). Por lo tanto, nunca debería volver nulo. Si algo sale mal (¿sin memoria?), Entonces debería arrojar una excepción.
mikera
fuente
1

En mi opinión, hay una diferencia entre devolver NULL, devolver algún resultado vacío (por ejemplo, la cadena vacía o una lista vacía) y lanzar una excepción.

Normalmente tomo el siguiente enfoque. Considero una función o método llamada f (v1, ..., vn) como la aplicación de una función

f : S x T1 x ... x Tn -> T

donde S it el "estado del mundo" T1, ..., Tn son los tipos de parámetros de entrada y T es el tipo de retorno.

Primero trato de definir esta función. Si la función es parcial (es decir, hay algunos valores de entrada para los que no está definida), devuelvo NULL para señalar esto. Esto se debe a que quiero que el cálculo finalice normalmente y me diga que la función que solicité no está definida en las entradas dadas. Usar, por ejemplo, una cadena vacía como valor de retorno es ambiguo porque podría ser que la función se define en las entradas y que la cadena vacía es el resultado correcto.

Creo que la verificación adicional de un puntero NULL en el código de llamada es necesaria porque está aplicando una función parcial y es la tarea del método llamado decirle si la función no está definida para la entrada dada.

Prefiero utilizar excepciones para errores que no permiten realizar el cálculo (es decir, no fue posible encontrar ninguna respuesta).

Por ejemplo, supongamos que tengo una clase Cliente y quiero implementar un método

Customer findCustomer(String customerCode)

buscar un cliente en la base de datos de la aplicación por su código. En este método, lo haría

  • Devuelve un objeto de la clase Cliente si la consulta es exitosa,
  • Devuelve nulo si la consulta no encuentra ningún cliente.
  • Lanza una excepción si no es posible conectarte a la base de datos.

Las comprobaciones adicionales para nulo, por ejemplo

Customer customer = findCustomer("...");
if (customer != null && customer.getOrders() > 0)
{
    ...
}

son parte de la semántica de lo que estoy haciendo y no solo los "omitiría" para que el código se lea mejor. No creo que sea una buena práctica simplificar la semántica del problema en cuestión solo para simplificar el código.

Por supuesto, dado que la comprobación de nulo ocurre muy a menudo es bueno si el lenguaje admite alguna sintaxis especial para ello.

También consideraría usar el patrón de objeto nulo (como lo sugiere Laf) siempre que pueda distinguir el objeto nulo de una clase de todos los demás objetos.

Giorgio
fuente
0

Los métodos que devuelven colecciones deberían devolverse vacíos, pero otros podrían devolver nulo, porque para las colecciones puede suceder que tenga un objeto pero no haya elementos, por lo que el llamante validará solo el tamaño en lugar de ambos.

Phani
fuente
0

Para mí hay dos casos aquí. Si devuelve algún tipo de lista, siempre debe devolver la lista, pase lo que pase, vacía si no tiene nada que agregar.

El único caso en el que veo algún debate es cuando devuelve un solo artículo. Me encuentro prefiriendo volver nulo en caso de falla en tal situación sobre la base de hacer que las cosas fallen rápidamente.

Si devuelve un objeto nulo y la persona que llama necesita un objeto real, puede seguir adelante e intentar usar el objeto nulo produciendo un comportamiento inesperado. Creo que es mejor que la rutina aumente si se olvidan de lidiar con la situación. Si algo está mal, quiero una excepción lo antes posible. Es menos probable que envíe un error de esta manera.

Loren Pechtel
fuente
0

Agregando a lo que la gente ya dijo sobre el Maybeconstructor de tipos:

Otra gran ganancia, además de no arriesgar NPE, es la semántica. En el mundo funcional, donde tratamos con funciones puras, nos gusta tratar de hacer funciones que, cuando se aplican, sean exactamente equivalentes a su valor de retorno . Considere el caso de String.reverse(): Esta es una función que dada una determinada cadena representa la versión invertida de esa cadena. Sabemos que esta cadena existe, porque cada cadena se puede revertir (las cadenas son básicamente conjuntos de caracteres ordenados).

Ahora, ¿qué pasa findCustomer(int id)? Esta función representa al cliente que tiene la ID dada. Esto es algo que puede o no existir. Pero recuerde, las funciones tienen un solo valor de retorno, por lo que realmente no puede decir "esta función devuelve a un cliente con la ID dada O devuelve null.

Este es mi problema principal al devolver nully devolver un objeto nulo. Son engañosos nullno es un cliente, y tampoco es realmente "la ausencia de un cliente". Es la ausencia de NADA. Es solo un puntero sin tipo a NADA. Muy bajo nivel y muy feo y muy propenso a errores. Un objeto nulo también es bastante engañoso aquí, creo. Un cliente nulo ES un cliente. No es la ausencia de uno, no es el cliente con la identificación solicitada, por lo que devolverlo es simplemente INCORRECTO. Este NO es el cliente que solicité, pero aún así afirma que devolvió un cliente. Tiene la identificación incorrecta, claramente esto es un error. Rompe el contrato sugerido por el nombre del método y la firma. Requiere que el código del cliente asuma cosas sobre su diseño o que lea la documentación.

Ambos problemas son resueltos por a Maybe Customer. De repente, no estamos diciendo "esta función representa al cliente con la ID dada". Estamos diciendo "esta función representa al cliente con la identificación dada si existe . Ahora es muy claro y explícito sobre lo que hace. Si solicita al cliente con una identificación no existente, recibirá Nothing. ¿Cómo es esto mejor? que null? no sólo por el riesgo NPE. Pero también porque el tipo de Nothingno es sólo Maybe. es Maybe Customer. tiene un significado semántico. Esto significa específicamente "la ausencia de un cliente", lo que indica que un cliente tal no existe.

Otro problema con nulo es, por supuesto, que es ambiguo. ¿Es que no encontró al cliente, o hubo un error de conexión de base de datos o simplemente no puedo ver a ese cliente?

Si tiene que manejar varios casos de error como este, puede lanzar excepciones para esas versiones o (y lo prefiero de esta manera) podría devolver un Either CustomerLoadError Customer, que representa algo que salió mal o el cliente devuelto. Tiene todas las ventajas de Maybe Customeral mismo tiempo que le permite especificar qué puede salir mal.

Lo principal que busco es capturar el contrato de la función en su firma. No asumas cosas, no confíes en convenciones fugaces, sé explícito.

sara
fuente
0

1) Si la función semántica es que no puede devolver nada, la persona que llama DEBE probarlo, de lo contrario, por ejemplo. tome su dinero y no se lo dé a nadie.

2) Es bueno hacer funciones que semánticamente siempre devuelven algo (o tirar).

Con un registrador , tiene sentido devolver un registrador que no se registra si no se definió ningún registrador. Al devolver la colección, casi nunca tiene sentido (excepto en un "nivel lo suficientemente bajo", donde la colección en sí es LOS datos, no lo que contiene) para no devolver nada, porque un conjunto vacío es un conjunto, nada.

Con un ejemplo de persona , iría de manera "hibernada" (get vs load, IIRC, pero allí se complica por los objetos proxy para la carga diferida) de tener dos funciones, una que devuelve nulo y la segunda que arroja.

user470365
fuente
-1
  • NULL debe devolverse si la aplicación espera que haya datos disponibles pero los datos no están disponibles. Por ejemplo, un servicio que devuelve CITY basado en código postal debe devolver nulo si no se encuentra la ciudad. La persona que llama puede decidir manejar el nulo o explotar.

  • Se debe devolver una lista vacía si hay dos posibilidades. Datos disponibles o NO hay datos disponibles. Por ejemplo, un servicio que devuelve las CIUDAD (s) si la población es mayor que cierto número. Puede devolver una lista vacía si no hay datos que satisfagan los criterios dados.

java_mouse
fuente
-2

Devolver NULL es un diseño terrible , en un mundo orientado a objetos. En pocas palabras, el uso NULL conduce a:

  • manejo de errores ad-hoc (en lugar de excepciones)
  • semántica ambigua
  • falla lenta en lugar de rápida
  • pensamiento de computadora versus pensamiento de objeto
  • objetos mutables e incompletos

Consulte esta publicación de blog para obtener una explicación detallada: http://www.yegor256.com/2014/05/13/why-null-is-bad.html

yegor256
fuente