segunda-feira, 21 de janeiro de 2013

ArgumentNullExceptions com Expressions

Introdução

Quando escrevemos código reaproveitável, criamos funções e/ou classes que recebem parâmetros. Na maioria das vezes esses parâmetros são fundamentais na implementação da lógica dentro de uma classe ou método, e o programador mais experiente irá, de forma defensiva, verificar se um determinado parâmetro recebido é válido antes de prosseguir com a lógica, e caso contrário, informar ao cliente (que está consumido o código) do erro cometido com a exceção correta.

Exemplo fictício

Vamos supor que temos uma classe chamada Formulario. Essa classe, quando instanciada, recebe em seu construtor uma instância de outra classe chamada Registro, que representa um registro no banco de dados, veja o código abaixo:


Note que o formulário recebe um registro, e quando o usuário clicar no botão Gravar, o registro por si mesmo irá ser persistido no banco de dados. Para consumir esse código, basta fazer a seguinte chamada:

Até aí tudo bem, mas a linguagem permite que façamos o seguinte código, sem erros de compilação:

O erro só será visto em tempo de execução, pois quando o usuário clicar em Gravar, o valor de "registro" é nulo e consequentemente o .NET irá lançar uma exceção não tratada e a aplicação provavelmente irá parar de funcionar.

Adicionando ArgumentNullException

É uma boa prática verificar se um parâmetro é nulo antes de sair consumindo o valor passado por referência.
Desta maneira, destacamos a importância do valor do parâmetro na classe, e que sem um valor válido, lançaremos uma exception informando o nome do argumento inválido. Vale ressaltar que classe ArgumentNullException recebe uma string que representa o nome do argumento que estamos tratando e esse valor deve ser passado de forma correta. Assim, se o cliente que estiver consumindo esse código tratar a excessão dentro de um bloco Try/Catch, ele terá essa informação de forma precisa.

Evitando código tedioso

Imagine agora um método e que contenha 4 parâmetros, todos eles obrigatórios. Teríamos o trabalho tedioso de escrever 4 vezes a mesma expressão, além do trabalho de digitar na mão o nome dos argumentos ao lançar a exception.
Para automatizar essa tarefa, criei uma classe chamada Requires, contendo um método chamado That, para utilizar da seguinte maneira:

O método That recebe uma Lambda Expression que representa uma função que retorna verdadeiro ou falso. Desejamos que o parâmetro "registro" não seja nulo. Caso o valor seja nulo, o método lança automaticamente para nós um ArgumentNullException com o nome do parâmetro corretamente, sem nos preocuparmos em digitar isso na mão, facilitando a nossa vida.
A classe requires ficou conforme o código abaixo:

Outro exemplo com Extension Method

Extension Methods recebem pelo menos um parâmetro (this), e devemos verificar se possuem valores. É muito fácil passar valores nulos para ExtensionMethods, basta fazer um Cast implícito.

No exemplo abaixo, possuímos uma classe Cliente que implementa a interface IEntidade.

Como no caso anterior, podemos facilmente escrever um programa que consome essas classes chamando o extension method criado:
No ExtensionMethod "AlteraEstado", não verificamos se passamos um valor nulo (entidade). Se escrevermos o seguinte código, a aplicação compilará normalmente, e só veremos o problema em tempo de execução, pois o cast que foi feito retornará nulo:
O Extension Method AlteraEstado deve ser modificado para ficar assim:
Dessa forma o programador será informado corretamente sobre um erro de argumento nulo, e terá oportunidade de fazer correções antes de entregar ao cliente. =)

Nenhum comentário:

Postar um comentário