Testando acoplamento

Olá, pessoal

Muitas vezes não queremos que determinadas bibliotecas sejam referenciadas em outras de camadas diferentes. Imaginem seu projeto (class library) que contém o domain model fazendo referência ao seu projeto ASP.NET MVC ou, pior, referenciando bibliotecas de terceiros como o NHibernate.

Claro, alguns desses problemas são evitados automaticamente uma vez que não é possível criar uma referência circular em projetos .Net. No entanto, nem sempre temos essa sorte.

Uma forma de reduzir esse acoplamento indesejado e comunicar essas restrições ao time em forma de código é escrevermos testes de unidade para isso.

Suponha que tenhamos em nossa solução uma class library de nome “MeuProjeto.Infra” e outra de nome “MeuProjeto.Dominio”. Para evitar o uso de classes de “MeuProjeto.Infra” em “MeuProjeto.Dominio”, podemos escrever o seguinte teste:

[TestFixture]
public class TesteDeAcoplamento
{
    [Test]
    public void Nao_deve_utilizar_assemblies_de_infra()
    {
        var referencias = typeof(DomainObject).Assembly.GetReferencedAssemblies();

        var possuiReferencia = referencias.Any(a => a.Name.Contains("Infra"));

        Assert.False(possuiReferencia);
    }
}

O código é auto-explicativo. Primeiro, obtenho todas as referências da class library “MeuProjeto.Dominio” (que estou assumindo possuir a classe DomainObject). Em seguida, verifico se uma das referências é do projeto “indesejado” e faço a asserção contra isso.

NOTA:
Existe um detalhe “chato” no código acima. O método “GetReferencedAssemblies()” só retorna as referências que possuam código em uso dentro do assembly. Sendo assim, se nenhum código de “MeuProjeto.Infra” estiver sendo usado, mesmo com a referência presente, o método NÃO retorna a referência e o teste passará! Não é uma solução perfeita mas já impede o uso de objetos em uma class library inapropriada (e a referência pode ser retirada manualmente sem esforço).

Ao invés de dizermos no teste quais referências não queremos, podemos fazer ao contrário, deixando explícitas as referências permitidas:

[TestFixture]
public class TestesDeAcoplamento
{
    [Test]
    public void Deve_validar_referencias_permitidas()
    {
        var referenciasPermitidas = new[] { "System", "System.Core", "mscorlib" };

        var referencias = typeof(DomainObject).Assembly.GetReferencedAssemblies();

        CollectionAssert.AreEquivalent(referenciasPermitidas, referencias.Select(r => r.Name));
    }
}

Escrevendo testes como estes, deixamos explícito qual o acoplamento permitido entre as class libraries de uma solução, garantindo que a arquitetura do software evolua de forma saudável.

O que acharam?

No próximo artigo, volto com a segunda parte da série “Padrões de DI”.

Até lá!

Anúncios

6 comentários em “Testando acoplamento

    1. Valeu, Rafael!
      Tb gostei da ideia. É bem simples e, portanto, pode ir pra build rapidamente. (Embora haja ferramentas que validem o acoplamento, de forma visual inclusive).
      []s

  1. Simples e realmente criativo!

    Não vejo problemas quanto ao detalhe de não retornar a referência quando não houver usos, já que o problema seria se realmente alguém estivesse usando algo em um lugar indevido (aí o teste pegaria).

    Ficando assim uma referência completamente inofensiva, que cedo ou tarde alguém irá notar e remover.

    Boa dica, abs.

    1. Pois é, realmente não é algo grave.
      No entanto, “perfeccionistamente” falando e pensando também no deploy, é recomendado não deixar ref. inúteis para que não sejam publicadas desnecessariamente (caso estejamos publicando um binário específico).
      []s!

Participe! Vamos trocar uma ideia sobre desenvolvimento de software!

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