Qual a diferença conceitual entre o Service e o Facade, ali quando é apresentado o GerenteConta como um Service, ele não poderia ser tb um Facede por definir um ponto de entrada?
Acredito que entendi o conceito do Repositório, mas fiquei um pouco perdido em como viabiliza-lo, e quem é responsável pelo o que: Usando o exemplo da revista, eu tenho um repositório de categorias, quem é responsável por criar este repositório, seria a Facade? A Facade busca uma categoria no repositório, se não encontrar, o repositório busca no DAO? E ao criar uma nova categoria, primeiro coloca ela no repositório e é ele o responsável por salvar fisicamente (usando o DAO).
Vamos lá: Um Façade é uma fachada, um filtro, ele diz o que pode e o que não pode entrar na camada de negócio e também diz o que pode sair. Um facade impede algo do tipo:
public class MeuFacadeMalImplementado extends MinhaArquiteturaMalPensada {
public DAOClienteImpl getBobagem(ActionFormDoStruts) {...}
}
Viu só que meleca? Estou jogando um ActionFormDoStruts pra dentro da minha camada de negócios, isso diz que a camada de negócio precisa conhecer o struts para funcionar (péssima idéia). Pior, esse método está
retornando uma classe de infra-estrutura, indicando que a minha camada de aplicação precisa conhecer a infra (uma idéia pior ainda).
Outra coisa que o Phillip colocou no artigo e que já discutimos aqui é que o façade tem granularidade grossa e agrega várias funcionalidades de granularidade fina que estão na camada de negócios.
O service é uma classe de negócio que coordena como as coisas acontecem. Ele tem uma inteligência própria que é estranha a qualquer outra entidade do Domain Model. No exemplo do Shoes, você tem conta1, conta2 e um valor. Ele fez um service que recebe isso e faz o trabalho. Nesse exemplo, não teria grandes problemas fazer um método conta1.transferirPara(conta2, valor) com essa inteligência.
Mas, determinadas operações ficam bem estranhas estarem nos entities. Exemplo: Quando você fatura um pedido, uma nota deve ser impressa, um estoque deve ser baixado, o crédito do cliente deve ser atualizado e mais umas trocentas coisas devem acontecer. Se você colocar tudo isso dentro de pedido.faturar() o próprio pedido vai ter que coordenar COMO todas essas outras classes fazem as suas tarefas diminuindo a coesão. Fora que dependendo do contexto, não é bom que o pedido conheça essas classes.
Determinados problemas é melhor você ter um servico do que um método. É importante ressaltar que o Pedido.faturar() pode existir e chamar esse servico (nesse caso, Dependency Injection nele).
Uma dúvida em relação a integração/comunicação da camada view com a camada de aplicação.
A camada view por exemplo creio que não deve conhecer os objetos de domínio, mas como fazer as chamadas à camada de aplicação sem conhecê-los?
Um exemplo um pouco mais prático:
Neste caso quem chamar este método, deverá conhecer o objeto de domínio ‘Client’ para passá-lo, certo?
Mas se não tiver esse conhecimento, o método responsável é quem vai ter que conhecer e em contrapartida receber todas as informações.(Imagine se houver uma dezena de atributos, ter de passar todos como parâmetros)
Eu, particularmente, não vejo problemas em outras camadas utilizarem Objetos de Transferencia, como no caso que vc citou, alguem conhecer o objeto Cliente. Isso é uma ‘briga’ que já tivemos aqui na empresa nas várias reuniões de arquitetura…
Acho que chamar um método com 12 parametros, alem de ferir qualquer regra de arquitetura, fica praticamente inviavel…
Eu passo os objetos de transferencia (TO para uns, DTO para outros) entre as camadas e não vejo melhor solução…
Num esquema de Camadas empilhadas a Camada de cime depende da interface da Camada de baixo, isso faz com que objetos que façam parte da interface da Camada de Baixo (como objetos de negócio quem entrem e saiam) possam ser utilizados.
Quanto à TOs, por que simplesmente não utilizar os objetos de domínio ao invés de copiar dados entre objetos, manter hierarquias paralelas, criar objetos de dados sem comportamento e todos os outros problemas de TOs?
Se você não quer que a Camada de cima tenha acesso à métodos específicos faça-a manipular uma interface. Exemplo:
class ContaCorrente{
public void depositar(BigDecimal a){...}
public String getNumero(){...}
}
Se eu não quero que minha Camada de Apresentação consiga chamar o método depositar (que é um método que muda o estado do Objeto e só deve ser chamado de outras Camadas) basta criar uma interface:
interface Conta{
public String getNumero();
}
Fazer C/C implementá-la e a Camada de Apresentação lidar apenas com ela. Sem repetiçãod e dados, sem objetos burros.
Note que mesmo esta solução é um tanto drástica demais, eu mesmo nunca vi real necessidade em meus projetos.
Ainda achei a criação de uma interface melhor do que ter VO´s espalhados pela aplicação.
Mas por exemplo se você não cria esta interface e deixa a camada de apresentação conhecer os objetos de domínio, o que impede de a camada de apresentação fazer uma chamada para um método que não deveria?
Não vejo problemas (até agora não ví) da camada de aplicação ou apresentação conhecer e usar entidades do Domain. É exatamente esse sentimento que gera muitas coisas desnecessárias no projeto (TOS, DTOS) e tendem a levar ao código procedural (já sofri bastante com essas más definições arquiteturais, meu projeto atual está bem procedural e o refactoring disso vai levar mais de um ano, exatamente por essa tentativa dos arquitetos anteriores de isolar o negócio de tudo, pra quê?).
Se existir uma necessidade da interface que o Philip falou, será mais por questões de arquitetura do que por necessidade de negócio. Por exemplo, se um pedido pode ser faturado [pedido.faturar()], não seria a camada que ele se encontra que limitaria a chamada do método. O que limitaria seriam as regras de negócio do próprio pedido.
[quote=Rafael Nunes]Ainda achei a criação de uma interface melhor do que ter VO´s espalhados pela aplicação.
Mas por exemplo se você não cria esta interface e deixa a camada de apresentação conhecer os objetos de domínio, o que impede de a camada de apresentação fazer uma chamada para um método que não deveria?
[/quote]
Esse ponto que eu ia colocar, nessa forma você vai ter uma interface a mais, porém não vai impedir que haja quebra de encapsulação. E se a proposta for reduzir a complexidade, diminuir uma classe VO e adicionar outra interface, daria no mesmo, não ? :roll:
Uma sugestão, seria colocar as classes que compõe a camada de aplicação, no mesmo pacote das classes de domínio. Assim, os métodos que a view poderia acessar marcaria-os como públicos, e os que seriam acessíveis somente pela camada de aplicação marcaria-os como acesso default ou protected.
DTOs não são objetos de domínio, são objetos usados apenas apra transmitir dados entre Camadas Físicas, não tem nada a ver com o Domínio da Aplicação.
Você não precisa (e nem deveria) usar DTOs com Hibernate. Isso é uma herança de Entity Beans que não faz o menor sentido quando se usa uma ferramenta de ORM para POJOs.
Eu nunca vi necessidade disso mas se você precisa se precaver basta criar a interface.
Eu diria que esta interface em específico seria mais relacionado com a estrutura de desenvolvimento. Imagino que um projeto onde times diferentes desenvolvemas Camadas você queira se rpecaver da outra equipe trapacear nos métodos, mas como disse nunca vi acontecer com tanta importância.
[quote=rodrigoallemand]
Neste mesmo exemplo, como vc colocaria o retorno da interface para o método getDetalhesCliente(idCliente)?[/quote]
Ué, faria um método na interface que retorna um objeto… não entendi sua dúvida.
[quote=Fabrício Cozer Martins]
Esse ponto que eu ia colocar, nessa forma você vai ter uma interface a mais, porém não vai impedir que haja quebra de encapsulação. E se a proposta for reduzir a complexidade, diminuir uma classe VO e adicionar outra interface, daria no mesmo, não ? :roll: [/quote]
Por isso que eu falei que não é comum utilizar esta técnica e as diferenças mais básicas são que você não rpecisa manter duas hierarquias de lasses nem ficar copiando dados para objetos de transferência.
Acho que isso limitaria demais a escolha de hierarquia de pacotes, mais do que estou disposto, mas é uma saída…
No seu artigo você comentou a respeito de Domain Model vs Transaction Scripts, algo do tipo “nem todo sistema exige a complexidade de um domain model… blá blá blá…”.
Bom, atualmente com mecanismos ORM um mapeamento fica mais simples. Isto é, é mais fácil atualmente ter uma estrutura OO persistente e convenhamos 90% dos projetos são aplicações de banco de dados. Se você tem o seu banco espelhado em objetos, potencialmente, já seria um Domain Model. Desse modo, não seria sempre mais fácil ter um Domain Model do que trabalhar com TranScripts?
Digo isso porque não acredito que é a complexidade que vai ditar o uso ou não de um domain model. Acho que para aplicações de banco de dados o Domain Model vai sempre existir, com doses maiores ou menores de TranScripts dependendo do caso.
Acredito que não, pois o Domain Model seria formado também por classes de negócios, que realizam processamento de use-cases e que não são obrigatoriamente espelhadas em tabelas.
Acredito que não, pois o Domain Model seria formado também por classes de negócios, que realizam processamento de use-cases e que não são obrigatoriamente espelhadas em tabelas.[/quote]
Isso não responde a minha pergunta. Que situação você teria Entities e Transaction Scripts que não justificam um Domain Model?
Transaction Scripts e Entities são uteis quando você não tem uma aplicação rica em comportamento, com predominancia de crud por exemplo, e a maioria dos casos de uso são apenas manipulação do banco de dados sem muita lógica de negocio (sumariza todos registros X, insere na tabela Y e atualiza na Z).