como o spring me ajudou a manter o active record
Nesse primeiro post vou falar um pouco sobre meu novo trabalho. Na verdade, sobre um problema que encontramos lá.
Dentre diversas coisas que estamos fazendo, como migrações por exemplo, estou ajudando na elaboração da arquitetura que irá abrigar as novas aplicações desenvolvidas na empresa.
É uma tarefa desgastante e cada decisão é crÃtica, indo de discussões sobre qual tecnologia usar para MVC até como organizar o layering da aplicação. Essa arquitetura compreende também o desenvolvimento de um framework para facilitar a vida dos novos desenvolvedores que integrarão a equipe.
Pois bem, uma das decisões que tomei foi a de evitar o Anemic Domain Model e usar o Spring como framework de IoC. Os benefÃcios disso são assunto para outro post. ;) E um outro padrão que ajuda nisso se chama Active Record. Aà começaram os problemas! Essa divisão de responsabilidades sempre agrega uma nova (nem tão nova assim) forma de pensar. Vou mostrar um exemplo para ilustrar isso.
[java]
public class Usuario {
private String login;
private String senha;
//normal getters e setters
}
[/java]
Nada de novo certo? Mais uma classe burra sem lógica de negócio alguma! Pois bem, seguindo o padrão Active Record, essa classe deveria “saber” como se persistir, delegando a real lógica para um Repository, que nada mais é que uma espécie de DAO. Desta forma, a classe que acabei de mostrar ficaria parecida com isso:
[java]
public class Usuario {
private String login;
private String senha;
// getters e setters
private Repository repo;
public void setRepository(Repository repo) {
this.repo = repo;
}
public void save();
public void update();
public void delete();
}
[/java]
A variável repo seria injetada pelo Spring, evitando assim qualquer código de lookup na classe Usuário. Porém, como você espera carregar um usuário previamente cadastrado no banco de dados? Recorrendo a um DAO padrão no código cliente - um façade por exemplo ?
Aà tudo que foi feito teria sido em vão! Se a classe sabe como se persistir, deve prover meios de se carregar objetos do seu repositório da mesma forma, isolando totalmente detalhes de implementação do código cliente. E aà começam os problemas.
Vamos à terceira versão de nossa classe:
[java]
public class Usuario {
private String login;
private String senha;
// getters e setters
private Repository repo;
public void setRepository(Repository repo) {
this.repo = repo;
}
public void save();
public void update();
public void delete();
public static Collection
return this.repo.findByLogin(login);
}
[/java]
Ora ora ora! Espera aÃ! Um método estático acessando uma variável de instância?!? Não pode! E isso me tirou o sono! Como é que eu vou injetar uma dependência num objeto se eu preciso dela antes mesmo de ter uma instância do mesmo?
Uma maneira, porca, de se resolver isso seria alterando a variável repo para static e inicializando-a num bloco static, assim:
[java]
static {
repo = new Usuario().getRepo();
}
[/java]
Dois problemas com isso: Eu exponho meu dao para o mundo - tá, posso resolver alterando o modificador de acesso do método - e instancio um novo objeto única e exclusivamente para pegar o DAO que o Spring injetou e joga-lo fora.
Soa estranho não? E é! Não queria ter que fazer isso. Funciona, mas é feio e tosco! E agora vem mais um motivo da minha lista de coisas que eu amo no Spring! A classe MethodInvokingFactoryBean!
São poucas linhas de configuração no arquivo do contexto da aplicação:
[xml]
[/xml]Dessa forma, na inicialização do container de Inversão de controle, a classe usuário já teria sua variável estática inicializada e, como não é proibido usar uma variável estática a partir de um método de instância, os métodos save(), update() e delete() já estariam com suas vidas resolvidas também, usando o mesmo repositório que foi inicializado no carregamento do container!Acho que fica uma solução limpa, elegante e não te faz abrir mão dos benefÃcios da inversão de controle e do padrão Active Record.Desculpem o primeiro post! Ficou meio grande né? Mas espero que tenha ficado legal! Um grande abraço e até a próxima!