Design by Contract com .Net

Não faz muito tempo que os interessados em utilizar DbC em .Net teriam que apelar para Spec# ou criar implementações customizadas (vide “Outras referências externas’) para conseguir algo similar ao modelo DbC original.

Similar pois muitas vezes uma das principais características do modelo iniciado em 1985 pela linguagem Eiffel não era adequadamente implementada.  Me refiro ao fato de que em grande parte das implementações, principalmente as caseiras, os processos de assertion continuam vigorando e sendo executados em códigos enviados para produção, o que certamente consome uma grande quantidade de recurso desnecessáriamente.

O modelo utilizado e documentado pela própria Eiffel recomenda manter ativas apenas as pré-condições e, em casos onde a performance é crucial, pode-se inclusive desabilitar completamente a verificação dos asserts, leia:

…When releasing the final version of a system, it is usually appropriate to turn off assertion monitoring, or bring it down to the require level. The exact policy depends on the circumstances; it is a trade off between efficiency considerations, the potential cost of mistakes, and how much the developers and quality assurance team trust the product. When developing the software, however, you should always assume — to avoid loosening your guard — that in the end monitoring will be turned off...” – Runtime assertion monitoring

Além, claro da linguagem Eiffel, poderiamos tomar como exemplo esta implementação DbC em Pearl, onde (quotando a referência oficial disponível no site do projeto):

An additional capacity that is often provided in design-by-contract systems is the ability to selectively disable checking in production code. This allows the contractual testing to be carried out during implementation, without impinging on the performance of the final system“.

No caso da plataforma .Net, a falecida Spec# cumpria este papel de forma grandiosa ao integrar a opção de avaliar ou não os asserts diretamente nas opções do projeto exibidas pelo Visual Studio.

Code Contracts

Pode-se dizer que a implementação Code Contracts é a continuação do Spec#. Ela está disponível para a plataforma .Net com integração tanto para Visual Studio 2008 quanto para o 2010 Beta e mantém a qualidade da implementação e da integração com o VS iniciada no Spec#. Para os não iniciados no paradigma, quando algo similar ao que se vê na imagem abaixo acontecer em tempo de compilação, pode-se facilmente pensar em forças sobrenaturais agindo:

Mensagens do Code Contracs

Trocando em miúdos

Baseado em opções definidas para o projeto (vide imagem “Opções no VisualStudio“), seu código e seus respectivos contratos (ou a falta deles) poderão ser avaliados em tempo de compilação ou de execução, o que quer dizer que o Visual Studio poderá te avisar de eventuais problemas relacionados ou não com quebras dos contratos definidos em sua aplicação. Explico isto mais pra frente…

Opções no VisualStudio

Ainda não tenho os números indicando eventuais perdas de performance durante a execução de um código que faça uso do Code Contracts, o que faz com que a possibilidade de desabilitar a verificação dos contratos para publicação em produção seja algo ainda mais crítico. É fato porém, que por motivos óbvios o tempo de compilação sofre impacto com a habilitação das opções disponíveis para “Static Checking“. Este é o recurso responsável pela bruxaria de te avisar dos eventuais problemas que seu código pode encontrar quando executado inadequadamente enquanto o mesmo é compilado.

Dentre as opções de verificação estática encontram-se duas que achei muito foda, são elas “Implicit Arithmetic Obligations” e “Implicit Array Bounds Obligations” que verificam respectivamente: possíveis estouros no limite de arrays e eventuais problemas na execução de rotinas aritméticas (não necessáriamente atreladas à um contrato). Trocando em miúdos: habilitando estas opções você praticamente dá adeus àquela famosa mensagem  de erro de “array out of bounds” e evita que o universo entre em colapso quando alguém tentar dividir por zero.

Na prática

Pra ficar mais fácil, vou colocar em forma de lista numerada os passos para gerar seu primeiro erro no CC:

  1. Instale o Code Contracts
  2. Crie uma nova Console Application no Visual Studio 2008
  3. Na janela Solution Explorer (ctrl W, S), clique com o botão direto sobre References, em seguida Add Reference, e na aba .Net, escolha Microsoft.Contracts
  4. Cole o seguinte código na classe “Program.cs” gerada pelo VS
    using System;
    using System.Diagnostics.Contracts;
    namespace ConsoleApplication1
    {
        class Divide
        {
            int _i;
            public Divide(int i)
            {
                /// Como quero que uma lista de erros seja exibida, não definiremos adequadamente os contratos
                /// e deixaremos o Code Contracts nos guiar neste processo... Porém,  por conta de um "BUG" do
                /// componente, para que seja possível utilizar "Static Checking" você deve ter ao menos uma
                /// ocorrência de contrato:
                /// http://social.msdn.microsoft.com/Forums/en/codecontracts/thread/aba1e662-9e5f-44ba-88bc-be204a0aaeb9
                Contract.Requires(i > 0);
                this._i = i;
            }
            public int Por(int strangelet) { return this._i / strangelet; }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine(new Divide(1).Por(0));
            }
        }
    }
    
  5. Clique com o botão direto sobre o ícone do projeto na janela de Solution Explorer e em seguida, em Properties
  6. Na aba de Code Contracts, habilite a opção  Perform Static Contract Checking e o item de Implicit Arithmetic Obligations
  7. Compile o projeto e verifique a janela Error List (ctrl + W, E) e você verá algo similar à:

    Rá!

  8. Fino né?

Conclusão

No geral eu diria que Code Contracts é uma implementação muito interessante e que pode direcionar o futuro da plataforma para um paradigma não só voltado à prevenção de BUGs e sim à validação da coerência lógica do que foi programado, paradigma este, que é o coração do DbC. Ainda existem muitos pontos a serem melhorados, como por exemplo, a possibilidade de incorporar as facetas do DbC diretamente na sintaxe das linguagens nativas. Imagine como seria bom podermos descrever um contrato da seguinte forma:

public class Dividir
     /// Sintaxe especializada...
     invariant (this.Divisor != 0)
{
     public int Divisor { get; set;}
     public int Dividendo { get; set;}
     public Dividir (int divisor, int dividendo)
    {
        this.Divisor = divisor;
        this.Dividendo = dividendo;
    }
    public int ToInt()
    {
        return this.Dividendo / this.Divisor;
    }
}

Como um primeiro passo o Code Contracts se mostrou uma opção muito positiva.

Outras referências externas:

Metematico

Um comentário

  1. Pingback: Design by Contract 101–parte 2–limpando o código « Elemar DEV

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: