Eu já vi vários recomendar o uso de contêineres IoC no código. A motivação é simples. Pegue o seguinte código injetado de dependência:
class UnitUnderTest
{
std::auto_ptr<Dependency> d_;
public:
UnitUnderTest(
std::auto_ptr<Dependency> d = std::auto_ptr<Dependency>(new ConcreteDependency)
) : d_(d)
{
}
};
TEST(UnitUnderTest, Example)
{
std::auto_ptr<Dependency> dep(new MockDependency);
UnitUnderTest uut(dep);
//Test here
}
Para dentro:
class UnitUnderTest
{
std::auto_ptr<Dependency> d_;
public:
UnitUnderTest()
{
d_.reset(static_cast<Dependency *>(IocContainer::Get("Dependency")));
}
};
TEST(UnitUnderTest, Example)
{
UnitUnderTest uut;
//Test here
}
//Config for IOC container normally
<Dependency>ConcreteDependency</Dependency>
//Config for IOC container for testing
<Dependency>MockDependency</Dependency>
(O exemplo acima é hipotético em C ++, é claro)
Embora eu concorde que isso simplifique a interface da classe removendo o parâmetro construtor de dependência, acho que a cura é pior que a doença por alguns motivos. Primeiro, e este é um grande problema para mim, isso torna seu programa dependente de um arquivo de configuração externo. Se você precisar de implantação binária única, simplesmente não poderá usar esses tipos de contêineres. A segunda questão é que a API agora está fraca e pior, tipicamente estrita . A evidência (neste exemplo hipotético) é o argumento de string para o contêiner de IoC e o elenco no resultado.
Então .. existem outros benefícios do uso desses tipos de contêineres ou apenas discordo dos que os recomendam?
fonte
Respostas:
Em uma aplicação grande com muitas camadas e muitas partes móveis, são os inconvenientes que começam a parecer bem menores em comparação com as vantagens.
O contêiner "simplifica a interface" da classe, mas o faz de uma maneira muito importante. O contêiner é uma solução para o problema que a injeção de dependência cria, que é a necessidade de transmitir dependências por todo o lugar, através de gráficos de objetos e em áreas funcionais. Você tem um pequeno exemplo aqui que tem uma dependência - e se esse objeto tivesse três dependências e os objetos que dependessem dele tivessem vários objetos que dependessem deles , e assim por diante? Sem um contêiner, os objetos na parte superior dessas cadeias de dependência acabam se tornando responsáveis por acompanhar todas as dependências em todo o aplicativo.
Existem diferentes tipos de contêineres também. Nem todos eles são digitados de forma estrita e nem todos exigem arquivos de configuração.
fonte
A estrutura do Guice IoC do Java não depende de um arquivo de configuração, mas do código de configuração . Isso significa que a configuração é um código diferente do código que compõe seu aplicativo real e pode ser refatorada etc.
Acredito que o Guice é o framework Java IoC que finalmente acertou na configuração.
fonte
Essa ótima resposta do SO de Ben Scheirman detalha alguns exemplos de código em C #; algumas vantagens dos contêineres IoC (DI) sendo:
fonte