Garantindo a consistência de uma Interface

by Israel Aece 17. February 2011 07:07

Imagine que você possui uma interface que descreve a base para alguma funcionalidade do seu sistema. Como sabemos, a ideia de isolarmos a definição em uma interface serve para facilitar os testes, diminuir o acoplamento e melhorar a estensibilidade.

Quando construímos um tipo, muitas vezes pensamos em como garantir que ele sempre fique em um estado consistente, para que seja utilizado pela aplicação sem qualquer problema. Mas como garantir a consistência de um tipo como uma interface? Interfaces não possuem qualquer implementação, e com isso não há como escrever qualquer código para validar parâmetros, garantia de estado, etc.

Com a criação da interface, também não temos controle de quantas implementações dela serão criadas. Deixar a responsabilidade de garantir a consistência para os implementadores, corre-se o risco de que um deles não se preocupe com isso, prejudicando o propósito para qual a interface foi criada.

A Microsoft recentemente publicou um projeto chamado Code Contracts, e que podemos utilizar uma funcionalidade dele para suavizar esse problema. Através dos atributos ContractClassForAttribute e ContractClassAttribute, conseguimos amarrar (e separar) a nossa interface à uma classe utilizada exclusivamente para validar as implementações, que analisará em runtime se as condições estão ou não sendo atentidas. Abaixo temos uma interface para um repositório de domínio, e logo em seguida, temos uma classe apenas para garantir a sua consistência.

[ContractClass(typeof(RepositoryContract))]
public interface IRepository
{
    T GetById<T>(Guid id) where T : AggregateRoot;

    void Save(AggregateRoot item);
}

[ContractClassFor(typeof(IRepository))]
internal sealed class RepositoryContract : IRepository
{
    public T GetById<T>(Guid id) where T : AggregateRoot
    {
        return default(T);
    }

    public void Save(AggregateRoot item)
    {
        Contract.Requires<ArgumentNullException>(item != null);
    }
}

Note que utilizamos o atributo ContractClassAttribute para apontar qual a classe que representa o contrato, e mais abaixo, utilizamos o atributo ContractClassForAttribute para indicarmos que a classe onde este atributo está sendo aplicado serve como contrato para a interface apontada nele. E, finalmente, um detalhe interessante é que a classe é definida como internal, evitando assim o acesso direto pelos consumidores da interface.

Tags: ,

C#

Comments

2/17/2011 7:45:36 AM #

pingback

Pingback from topsy.com

Twitter Trackbacks for
        
        Israel Aece | Garantindo a consistência de uma Interface
        [israelaece.com]
        on Topsy.com

topsy.com

2/17/2011 8:05:31 AM #

Abraão Alves

Muito bom o post!
Simples, direto e de facil entendimento.

Abraão Alves Brazil

2/24/2011 5:17:30 PM #

Eduardo Ernandes

Israel,

   não seria mais fácil utilizar uma classe abstrata? Desse modo vc poderia escrevar código na classe abastrata que verifica se o estado do objeto é valido, independente da classe concreta.

[]'s
Eduardo Ernandes
    

Eduardo Ernandes Brazil

2/28/2011 8:34:31 AM #

IsraelAece

Boas Eduardo,

Sim, e com a vantagem de não precisar da API do CodeContracts.

IsraelAece Brazil

Comments are closed

Powered by BlogEngine.NET 1.5.0.0
Theme by Mads Kristensen

Sobre

Meu nome é Israel Aece e sou especialista em tecnologias de desenvolvimento Microsoft, atuando como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. [ Mais ]

Twitter

Host