Estou desenvolvendo uma biblioteca destinada a lançamento público. Ele contém vários métodos para operar em conjuntos de objetos - gerando, inspecionando, particionando e projetando os conjuntos em novas formas. Caso seja relevante, é uma biblioteca de classes C # contendo extensões no estilo LINQ IEnumerable
, a ser lançada como um pacote NuGet.
Alguns dos métodos nesta biblioteca podem receber parâmetros de entrada insatisfatórios. Por exemplo, nos métodos combinatórios, existe um método para gerar todos os conjuntos de n itens que podem ser construídos a partir de um conjunto de origem de m itens. Por exemplo, dado o conjunto:
1, 2, 3, 4, 5
e pedir combinações de 2 produziria:
1, 2
1, 3
1, 4
etc ...
5, 3
5, 4
Agora, obviamente, é possível pedir algo que não pode ser feito, como fornecer um conjunto de 3 itens e, em seguida, solicitar combinações de 4 itens enquanto define a opção que diz que ele pode usar cada item apenas uma vez.
Nesse cenário, cada parâmetro é válido individualmente :
- A coleção de origem não é nula e contém itens
- O tamanho solicitado das combinações é um número inteiro diferente de zero positivo
- O modo solicitado (use cada item apenas uma vez) é uma opção válida
No entanto, o estado dos parâmetros, quando reunidos, causa problemas.
Nesse cenário, você esperaria que o método gerasse uma exceção (por exemplo InvalidOperationException
) ou retornasse uma coleção vazia? Qualquer um parece válido para mim:
- Você não pode produzir combinações de n itens a partir de um conjunto de m itens em que n> m se você puder usar cada item apenas uma vez, portanto, essa operação pode ser considerada impossível
InvalidOperationException
. - O conjunto de combinações de tamanho n que pode ser produzido a partir de m itens quando n> m é um conjunto vazio; nenhuma combinação pode ser produzida.
O argumento para um conjunto vazio
Minha primeira preocupação é que uma exceção evite o encadeamento idiomático de métodos no estilo LINQ quando você estiver lidando com conjuntos de dados que podem ter tamanho desconhecido. Em outras palavras, você pode fazer algo assim:
var result = someInputSet
.CombinationsOf(4, CombinationsGenerationMode.Distinct)
.Select(combo => /* do some operation to a combination */)
.ToList();
Se o seu conjunto de entradas tiver tamanho variável, o comportamento desse código é imprevisível. Se .CombinationsOf()
lança uma exceção quando someInputSet
possui menos de 4 elementos, esse código às vezes falha no tempo de execução sem pré-verificação. No exemplo acima, essa verificação é trivial, mas se você está chamando pela metade de uma cadeia mais longa de LINQ, isso pode ser entediante. Se retornar um conjunto vazio, ele result
estará vazio, com o qual você poderá estar perfeitamente feliz.
O argumento para uma exceção
Minha segunda preocupação é que o retorno de um conjunto vazio possa ocultar problemas - se você estiver chamando esse método na metade de uma cadeia de LINQ e retornar silenciosamente um conjunto vazio, poderá encontrar alguns problemas mais tarde ou encontrar um vazio. conjunto de resultados e pode não ser óbvio como isso aconteceu, pois você definitivamente tinha algo no conjunto de entradas.
O que você esperaria e qual é o seu argumento para isso?