Estoy desarrollando una biblioteca destinada al lanzamiento público. Contiene varios métodos para operar en 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 IEnumerable
, que se lanzará como un paquete NuGet.
Algunos de los métodos en esta biblioteca pueden recibir parámetros de entrada insatisfactorios. Por ejemplo, en los métodos combinatorios, hay un método para generar todos los conjuntos de n elementos que se pueden construir a partir de un conjunto fuente de m elementos. 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 configura la opción que dice que solo puede usar cada elemento una vez.
En este escenario, cada parámetro es válido individualmente :
- 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 (use 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 arroje una excepción (por ejemplo InvalidOperationException
) o devuelva una colección vacía? Cualquiera de los dos me parece válido:
- No puede producir combinaciones de n elementos a partir de un conjunto de m elementos donde n> m si solo se le permite usar cada elemento una vez, por lo tanto, esta operación puede considerarse imposible
InvalidOperationException
. - El conjunto de combinaciones de tamaño n que se pueden producir a partir de m elementos 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 evita el encadenamiento idiomático de métodos al 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()
arroja una excepción cuando someInputSet
tiene menos de 4 elementos, este código a veces fallará en tiempo de ejecución sin alguna verificación previa. En el ejemplo anterior, esta comprobación es trivial, pero si la está llamando a la mitad de una cadena más larga de LINQ, esto puede ser 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 está llamando a este método a la mitad de una cadena de LINQ y devuelve silenciosamente un conjunto vacío, entonces puede tener problemas algunos pasos más tarde o encontrarse con un vacío conjunto de resultados, y puede no ser obvio cómo sucedió eso dado que definitivamente tenía algo en el conjunto de entrada.
¿Qué esperarías y cuál es tu argumento?