Eu entendo os benefícios da injeção de dependência em si. Vamos pegar o Spring, por exemplo. Também entendo os benefícios de outros recursos do Spring, como AOP, auxiliares de diferentes tipos, etc. Estou apenas me perguntando quais são os benefícios da configuração XML, como:
<bean id="Mary" class="foo.bar.Female">
<property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
<property name="girlfriend" ref="Mary"/>
</bean>
em comparação com o código Java simples, como:
Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);
que é mais fácil de depurar, verificar o tempo de compilação e pode ser entendido por qualquer pessoa que conheça apenas java. Então, qual é o objetivo principal de uma estrutura de injeção de dependência? (ou um pedaço de código que mostra seus benefícios.)
ATUALIZAÇÃO:
Em caso de
IService myService;// ...
public void doSomething() {
myService.fetchData();
}
Como o framework IoC pode adivinhar qual implementação de myService eu desejo que seja injetada, se houver mais de uma? Se houver apenas uma implementação de determinada interface e eu permitir que o contêiner IoC decida automaticamente por usá-la, ela será quebrada após o aparecimento de uma segunda implementação. E se houver intencionalmente apenas uma implementação possível de uma interface, você não precisa injetá-la.
Seria realmente interessante ver um pequeno pedaço de configuração para IoC que mostra seus benefícios. Eu uso o Spring há algum tempo e não posso fornecer esse exemplo. E posso mostrar linhas únicas que demonstram os benefícios do hibernate, dwr e outros frameworks que eu uso.
ATUALIZAÇÃO 2:
Eu percebo que a configuração IoC pode ser alterada sem recompilar. É realmente uma boa ideia? Posso entender quando alguém deseja alterar as credenciais do banco de dados sem recompilar - ele pode não ser desenvolvedor. Em sua prática, com que frequência outra pessoa que não seja o desenvolvedor altera a configuração do IoC? Acho que para os desenvolvedores não há esforço para recompilar essa classe em particular em vez de alterar a configuração. E para quem não é desenvolvedor, você provavelmente gostaria de tornar sua vida mais fácil e fornecer algum arquivo de configuração mais simples.
ATUALIZAÇÃO 3:
Configuração externa de mapeamento entre interfaces e suas implementações concretas
O que há de tão bom em torná-lo extenso? Você não torna todo o seu código externo, embora definitivamente possa - apenas coloque-o no arquivo ClassName.java.txt, leia e compile manualmente em tempo real - uau, você evitou a recompilação. Por que a compilação deve ser evitada ?!
Você economiza tempo de codificação porque fornece mapeamentos declarativamente, não em um código procedural
Eu entendo que às vezes a abordagem declarativa economiza tempo. Por exemplo, declaro apenas uma vez que um mapeamento entre uma propriedade de bean e uma coluna DB e o hibernate usa esse mapeamento ao carregar, salvar, construir SQL baseado em HSQL, etc. É aqui que funciona a abordagem declarativa. No caso do Spring (no meu exemplo), a declaração tinha mais linhas e tinha a mesma expressividade do código correspondente. Se houver um exemplo em que tal declaração seja mais curta do que o código - eu gostaria de ver.
O princípio de inversão de controle permite fácil teste de unidade porque você pode substituir implementações reais por falsas (como substituir o banco de dados SQL por um na memória)
Eu entendo os benefícios da inversão de controle (prefiro chamar o padrão de design discutido aqui como Injeção de Dependência, porque IoC é mais geral - existem muitos tipos de controle, e estamos invertendo apenas um deles - controle de inicialização). Eu estava perguntando por que alguém precisa de algo diferente de uma linguagem de programação para isso. Definitivamente, posso substituir implementações reais por falsas usando código. E esse código expressará a mesma coisa que configuração - ele apenas inicializará campos com valores falsos.
mary = new FakeFemale();
Eu entendo os benefícios do DI. Não entendo quais benefícios são adicionados pela configuração XML externa em comparação com a configuração de código que faz o mesmo. Não acho que a compilação deva ser evitada - eu compilo todos os dias e ainda estou vivo. Acho que a configuração do DI é um mau exemplo de abordagem declarativa. A declaração pode ser útil se for declarada uma vez E é usada muitas vezes de maneiras diferentes - como hibernate cfg, onde o mapeamento entre a propriedade do bean e a coluna DB é usado para salvar, carregar, construir consultas de pesquisa, etc. A configuração do Spring DI pode ser facilmente traduzida para configurando código, como no começo dessa pergunta, não pode? E é usado apenas para inicialização do bean, não é? O que significa que uma abordagem declarativa não acrescenta nada aqui, certo?
Quando declaro o mapeamento do hibernate, apenas dou algumas informações ao hibernate e ele funciona com base nelas - não digo a ele o que fazer. No caso de spring, minha declaração diz a spring exatamente o que fazer - então por que declarar, por que não simplesmente fazer?
ÚLTIMA ATUALIZAÇÃO:
Pessoal, muitas respostas estão me falando sobre injeção de dependência, o que SEI QUE É BOM. A questão é sobre o propósito da configuração de DI em vez de inicializar o código - tendo a pensar que a inicialização do código é mais curta e clara. A única resposta que recebi até agora à minha pergunta, é que evita a recompilação, quando a configuração muda. Acho que devo postar outra pergunta, porque é um grande segredo para mim, por que compilar deve ser evitado neste caso.