Ola, no começo da semana eu postei um topico com duvidas de como evitar VOs BOs, apos muita discussao eu nao tinha entendido mas depois de ler tudo novamente e inclusive os outros posts que falam sobre o mesmo assunto eu cheguei a seguinte conclusao e gostaria de saber se isto esta correto.
//Meu servlet ou algo do genero
public class Beta {
//Como eu gravava um objeto em um modelo anemico
private void anemic(){
PessoaBO pessoaBO = new PessoaBO();
Pessoa pessoa = new Pessoa();
pessoa.setIdade(30);
pessoaBO.save(pessoa);
}
//Como eu deveria gravar um objeto usando DDD
private void DDD(){
Pessoa pessoa = new Pessoa();
pessoa.setIdade(20);
pessoa.save();
}
//Teste de uso
public static void main(String args[]){
Beta beta = new Beta();
beta.DDD();
beta.anemic();
}
}
//Meu antigo VO, POJO, DTO ou TO, chamem como quiser
class Pessoa{
private int idade = 50;
private Repositorio repositorio;
public Pessoa(){
repositorio = new Repositorio();
}
public int getIdade() {
return idade;
}
public void setIdade(int i) {
this.idade = i;
}
public void save(){
repositorio.save(this);
}
}
//Objeto de negocio parte do modelo anemico
class PessoaBO{
public void save(Pessoa pessoa){
Repositorio repositorio = new Repositorio();
repositorio.save(pessoa);
}
}
//Meio de como persistir os dados
class Repositorio{
//Grava o objeto em algum lugar qualquer
public void save(Pessoa pessoa){
System.out.println(pessoa.getIdade());
}
}
Observacoes:
A classe repositorio poderia ser uma interface, e vc poderia obter uma instancia dessa forma para abstrair aonde vc grava as informacoes
Mas eu acho que isso nao vem ao caso, o que importa é que uma Pessoa tem que possuir um repositorio e a Pessoa deve ser responsavel pela acoes de persistir um objeto do tipo pessoa ! correto ?
Portando a logica de negocio fica no proprio VO.
Mas questão é mais quando uma logica de negocio de Pessoa for executada… exemplo
Antigamente você teria
e sem BO e VO, você usa:
Já que agora, pessoa possui estado e comportamentos…
Quando você quiser exibir Pessoa num JSP, você manda o objeto e não um VO dele porque simplesmente não há necessiade de um VO, então veja que nesse caso ele seria inutil.
Só não chame Pessoa de VO… Pessoa é um objeto de domínio… VO/DTO tem oturo significado
pessoa.save() não é uma “logica de negócio”. Salvar um dado em um banco de dados no fundo não é um problema do negócio, mas quase um “requisito não funcional” do seu sistema. Na minha opinião não seria errado delegar o “salvar” para outra classe (fora do domínio do negócio).
Se fosse tipo pessoa.definirIdade(20), e isto no fundo salva o dado, para mim ai estaria mais correto.
[quote=oyama]Só acho que o seu exemplo não foi muito feliz…
pessoa.save() não é uma “logica de negócio”. Salvar um dado em um banco de dados no fundo não é um problema do negócio, mas quase um “requisito não funcional” do seu sistema. Na minha opinião não seria errado delegar o “salvar” para outra classe (fora do domínio do negócio).
Se fosse tipo pessoa.definirIdade(20), e isto no fundo salva o dado, para mim ai estaria mais correto.[/quote]
É por isso que o infeliz do Phillip Calçado nao citou exemplos, pois é dificil retrar a situação atraves de um exemplo.
Porem por mais que o exemplo seja ruim :oops: , eu espero que parte do conceito tenha sido entendido
Agora eu nao entendi o que vc quis dizer em relação a delegar o “salvar” para outra classe (fora do domínio do negócio).
Aonde por exemplo e porque ?
Obs.: Espero que ele nao fique ofendido com o infeliz rsrs
A abordagem que eu costumo usar, você preserva de certa forma a idéia de um Active Record mas sem acoplar o objeto de domínio com a tecnologia de persistência.
class Pessoa{
void save(){
repository.save(this)
}
}
O ActiveRecord “parece” não trabalhar com POJOs, ou seja, a tua entidade faz tudo, o que me referi a sopa de camadas era a respeito de você juntar uma entidade do sistema + DAO, tal como mostrado no exemplo
Entendi, obrigado por corrigir.
Eu so me pergunto como ficaria isso mapeado no hibernate, eu teria um Pessoa.hbm.xml referenciando o objeto de dominio e nao mais a um VO ?
E dentro do método vc decide. Pode usar um properties ou outra coisa para decidir. Isto elimina mais uma dependencia.
Por outro lado vc só precisa de uma instancia de Repositor. O factory deve controlar o numero de instanciações e para simplificar torne os métodos de Repository estáticos e genericos.
Vc pode ainda separar o acesso ao banco com DAO se quiser.
E ficaria assim.
//Meu servlet ou algo do genero
public class Beta {
//Como eu deveria gravar um objeto usando DDD
private void DDD(){
Pessoa pessoa = new Pessoa();
pessoa.setIdade(20);
Repository.store (pessoa);
}
}
}
Na verdade no link só tem um breve resumo deste padrão, no livro do Fowler tem uma explicação maior.
Mas em suma, Active Record seria além das propriedades e lógica de negócio, inserir nos objetos de domínio também a lógica de acesso a dados. No próprio livro Fowler diz que active record é uma boa solução para sistemas que não tenham uma lógica de negócio muito complexa, tipo CRUDs, e sugere que para domínios com relacionamentos mais complexos, seja utilizado alguma forma de Data Mapper, como DAO por exemplo.
O exemplo que eu dei utiliza as duas estratégias, porém ao invés de o objeto de domínio conter a lógica de acesso a dados, ele delega essa responsabilidade para um Data Mapper.
1)Eu entendo que o objeto de dominio seja a Pessoa, se colocarmos a funcao salvar dentro do repositio e a funcao salvar necessitar de logica, a logica ficaria fora do dominio, a nao ser que o objeto de dominio seja composto por Pessoa + Repositorio, e por isso eu usei composição pois uma pessoa contem um repositorio.
2)Perfeito, realmente tava pessimo aquela dependencia
3)Tornar os metodos do repositorio estatico e generico, nao entendi como fazer, pode ser mais claro.
[quote=Rafael Nunes]
Mas em suma, Active Record seria além das propriedades e lógica de negócio, inserir nos objetos de domínio também a lógica de acesso a dados.[/quote]
Eu nao achei pratica essa solução, e se eu mudar a logica de acesso a dados, por exemplo: Hoje eu uso hibernate mas amanha eu gostaria de usar JDBC, seguindo o Active Record eu teria de configurar novamente todos os objetos de dominio, nao achei muito inteligente nao :?
[quote=Rafael Nunes] No próprio livro Fowler diz que active record é uma boa solução para sistemas que não tenham uma lógica de negócio muito complexa, tipo CRUDs, e sugere que para domínios com relacionamentos mais complexos, seja utilizado alguma forma de Data Mapper, como DAO por exemplo.
O exemplo que eu dei utiliza as duas estratégias, porém ao invés de o objeto de domínio conter a lógica de acesso a dados, ele delega essa responsabilidade para um Data Mapper.[/quote]
Pode substituir na frase acima, lógica de negócio complexa por estratégias arquiteturais mutáveis.(E particularmente, já ouvi bastante esta questão de ‘e se eu trocar de banco’, ‘e se eu trocar de mecanismo de persistência’, ‘e se eu trocar o SO do meu servidor’), mas na prática nunca vi e nem ouvi falar disso, a não ser para softwares que já nascem com a intenção de independência de plataforma. E sistemas simples, eu diria que dificilmente isso vai ocorrer.
E no exemplo que eu dei, caso você troque o mecanismo de persistência, só vai ter de fazer modificações no Data Mapper, como faria caso estivesse utilizando diretamente DAO.
[quote=ronildobraga][quote=felipec]
Nós não estamos usando mais VO nem BO. Estamos usando um objeto de domínio para cumprir o papel do VO e do BO.
[/quote]
Entendi, obrigado por corrigir.
Eu so me pergunto como ficaria isso mapeado no hibernate, eu teria um Pessoa.hbm.xml referenciando o objeto de dominio e nao mais a um VO ?[/quote]
Exato!
mas pra melhorar a frase… “referenciando o objeto de dominio e nao mais um objeto anêmico…”
Porque ja vi muito sistema com objetos anêmicos usarem VOs (nesse caso, o hbm.xml mapeava o objeto anemico e não o VO)
[quote=Rafael Nunes] (…)
E particularmente, já ouvi bastante esta questão de ‘e se eu trocar de banco’, ‘e se eu trocar de mecanismo de persistência’, ‘e se eu trocar o SO do meu servidor’), mas na prática nunca vi e nem ouvi falar disso, (…)[/quote]
Em termos de aplicações prontas isso é muito verdade. Mas, existe a necessidade de independencia por dois motivos ortogonais a esses.
Testabilidade. Ao fazer testes não quero usar o banco. Quero usar uma lista predefenida de valores que usarei nos meus testes. Ai eu substitui o meu DataBaseDAO por um TestDAO (que herda de InMemoryDAO) devidamente inicializado.
Vida util. O sistema tem maior vida util quanto mais o seu dominio não depender de tecnologia. Se todas as logicas escritas em Clipper ou COBOL podessem simplesmente ser reaproveitadas mudando apenas o SO, ou o Banco ou a interface gráfica essas linguagens ainda estariam dando cartas. Em Java se mudar o SO vc muda a JVM, se mudar o banco vc muda o DAO, etc… A sua logica de dominio permanece.
Outra coisa que pode acontecer é mudar a versão do banco , por exemplo, e vc quiser usar funcionalidades novas. Ai vc cria um novo DAO que funciona para essa versão mas não para as anteriores. E assim vai.
Se vc pensa que a vida util do seu programa é menos de 5 anos, então realmente, estas considerações são meio sem sentido e vc acaba criando uma aplicação que dura 5 anos por vicios no seu design. A minha opinião é que a vida util não deve depender dessas coisas se for possivel não depender.