Esse é o terceiro artigo de uma série de artigos onde apresentarei alguns conceitos de arquitetura de software utilizados no desenvolvimento de aplicações corporativas.
Nesse artigo vamos estudar a Injeção de Dependência que também é uma aplicação do conceito de inversão de controle.
A Injeção de Dependência consiste em retirar da classe a responsabilidade de conhecer ou encontrar as suas dependências, reduzindo o acoplamento, e aumentando a flexibilidade do código. A Injeção de Dependência na maioria das vezes é realizada utilizando frameworks de inversão de controle.
Mas quando a classe não conhece suas dependências ela deve estar apta a receber essa informação de alguma forma.
Os modos mais comuns de receber essa informação são no construtor, ou em uma propriedade.
Exemplo da classe “Usuario” que permite injeção de dependência por construtor (constructor injection):
public class Usuario
{
private IEnviadorDeEmail _enviadorDeEmail;
public Usuario(IEnviadorDeEmail enviadorDeEmail)
{
this._enviadorDeEmail = enviadorDeEmail;
}
}
Exemplo da classe “Usuario” que permite injeção de dependência por propriedade (setter injection):
public class Usuario
{
public IEnviadorDeEmail EnviadorDeEmail { get; set; }
}
Um framework muito famoso que auxilia a realizar Inversão de Controle e Injeção de Dependência é o Spring.NET (http://www.springframework.net/), que é baseado nos conceitos já consolidados do Spring (versão para Java).
Todo o funcionamento do Spring baseia-se na configuração dos objetos que são utilizados na nossa aplicação, geralmente essa configuração é feita em formato XML.
Exemplo de configuração de um objeto básico no Spring.NET:
<object id="EnviadorDeEmailPadrao" type="Namespace.EnviadorDeEmailPorSMTP, AssemblyName" singleton="true" />
Todo objeto configurado no Spring.NET que deve ser exposto para a aplicação deve possuir o atributo “id”, que é o nome que você utilizará para identificar aquele objeto. Também definimos o atributo “type”, que é o nome completo (com assembly) do tipo que será utilizado na criação do objeto quando ele for requisitado. O atributo “singleton” define que o objeto pode ser reutilizado, ou seja, apenas 1 objeto será criado, e o mesmo objeto será retornado sempre que solicitado ao Spring.NET.
Quando precisamos enviar um e-mail na nossa aplicação, basta solicitarmos ao Spring o objeto pelo id, por exemplo:
//Obtemos o contexto atual da aplicação no spring
IApplicationContext ctx = ContextRegistry.GetContext();
//Solicitamos ao contexto do spring o objeto com id EnviadorDeEmail
IEnviadorDeEmail enviadorDeEmail = (IEnviadorDeEmail) ctx.getObject("EnviadorDeEmailPadrao");
Agora, veja como ficaria a configuração do Spring realizando injeção de dependência na classe “Usuario” por construtor:
<object id="EnviadorDeEmailPadrao" type="Namespace.EnviadorDeEmailPorSMTP, AssemblyName" singleton="true" />
<object id="Usuario" type="MeuNamespaceDeNegocio.Usuario, NomeDoAssemblyDeNegocio" singleton="false">
<constructor-arg name="enviadorDeEmail" ref="EnviadorDeEmailPadrao" />
</object>
E também por propriedade:
<object id="EnviadorDeEmailPadrao" type="Namespace.EnviadorDeEmailPorSMTP, AssemblyName" singleton="true" />
<object id="Usuario" type="MeuNamespaceDeNegocio.Usuario, NomeDoAssemblyDeNegocio" singleton="false">
<property name="EnviadorDeEmail" ref="EnviadorDeEmailPadrao" />
</object>
Nesses exemplos, configuramos um objeto com id “EnviadorDeEmailPadrao”, que é responsável pelo envio de e-mail, e também configuramos o objeto “Usuario”, que é nossa classe de negócio da entidade Usuário. Mas ao configurar o objeto “Usuario”, através dos nós “constructor-arg” ou “property”, definimos que o objeto “EnviadorDeEmailPadrao” deve ser passado ao objeto “Usuario” no construtor, ou através da propriedade. Realizando assim, a injeção de dependência.
Agora, sempre que precisarmos instanciar um objeto da classe “Usuario”, pedimos ao Spring o objeto, conforme o código abaixo:
//Solicitamos ao contexto do spring o objeto com id Usuario
Usuario usuario = (Usuario) ContextRegistry.GetContext().getObject("Usuario");
E o objeto retornado já estará com as suas dependências preenchidas.
Embora o exemplo não tenha utilizado, é recomendável a criação de uma classe para encapsular a obtenção dos objetos do contexto do Spring.NET, desse modo, estaremos acoplando apenas uma classe do nosso projeto ao Spring, o que tornará mais fácil a migração para outro framework de injeção de dependência.
Quando precisarmos alterar nosso sistema para enviar e-mail utilizando SQL Server, podemos alterar a configuração do Spring para algo semelhante a:
<object id="EnviadorDeEmailPadrao" type="Namespace.EnviadorDeEmailPorSQLServer, AssemblyName" singleton="true" />
<object id="Usuario" type="MeuNamespaceDeNegocio.Usuario, NomeDoAssemblyDeNegocio" singleton="false">
<property name="EnviadorDeEmail" ref="EnviadorDeEmailPadrao" />
</object>
Ou imagine que você queira parametrizar a classe “EnviadorDeEmailPorSMTP”, com as propriedades “Servidor”, “Porta”, “Usuario” e “Senha”. Após criarmos as propriedades, podemos alterar a configuração do Spring para:
<object id="EnviadorDeEmailPadrao" type="Namespace.EnviadorDeEmailPorSQLServer, AssemblyName" singleton="true">
<property name="Servidor" value="192.168.0.10" />
<property name="Porta" value="25" />
<property name="Usuario" value="aplicacao1" />
<property name="Senha" value="123456" />
</object>
<object id="Usuario" type="MeuNamespaceDeNegocio.Usuario, NomeDoAssemblyDeNegocio" singleton="false">
<property name="EnviadorDeEmail" ref="EnviadorDeEmailPadrao" />
</object>
Isso é apenas o início das possibilidades do Spring.NET, mas essas simples funcionalidades podem ajudar enormemente na configuração da aplicação e no desacoplamento.
0 comentários:
Postar um comentário