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.
Robson, curti bastante o post.
Gosto desta abordagem mas confesso que preciso colocar mais em prática.
Nada melhor que cuidar da arquitetura na prática, escrevendo código.
Abraços!
CurtirCurtir
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
CurtirCurtir
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.
CurtirCurtir
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!
CurtirCurtir
Ótima dica Robson!
Abs
CurtirCurtir
Valeu!
[]s
CurtirCurtir