Ao analisar a entrada do usuário, geralmente é recomendável não lançar e capturar exceções, mas usar métodos de validação. No .NET BCL, essa seria a diferença entre, por exemplo, int.Parse
(lança uma exceção em dados inválidos) e int.TryParse
(retorna false
em dados inválidos).
Estou projetando meu próprio
Foo.TryParse(string s, out Foo result)
método e não tenho certeza sobre o valor de retorno. Eu poderia usar bool
como o próprio TryParse
método do .NET , mas isso não daria nenhuma indicação sobre o tipo de erro, sobre o motivo exato pelo qual s
não poderia ser analisado em um arquivo Foo
. (Por exemplo, s
pode ter parênteses sem correspondência, ou o número errado de caracteres, ou um Bar
sem um correspondente Baz
, etc.)
Como usuário de APIs, não gosto de métodos que retornam um booleano de êxito / falha sem me dizer por que a operação falhou. Isso torna a depuração um jogo de adivinhação, e também não quero impor isso aos clientes da minha biblioteca.
Posso pensar em várias soluções alternativas para esse problema (retornar códigos de status, retornar uma string de erro, adicionar uma string de erro como um parâmetro out), mas todas elas têm suas respectivas desvantagens e também quero permanecer consistente com as convenções de o .NET Framework .
Assim, minha pergunta é a seguinte:
Existem métodos no .NET Framework que (a) analisam a entrada sem gerar exceções e (b) ainda retornam informações de erro mais detalhadas do que um simples booleano verdadeiro / falso?
fonte
Parse()
.Respostas:
Eu recomendaria usar o padrão de mônada para o seu tipo de retorno.
ParseResult<Foo> foo = FooParser.Parse("input");
Observe também que não deve ser responsabilidade do Foo descobrir como deve ser analisado a partir da entrada do usuário, pois isso vincula diretamente a camada do domínio à camada da interface do usuário e também viola o principal de responsabilidade única.
Você também pode criar uma classe de resultado de análise específica, em
Foo
vez de usar genéricos, dependendo do seu caso de uso.Uma classe de resultado de análise específica foo pode ser algo como isto:
Aqui está a versão do Monad:
Não conheço nenhum método na estrutura .net que retorne informações detalhadas sobre erros de análise.
fonte
Foo.ToString
eFoo.Parse
.Func<T>
atenderia a esse critério, se você incluirT
as informações necessárias. O retorno de informações detalhadas sobre erros depende muito de você. Você já pensou em usar umMaybe<T>
? Veja mikhail.io/2016/01/01/monads-explained-in-csharpVocê pode ver o ModelState na estrutura MVC. Representa uma tentativa de análise de alguma entrada e pode ter uma coleção de erros.
Dito isto, não acho que exista um padrão recorrente para isso no .net BCL, já que as exceções são - para melhor ou pior - o padrão estabelecido para relatar condições de erro no .net. Eu acho que você deve seguir em frente e implementar sua própria solução adequada ao seu problema, por exemplo, uma
ParseResult
classe com duas subclassesSuccessfulParse
eFailedParse
, ondeSuccessfulParse
possui uma propriedade com o valor analisado eFailedParse
possui uma propriedade de mensagem de erro. Combinar isso com a correspondência de padrões no C # 7 pode ser bastante elegante.fonte
Eu tive problemas semelhantes ao querer usar um
TryParse/Convert/etc.
método em que às vezes preciso saber como e por que ele falhou.Acabei me inspirando em como alguns serializadores lidam com erros e usam eventos. Dessa forma, a sintaxe do meu
TryX(..., out T)
método parece tão limpa quanto qualquer outra e retorna com segurança um simplesfalse
como o padrão implica.No entanto, quando eu quero precisar de mais detalhes, basta adicionar um manipulador de eventos e obter os resultados necessários em um pacote tão complexo ou simples quanto eu desejar (a
MyEventArgs
seguir). Adicione-o a uma lista de strings, adicioneExceptionDispatchInfo
e capture Exceptions; deixe o interlocutor decidir se e como deseja lidar com algo que der errado.fonte