MentaContainer: IoC simples e rápido

[quote=magnomp]Algum motivo em especial para preferir via setter?

Digo isso por que eu implementei um container de DI para Delphi onde suporto apenas injeção pelo construtor (o projeto é novo… eventualmente posso implementar isso), e queria saber quais as vantagens de fazer injeção pelo setter.

Inicialmente eu suportava injeção diretamente nos campos do objeto (ou seja, sem passar pelo construtor nem pelos setters), mas depois descartei isso pois vi que era furada trabalhar assim[/quote]

Tanto faz injetar por setter ou por construtor. Ambos tem vantagens e desvantagens. O MentaContainer suporta ambos. Agora wiring por construtor é esquisito pelo motivo acima. Eu particularmente prefiro por setter.

O Mentawai suportava injection direto em campo privado, mas no MentaContainer tirei isso, pois é muita mágica. Se uma propriedade pode ser setada externamente ela precisa declarar um setter e ser uma boa cidadã.

O mais comum é fazer injection por setter mesmo. É o que eu vejo por aí.

[quote=magnomp]O que seria o wiring a que você se refere? Seria outro termo para injeção?

[/quote]

AutoWiring = Tudo pode depender de tudo, e quando o container retorna um bean ele já retorna ele populado / preenchido com outros beans. Exemplo: Container está configurado para prover Connection e MyDAO. MyDAO depende de connection. Quando vc pede o MyDAO ele te retorna uma instancia de MyDAO com uma Connection dentro, que ele tb procura (a connection) no container. Faz isso automaticamente (por nome e type), daí auto-wiring.

Agora DI é simplesmente inversão de controle, ou seja, o container é que tem o controle para criar e injetar as instancias ao invés do objeto que depende dela fazer um new. É o desacoplamento total. Vc pode fazer isso via construtor ou setting. É parecido mais diferente de auto-wiring.

É claro que se vc entendeu DI vai entender também que todo DI deve acontecer numa campo de tipo INTERFACE.

Pelo que eu entendi, você considera que em DI o container instancia a classe e retorna para você, mas sem considerar as dependencias da mesma.
Já no wiring, o container instancia a classe e ainda provê todas as dependencias que ela pode precisar.

É isso?

Se sim, então acho que não faz sentido chamar de DI. O container não injeta nada, só cria e retorna para alguem (e esse alguem sim, poderá injetar em algum lugar). No Emballo (o projeto que citei), faço esse wiring via construtor sem problemas. No GIN (Google Guice adaptado para o GWT) idem.

Se eu lhe entendi errado, peço que desconsidere o paragrafo acima

[quote=magnomp]Pelo que eu entendi, você considera que em DI o container instancia a classe e retorna para você, mas sem considerar as dependencias da mesma.
Já no wiring, o container instancia a classe e ainda provê todas as dependencias que ela pode precisar.

É isso?

Se sim, então acho que não faz sentido chamar de DI. O container não injeta nada, só cria e retorna para alguem (e esse alguem sim, poderá injetar em algum lugar). No Emballo (o projeto que citei), faço esse wiring via construtor sem problemas. No GIN (Google Guice adaptado para o GWT) idem.

Se eu lhe entendi errado, peço que desconsidere o paragrafo acima[/quote]

Entendeu certo. :slight_smile:

Realmente temos IoC, DI e Wiring. Isso que descrevi é IoC e Wiring. A parte de DI é o método Container.populate(Object). O MentaContainer suporta as 3 coisas. Faz injeção, wiring e instanciamento de beans (IoC).

Acho que não faz muito sentido falar de IoC sem DI e vice-versa. Um meio que complementa o outro.

A boa prática geral diz que injeção por construtor é bem mais elegante que por setter. Além de gerar menos código, exibe melhor a relação de dependência e não permite que o objeto esteja em estado inconsistente. É o que o pessoal chama do Good Citizen Pattern.

Aliás, achei curioso você citar uns posts aí pra cima o padrão do bom cidadão com setters. É justamente o contrário.

[quote=Sergio Lopes]A boa prática geral diz que injeção por construtor é bem mais elegante que por setter. Além de gerar menos código, exibe melhor a relação de dependência e não permite que o objeto esteja em estado inconsistente. É o que o pessoal chama do Good Citizen Pattern.
[/quote]

Eu prefiro por setter. Há vantagens e desvantagens de usar construtores versus setters.

[quote]
Aliás, achei curioso você citar uns posts aí pra cima o padrão do bom cidadão com setters. É justamente o contrário.[/quote]

Estava falando de injetar em campo privado (sem setter ou construtor) e não em usar setter ou construtor.

Como já falei, tambem prefiro injeção pelo construtor.
Se um objeto MyDao PRECISA de um objeto Connection pra funcionar, não tem por que essa dependencia não ser passada no construtor.

Quando está escrevendo testes de unidade, é muito facil esquecer de chamar um setter para colocar uma dependencia. Já se for no construtor, você nem conseguiria compilar o código.

Ou então se esquecer de configurar a dependencia no container, ele vai simplesmente te entregar o objeto em um estado inconsistente. Se fosse no construtor, o container não conseguiria instanciar o objeto e iria ocorrer uma exceção

parabens pela criação… parece ser bem interessante, mesmo

[quote=saoj][quote=Sergio Lopes]A boa prática geral diz que injeção por construtor é bem mais elegante que por setter. Além de gerar menos código, exibe melhor a relação de dependência e não permite que o objeto esteja em estado inconsistente. É o que o pessoal chama do Good Citizen Pattern.
[/quote]
Eu prefiro por setter. Há vantagens e desvantagens de usar construtores versus setters.
[/quote]

oi saoj,

acho q ele ta querendo dizer q quando objetos são criados eles devem estar prontos para o uso.
quando ocorre a injeção por setter vc tem uma instancia inconsistente, que na verdade é corrigida posteriormente via setter.

[]s,
bob

Usar apenas ioc, faço na "unha"mesmo. Spring vai além do ioc, por isso o considero muito bom, quando não preciso usar EJB (e quase nunca se precisa mesmo).

[quote=Sergio Lopes]A boa prática geral diz que injeção por construtor é bem mais elegante que por setter. Além de gerar menos código, exibe melhor a relação de dependência e não permite que o objeto esteja em estado inconsistente. É o que o pessoal chama do Good Citizen Pattern.

Aliás, achei curioso você citar uns posts aí pra cima o padrão do bom cidadão com setters. É justamente o contrário.[/quote]

Interessante Sergio,

no entanto gostaria de dar um voto positivo ao saoj, pois eu também já li algumas referências que diziam que haviam mais vantagens em se usar os setters. Confesso que não lembro as referências, só lembro que me convenceu.

Vocês podem achar doido, mas o tipo de injeção que eu mais gosto não é nem construtor e nem setter. Curto criar pequenas API`s que buscam o que eu quero dentro do container de DI. Assim não uso nem setter, nem construtor… e ainda fico livre para buscar uma dependência dentro de um método estático das minhas classes. Acho que assim consigo fazer um código mais limpo e aproveitar de forma mais inteligente os métodos estáticos dos meus objetos. Doidera, né? :stuck_out_tongue:

saoj, já pensou em usar uma abordagem parecida com a do EJB 3, em que as annotations podem ser sobrescritas por XML? E além disso, com EJB 3 você pode manter uma parte da configuração em annotation e outra parte em XML, mesmo para um único POJO. Eu gosto muito dessa abordagem por dar opções ao desenvolvedor e atenuar consideravelmente(ou até eliminar) o problema do full redeploy…

Ou seja, tu faz um second level de IoC! Hahahahaha! Isso que é ser fascinado por baixo acoplamento!

Documentação para a versão 0.9.4, com novas funcionalidades como escopo THREAD, clearable components, etc.

http://forum.seducaotecnologica.com.br/posts/list/5.page