“O homem, criatura viva e criador individual, é sempre mais importante do que qualquer estabelecido estilo ou sistema.” – Bruce Lee
Olá, pessoal! Escrevo este artigo no intuito de compartilhar com
vocês o resultado de uma de minhas pesquisas: Como aplicar o Design By Contract usando os recursos do framework .NET.
O conceito DbC é usado para garantir o estado de seus objetos em
tempo de execução. Basicamente, quando construímos nossa classe usando
o conceito DbC, definimos acordos formais (o que chamamos de contratos) com quem a utiliza. Esses contratos visam garantir regras de utilização e estado, regras essas que são expressas através de pré-condições, pós-condições e invariantes.
Vamos explorar algumas situações do nosso dia a dia para fortalecer o conceito e aprender a utilizar a classe Contract que se encontra no namespace System.Diagnostics.Contracts:
Como podem ver no código abaixo, estou criando uma classe chamada Cor
que receberá no construtor uma string contendo o código hexadecimal. No
teste, desejo garantir que caso a classe Cor seja instanciada com um
parâmetro nulo, uma exceção do tipo ArgumentNullException seja lançada.
[TestMethod]<br />[ExpectedException(typeof(ArgumentNullException))]<br />public void Deve_rejeitar_parametros_nulos()<br />{<br /> var cor = new Cor(null);<br />}Para fazer o nosso teste passar, poderíamos verificar se o parâmetro é nulo usando if e
lançar a exceção, porém, quando pensamos em contratos, o que fazemos é
criar uma pré-condição de utilização da nossa classe. Para construir
pré-condições, utilizamos o método Requires da classe Contract informando qual tipo de exceção será lançada caso o contrato for quebrado. Vejam o código abaixo:
public class Cor<br />{<br /> public Cor(string pCodigoHexadecimal)<br /> {<br /> Contract.Requires<ArgumentNullException>(pCodigoHexadecimal != null);<br /> <br /> // Código que converte o hexadecimal...<br /> }<br />}Como podem ver, o código fica bem mais limpo e expressivo. Sem falar que, caso você tenha o plugin do Visual Studio
instalado, terá essas verificações de contrato em tempo de design; isso
mesmo, enquanto você cria suas classes, seu código será analisado para
verificar possíveis quebras de contrato. Vejam a imagem abaixo:

Vamos para outra situação:agora nossa classe Cor possui um
construtor que recebe as taxas de vermelho, verde e azul. Construímos
um método para adicionar tonalidades de vermelho na cor, porém, a taxa
máxima permitida de vermelho é de 255.
[TestMethod]<br />public void Deve_garantir_taxa_de_vermelho_menor_ou_igual_255()<br />{<br /> var vermelho = 200;<br /> var verde = 200;<br /> var azul = 200;<br /> var cor = new Cor(vermelho, verde, azul);<br /> <br /> try<br /> {<br /> cor.AdicionarVermelho(56);<br /> }<br /> catch<br /> {<br /> // O método deve lançar a exceção pois 200 + 56 ultrapassa o limite de 255.<br /> Assert.AreEqual(vermelho + 56, cor.Vermelho);<br /> }<br />}Para garantir o limite da taxa de vermelho no nosso objeto,
precisamos que o nosso método seja executado para então verificar o
estado. Em DbC, podemos criar uma pós-condição para avaliar o estado do
nosso objeto ao final da execução do nosso método/propriedade. No
exemplo abaixo, usamos o método Ensures para criar a pós-condição que verifica a taxa de vermelho do nosso objeto após a execução do nosso método. Os contratos sempre são definidos no início dos métodos/propriedades.
public class Cor<br />{<br /> public int Vermelho { get; private set; }<br /> <br /> public Cor(int pVermelho, int pVerde, int pAzul)<br /> {<br /> this.Vermelho = pVermelho;<br /> // Configurar as outras propriedades...<br /> }<br /> <br /> public void AdicionarVermelho(int pValor)<br /> {<br /><br />// Aqui estamos garantindo que ao final da execução desse método, a<br />propriedade Vermelho deverá respeitar o limite de 255;<br /> Contract.Ensures(this.Vermelho <= 255);<br /> <br /> this.Vermelho += pValor;<br /> }<br />}As pós-condições são tão simples de serem escritas quanto as pré-condições.
Outra forma de garantir o nosso limite de 255 é criar um contrato
invariante, ou seja, uma regra que será mantida sempre, independentemente de
quais métodos forem executados no objeto. Para criamos o contrato
invariante no .net, usamos o método Invariant da classe Contract.
Métodos invariantes são verificados sempre após a execução de qualquer
método público da sua classe, eles só devem ter declarações de
contratos e não podem retornar valores.
[ContractInvariantMethod]<br />private void Invariant()<br />{<br /> Contract.Invariant(this.Vermelho <= 255);<br />}Como vimos, DbC é uma abordagem muito interessante e pode nos
auxiliar muito no dia-a-dia. O objetivo desse post não é apresentar bons
padrões para design de testes ou grandes soluções no trabalho com
cores, os exemplos aqui mostrados visam apenas apresentar alguns
recursos da classe Contract. Façam os devidos testes e contem o que
acharam do recurso e dessa abordagem.
Separei alguns links interessantes sobre o assunto no delicious, veja no link: delicious.com/denisferrari/DbC.
Fico no aguardo do feedback de vocês.
Abraços!







