[quote=sergiotaborda]Isso é uma falácia.
O fornecedor realmente tem conhece os seus dados, mas não conhece a localização da persistência. Entenda que essa localização pode mudar e ver variada. Se o fornecedor conhecer essa localização ele está puxando para si uma responsabilidade que não lhe cabe.[/quote]
Concordo plenamente, sem ressalvas.
E se fizermos isso com DI? A classe Fornecedor continua sem saber como persistir, isso seria injetado nela. Isso é uma boa solução?
Domain Model com Entidades contendo save, persist, … ?
Se você acredita que estas assinaturas de métodos faz sentido estar nas entidades, sua equipe e Expert Domain concordarem com você, tudo bem.
Eu simplemente acho que um EntidadeRepository.add(entidade) resolve o problema, sem ter que comprometer a modelagem da Entidade a.k.a. ActiveRecord desnecessário.
E se fizermos isso com DI? A classe Fornecedor continua sem saber como persistir, isso seria injetado nela. Isso é uma boa solução?[/quote]
Se vc usar injeção de dependência vc continua tendo dependência. Apenas não é vc que seta as referencias dos objetos manualmente. Não muda nada em termos de responsabilidade.
Se vc injetar um objeto que tenha essa responsabilidade de saber onde persistir vc estará implicitamente retirando essa responsabilidade de Fornecedor. Ai fica pior, a responsabilidade é de outro objeto mas vc está forçando o uso atravéz de Fornecedor como um façade. Ou seja se vc tiver
[code]class Fornecedor {
DAO dao ; // injetado pela infraestrutura
// atributos
public void save (){
dao.save(this);
}
}[/code]
Vc está usando Fornecedor como um Façade para DAO só porque vc gostaria de escrever:
Você esta dizendo que um padrão GRASP é uma falácia?
Eu discordo. Acho que os padrões de responsábilidades GRASP nos ajudam a aplicar a base da orientação a objeto, ainda mais se tratando do especialista da informação que é o mais importante.
Ele não precisa saber onde se persitir… é só criar uma indireção e utilizar injeção de dependencia…
Acho que você esta enganado. Há uma quebra de encapsulamento! Sorte que a quebra é feita com reflexão ou aspectos… Senão teriamos que fazer fazer manutenção com espingarda!
[quote=brunohansen]
Seguindo o Padrão GRASP Especialista na Informação, poderiamos dizer que: Quem tem os dados deve ser responsável por manipula-los. Com isso, conseguimos um boa divisão de responsábilidades, conseguimos fornecer um bom encapsulamento, evitamos inveja dos dados enfim, conseguimos evitar modelos anêmicos.
Muitas vezes olhando para o Especialista da Informação fiz reflexões parecidas com esta: O objeto Fornecedor conhece seus dados logo seria responsabilidade dele se salvar, assim manteriamos o encapsulamento etc… etc…
Mas como persistência é um problema de infra vamos voltar lá no mundo de bobject…
reflexões…[/quote]
Manipular os dados não significa persisti-los mas aplicar invariantes e regras de negócio. Isso que torna o modelo não anêmico.
Eu vejo que no DDD essa coisa de persistir a si mesmo é desestimulada. Eu (digamos entity) posso até usar o repositório para ler a persistencia e resolver alguma regra de negocio, ou seja, eu conheco a persistencia (por meio do repositorio), mas eu nao me persisto porque não é minha responsabilidade, eu faco parte de uma unit of work.
Uma pergunta: nesse caso, como vc faz a validação dos dados do objeto?
:arrow: Cria um método entidade.validar() e chama dentro do EntidadeRepository.add(entidade)?
[]'s
Rodrigo C. A.
[/quote]
A questão da validação é relativa a cada caso.
Se a validação é sobre invariantes simples do contrato, eu utilizo Hibernate Validator (para contratos nulos, tamanho de campos, datas futuras ou passadas, regex, etc)
Ex:
@Entity
public class Entidade{
@Future
private Date apenasDataFutura
@NotNull
private Object objetoQualquerNaoNulo
...
}
Se a validação para um contrato for quanto a permissão de papeis do usuário, eu uso o Seam com Drools :
//somente usuarios com o papel `admin` pode acessar este método
@Restrict("#{s:hasRole('admin')}")
public void meuMetodoDeNegocio(Object obj){
....
}
… agora se o contrato for algo que exige mais do negócio, entao eu evito colocar validações nos clientes e implemento no próprio negócio (por exemplo, quando um Entity faz um pedido ao Repository, quem vai verificar o contrato é o Repository).
Eu tento manter o código o mais limpo possível dos contratos, mas quando não é possível não se pode fazer muita coisa.
[quote=brunohansen][quote=sergiotaborda]
Isso é uma falácia.
[/quote]
Rs… Engraçada essa afirmação!
Você esta dizendo que um padrão GRASP é uma falácia?
[/quote]
Não. Estou dizendo que a frase a seguir é uma falácia.
[quote=brunohansen]] O objeto Fornecedor conhece seus dados logoseria responsabilidade dele se salvar, assim manteriamos o encapsulamento etc… etc…
[/quote]
‘A’ conhecer seus dados não implica em que é responsabilidade de ‘A’ fazer algo com eles.
Se formos por esse caminho eu poderia dizer que:
“O DefaultTableModel do Swing conhece seus dados logo ele teria a responsabilidade de se mostrar na tela.”
Acho que é simples de entender que esse tipo de construção lógica é uma falácia.
Fornecedor.insert() é errado do pontode vista de Domain Driven Design.
Porque?
Porque você não chega no mundo real e pede pelo telefone pra um fornecedor inserir dados, mas pede pra um fornecedor preencher um formulário. Portanto, Fonecerdor.preencheFormulario() seria cogitável, porém a melhor forma é colocar o metodo de inserção num repository ou num service.
Pense num repository como uma classe que administra uma coleção de objetos de um determinado tipo. Se você que adicionar um fornecedor a uma coleção (DB por exemplo), tem que adicionar pelo repository.
Nomes importam muito na abastração. Aliás acho que é isso que diferencia arquitetos de desenvolvedores. A capacidade de abstrair.
PS.: Você não é obrigado a utilizar DDD, mas não diga que está utilizando quando na verdade não está.
Qualquer padrão possui as contra-indicações, além de ser importante saber onde aplicar, devemos saber também onde não aplicar.
No caso, as classes de persistência são mais Especialistas na Informação para a tarefa de inserir no BD.
E você teria um problemas de Coesão Baixa e Alto Acoplamento, além de uma lógica similar fique duplicada em muitas classes persistêntes.
Por exemplo: uma venda pode informar seu total, mas ela não saber onde persistir (penso que ela nem deveria saber da existência do DAO), o DAO sabe onde persistir um objeto, e traze-lo de volta.
Estou com saudades do tempo que eu fazia tudo da minha cabeça. IMHO.