Fugindo do modelo anêmico

[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.

Isso não é falácia, é ponto de vista.

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=bonfarj]

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:

Porque não fazer logo:

dao.save(fornecedor);

Em vez de complicar a vida com ActiveRecord ?

Eu concordo com a afirmação do Lezinho:

Rs… Engraçada essa afirmação!

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. :slight_smile: IMHO.

[b]

Nem falácia nem controverso!

Não se pode confundir um objeto de invenção pura, com o Data Transfer Objects.

Um objeto não deve persistir a si mesmo; isso viola o principio de Separação de Interesses.

O padrão Separação de Interesses tem prioridade sobre o Especialista na Informação.

Existe uma prioridade nos padrões; Primeiro Grasp (básicos) depois GoF, e todo padrão tem contra-indicação…

[/b]