Estoy desarrollando una biblioteca destinada al lanzamiento público. Contiene varios métodos para operar con conjuntos de objetos: generar, inspeccionar, particionar y proyectar los conjuntos en nuevas formas. En caso de que sea relevante, es una biblioteca de clase C # que contiene extensiones de estilo LINQ en IEnumerable
, que se lanzará como un paquete NuGet.
Algunos de los métodos en esta biblioteca pueden recibir parámetros de entrada no satisfactorios. Por ejemplo, en los métodos combinatorios, hay un método para generar todos los conjuntos de elementos n que se pueden construir a partir de un conjunto de origen de elementos m . Por ejemplo, dado el conjunto:
1, 2, 3, 4, 5
y pedir combinaciones de 2 produciría:
1, 2
1, 3
1, 4
etc ...
5, 3
5, 4
Ahora, obviamente, es posible pedir algo que no se puede hacer, como darle un conjunto de 3 elementos y luego pedir combinaciones de 4 elementos mientras se configura la opción que dice que solo se puede usar cada elemento una vez.
En este escenario, cada parámetro es individualmente válido:
- La colección de origen no es nula y contiene elementos
- El tamaño solicitado de las combinaciones es un entero positivo distinto de cero
- El modo solicitado (usar cada elemento solo una vez) es una opción válida
Sin embargo, el estado de los parámetros cuando se toman juntos causa problemas.
En este escenario, ¿esperaría que el método arrojara una excepción (por ejemplo, InvalidOperationException
) o devolviera una colección vacía? Cualquiera de los dos me parece válido:
- No puede producir combinaciones de elementos n a partir de un conjunto de elementos m donde n > m si solo puedes usar cada elemento una vez, por lo que esta operación puede considerarse imposible, por lo tanto,
InvalidOperationException
. - El conjunto de combinaciones de tamaño n que se pueden producir a partir de los elementos de m cuando n > m es un conjunto vacío; no se pueden producir combinaciones.
El argumento para un conjunto vacío
Mi primera preocupación es que una excepción impide el encadenamiento idiomático de los métodos del estilo LINQ cuando se trata de conjuntos de datos que pueden tener un tamaño desconocido. En otras palabras, es posible que desee hacer algo como esto:
var result = someInputSet
.CombinationsOf(4, CombinationsGenerationMode.Distinct)
.Select(combo => /* do some operation to a combination */)
.ToList();
Si su conjunto de entrada es de tamaño variable, el comportamiento de este código es impredecible. Si .CombinationsOf()
lanza una excepción cuando someInputSet
tiene menos de 4 elementos, entonces este código a veces fallará en el tiempo de ejecución sin una comprobación previa. En el ejemplo anterior, esta comprobación es trivial, pero si lo está llamando a la mitad de una cadena más larga de LINQ, esto puede resultar tedioso. Si devuelve un conjunto vacío, entonces result
estará vacío, con lo que puede estar perfectamente satisfecho.
El argumento para una excepción
Mi segunda preocupación es que devolver un conjunto vacío puede ocultar problemas: si llama a este método hasta la mitad de una cadena de LINQ y regresa silenciosamente un conjunto vacío, es posible que tenga problemas algunos pasos más adelante o se encuentre con un conjunto de resultados vacío, y puede que no sea obvio cómo sucedió, dado que definitivamente tuvo algo en el conjunto de entrada.
¿Qué esperaría usted y cuál es su argumento al respecto?