Comportamiento esperado cuando una solicitud de una colección tendrá cero elementos

13

Digamos que te dan lo siguiente ...

List<Thing> theThings = fubar.Things.All();

Si no hubiera nada que devolver, ¿qué esperarías que volviera fubar.Things.All ()?

Editar: Gracias por las opiniones. Esperaré un poco y aceptaré la entrada con más ups.

Estoy de acuerdo con las respuestas hasta ahora, particularmente aquellas que sugieren una colección vacía. Un proveedor proporcionó una API con varias llamadas similares al ejemplo anterior. Un proveedor que hizo $ 4.6 millones en ingresos a través de sus API el año pasado, por cierto. Hacen algo con lo que estoy básicamente en desacuerdo: lanzan una excepción.

abscode
fuente
Parece ser un consenso bastante sólido [aquí] [1]: colección vacía. Siempre. [1]: stackoverflow.com/questions/1969993/…
Jesse C. Slicer
¿Para qué es el tipo de datos Things? Si tiene sentido que el Thingscampo devuelva nulo, entonces tiene sentido que reciba una excepción porque no verificó nulo antes de su llamada All(). Sin embargo, estoy de acuerdo con las personas que piensan que fubar.Thingsdebería devolver una colección vacía en lugar de nula.
Colin D
Ya veo a lo que te refieres, Colin. En este caso, puede asumir que las cosas existen y que All () es estático. La excepción es específica de que la colección esté vacía, no por alguna otra razón.
abscode
Dios mío, lanzan una excepción ...! o_O
Stuart Marks
Ahora, la pregunta más interesante sería ¿qué razón en la tierra alguien podría tener para lanzar en un caso tan genérico, o qué hace que el caso sea tan especial para justificar el lanzamiento?
Martin Ba

Respuestas:

29

De las dos posibilidades (es decir, devolver una nullo una colección vacía) elegiría devolver una colección vacía, ya que permite que la persona que llama omita una comprobación del valor devuelto. En lugar de escribir esto

List<Thing> theThings = fubar.Things.All();
if (theThings != null) {
    for (Thing t : theThings) {
        t.doSomething();
    }
}

ellos podrían escribir esto:

List<Thing> theThings = fubar.Things.All();
for (Thing t : theThings) {
    t.doSomething();
}

Este segundo fragmento de código es más corto y más fácil de leer, porque el nivel de anidación es más bajo en uno.

dasblinkenlight
fuente
2
Creo que también me resultaría más fácil de entender conceptualmente ya que 'el conjunto está vacío' (sin elementos). Nulo es 'no hay conjunto', que es bastante diferente. (Esto también debería cubrir cosas que son imposibilidades lógicas: el conjunto de todos los elementos que son impares que también son pares debería estar vacío, no nulo). Sinceramente, no estoy seguro de qué (lógicamente) constituiría un conjunto nulo ... (incluso si estás desnudo en una isla, tus posesiones son un conjunto vacío, no nulo)
Clockwork-Muse
@ X-Zero Pero si estás completamente desnudo, "las posesiones en la mochila" podrían devolver un conjunto nulo, ya que ni siquiera tienes una mochila contigo. Que podría ser un BackpackNotFoundException, pero sólo si es realmente inesperada. Debería ser un estado normal en, digamos, un juego de supervivencia en una isla.
Izkata
El cheque nulo adicional es lo que me ayuda a dormir por la noche.
Joel B
6

Esperaría una lista vacía. theThingsseguiría siendo un objeto, pero theThings.Counto theThings.size()volvería 0.

David Hogue
fuente
5

Problemas de diseño como ese son abordados por el patrón de objeto nulo

... En lugar de usar una referencia nula para transmitir la ausencia de un objeto (por ejemplo, un cliente inexistente), uno usa un objeto que implementa la interfaz esperada, pero cuyo cuerpo de método está vacío. La ventaja de este enfoque sobre una implementación predeterminada que funciona es que un objeto nulo es muy predecible y no tiene efectos secundarios: no hace nada.

Por ejemplo, una función puede recuperar una lista de archivos en un directorio y realizar alguna acción en cada uno. En el caso de un directorio vacío, una respuesta puede ser lanzar una excepción o devolver una referencia nula en lugar de una lista. Por lo tanto, el código que espera una lista debe verificar que de hecho tenga una antes de continuar, lo que puede complicar el diseño ...

La sugerencia particularmente aplicable en su caso (regresar Listcuando no hay Things) es:

... Al devolver un objeto nulo (es decir, una lista vacía ) en su lugar, no hay necesidad de verificar que el valor devuelto sea de hecho una lista. La función de llamada puede simplemente iterar la lista como normal, sin hacer nada. Sin embargo, todavía es posible verificar si el valor de retorno es un objeto nulo (por ejemplo, una lista vacía) y reaccionar de manera diferente si se desea.

mosquito
fuente
3

En mi humilde opinión, debe devolver un valor VACÍO. No sé acerca de C #, pero en Java tenemos esto:

  List list = Collections.EMPTY_LIST;
  Set set = Collections.EMPTY_SET;
  Map map = Collections.EMPTY_MAP;

  // For the type-safe 
  List<String> s = Collections.emptyList();
  Set<Long> l = Collections.emptySet();
  Map<Date> d = Collections.emptyMap();

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html

Marcelo Assis
fuente
1
El equivalente de C # es Enumerable.Empty<T>(), que devuelve un vacío IEnumerable<T>(ver msdn.microsoft.com/en-us/library/bb341042.aspx )
Avner Shahar-Kashtan
1
Los documentos actuales están aquí: docs.oracle.com/javase/7/docs/api/java/util/Collections.html : los documentos 1.4.2 tienen ahora alrededor de diez años.
Stuart Marks
2

Devolvería una colección vacía sobre la devolución de un valor nulo porque de esa manera puede evitar escribir una verificación nula en el código de llamada.


fuente
2

Las dos soluciones significan cosas diferentes.

Si solo hay cero de lo que está devolviendo, ¡SIEMPRE devuelve una colección vacía! Tome el caso de una lista de directorio. Si no hay archivos en el directorio, devuelve una colección de archivos vacía.

Por otro lado, si el directorio no existe, eso no es realmente apropiado. "No puedo devolver nada" significa algo completamente diferente. En ese caso, debe devolver nulo o lanzar una excepción según la situación, no solo devuelva una colección vacía como si nada estuviera mal.

Bill K
fuente
Explicación muy razonable. El resultado devuelto no debe cubrir el estado no válido, tenemos excepciones para esto.
Ivaylo Slavov