|
Olá Pessoal! No meu primeiro post sobre Design By Contract recebi questionamentos interessantes sobre os prós e contras dessa abordagem comparando-a com a forma tradicional de validações com if…throw, logo, o objetivo deste post será evidenciar as diferenças entre essas duas abordagens. No último post lancei um desafio ao meu amigo Gustavo Badke (@guripunk) após ele ter escrito o seguinte comentário: “Pra min isso é firula, não vejo diferença nenhum do if(…) throw new Exception…“. Alguns códigos que vou apresentar aqui foram escritos por ele, então, considerem-no como uma participação especial nesse post
Pré-condições Tradicionalmente, quando precisamos verificar se os parâmetros de um método qualquer estão válidos para utilização, escrevemos algo semelhante ao código abaixo:
A abordagem acima resolve o nosso requisito de validação dos parâmetros, porém, o código utilizado para isso é extremamente “carregado” para a implementação de um requisito simples. Utilizando DbC a implementação ficaria da seguinte forma:
A abordagem acima não só resolve o nosso requisito de validação dos parâmetros, como também deixa o código mais legível e você ainda conta com a validação dos contratos em tempo de compilacão. O método Requires ainda possibilita a configuração de uma mensagem personalizada caso seja necessário. Também poderíamos usar AOP para resolver nosso problema, contudo, seria utilizar um recurso muito poderoso e complexo para uma necessidade muito simples. Se você não vai usar AOP para nenhuma outra necessidade do seu projeto, não recomendo utilizar nessa situação. Não devemos avaliar o poder do DbC analisando somente suas pré-condicões. Precisamos avaliar se todos os aspectos dessa abordagem serão realmente úteis no nosso projeto, isso inclui também as pós-condições e invariantes. Pós-condições É comum, após a execução de um método, realizar a verificação de estado da classe nos membros que foram afetados pelo mesmo. Nessa situação, usando a abordagem tradicional, faríamos uma verificação qualquer no final do corpo do método. Algo como mostra o código abaixo:
Um dos principais problemas nessa abordagem é a falta de legibilidade no método. Veja a solução usando DbC:
Quando trabalhamos com contratos, sempre inserimos os mesmos no topo dos métodos, o que facilita muito a leitura dos códigos. Mesmo com exemplos simples como esses, podemos perceber que a curva de aprendizagem é muito baixa. Invariantes Como você garantiria que um objeto estará válido sempre independente de quais e quantos métodos forem executados? Provavelmente, você precisará construir algum método de validação e chamá-lo ao final de cada método público de sua classe. Nesse ponto, percebemos uma grande diferença entre as abordagens, pois usando DbC, só precisaríamos construir o método Invariant com as validações necessárias e pronto, vejam o exemplo:
Em resumo, como disse anteriormente, é necessário analisar todos os recursos da abordagem e não somente um. Apensar das pré-condições serem facilmente substituídas por if…throw, isso não acontece da mesma forma com as invariantes. DbC não é para todos os projetos, DbC não é regra, DbC não é melhor ou pior que ninguém. Use em seus projetos quando precisar de todos os recursos que a abordagem dispõe, e mesmo assim não deixe de analisar alternativas como AOP. Abraços Pessoal!
Comentários:
1 Comentário postados em "Design By Contract (DbC) em .NET – Comparando soluções"
rodrigo on junho 11th, 2011 at 12:23 #
Ferrari Muito boa a “séria” sobre DbC. Concordo com o seu comentário a respeito de que DbC não é para todos os projetos; mas pensando em uma abordagem superficial podemos considerá-lo no mínimo como “recomendado para boa parte dos projetos” IMHO A expressividade que ganhamos com o DbC já vale o seu uso; “qualquer” classe naturalmente vai precisar de validações, checagens e afins e algum momento no seu ciclo de vida e o emaranhado de IF’s apesar de resolver acaba deixando uma gordurada danada o exemplo do construtor “Cor” com 3 parâmetros deixou isso claro! Parabéns pelo blog; muito bom! Saudações Deixe um comentário
|
|