Boa tarde!
Há alguns anos atrás quando comecei a estudar e aprender desenvolvimento (Java na época) me cadastrei aqui no fórum. Logo depois comecei a trabalhar com .NET e acabei esquecendo deste fórum. Nós últimos tempos, estou procurando me aprofundar em Design e Padrões de Projeto e acabei caindo aqui novamente. Desde então (já uns 4 meses) frequento diariamente apenas como leitor, mas agora chegou a hora de postar umas dúvidas e pedir a ajuda dos colegas de fórum
Como falei, trabalho com .NET e procuro aplicar o máximo possível as boas práticas de projeto. Estou estudando DDD (já li o “resumo” do livro do Eric Evans do InfoQ, diversos blogs de pessoas que postam aqui no fórum e blogs indicados por eles, li bastante coisa de Fowler e estou estudando atualmente um pouco o PEAA entre outras literuaturas menores) e tenho uma dúvida que ainda não consegui achar uma resposta satisfatória.
Em .NET, não utilizamos MVC como em Java (ainda, pois ASP.NET MVC está saindo) então não temos os conceitos de controllers tão explicitos quando vocês, portanto algumas abordagens devem ser levemente adaptadas. Meu cenário é:
Modelei (estou tentando) uma pequena parte de um sisteminha de E Commerce (estou colocando diagrama anexo) utilizando Entidades (Atributos + Comportamento) e Repositorios. Desta maneira, já consegui tornar meu código bastante testável e acredito estar no caminho certo para um design mais clean e mais fácil de manter e testar.
Exemplo de teste:
/// <summary>
///A test for Total
///</summary>
[TestMethod()]
public void TotalTest()
{
IPedidoRepository pedidoRep = mock.DynamicMock<IPedidoRepository>(null);
IProdutoRepository produtoRep = mock.DynamicMock<IProdutoRepository>(null);
using (mock.Record())
{
Expect.Call(pedidoRep.CriarPedido()).Return(new Pedido());
Expect.Call(produtoRep.CriarProduto()).Return(new Produto()).Repeat.Twice();
}
Pedido target = pedidoRep.CriarPedido();
Produto prodBebida = produtoRep.CriarProduto();
prodBebida.Preco = 100;
target.AdicionarProduto(prodBebida, 1);
Produto prodComida = produtoRep.CriarProduto();
prodComida.Preco = 35.20m;
target.AdicionarProduto(prodComida, 7);
decimal expected = 346.40m;
decimal actual = target.Total;
Assert.AreEqual(expected, actual);
}
Tenho no modelo minhas entidades: Pedido, ItemPedido (value object), Cliente, etc.
Meus repositórios (o conceito) são definidos por Interfaces implementadas por DAO, visto que são persistências simples inicialmente (apenas CRUD).
Factories das Entidades que coloquei junto com o Repositórios (método CriarPedido() por exemplo) visto que também são simples e não necessitam de uma classe apenas para isso.
Como em .NET trabalhamos com WebForms e temos acesso aos controles da página através do code-behind não se faz necessário popular minhas entidades a partir de um objeto request passado para uma action, mas sim no próprio code-behind através de:
Objeto.Propriedade = txtQualquer.Text;
No início me pareceu um pouco estranho criar entidades e efetuar chamadas ao repositório diretamente do code-behind (que fica na camada de aplicação), mas dado o cenário simples achei que iria complicar muito se fizesse diferente.
Exemplo de persistência CRUD de um Cliente:
protected void btnSalvar_Click(object sender, EventArgs e)
{
if (ClienteAtual.Id.Equals(0))
Adicionar();
else
Atualizar();
}
private void Atualizar()
{
//ClienteAtual é mantida em viewstate na minha camada de aplicação
IClienteRepository rep = RepositoryFactory<IClienteRepository>.Create();
ClienteAtual.Nome = txtNome.Text;
ClienteAtual.CPF = txtCPF.Text;
ClienteAtual.Email = txtEmail.Text;
rep.Atualizar(ClienteAtual);
Response.Write("Cliente atualizado com sucesso!");
}
private void Adicionar()
{
IClienteRepository rep = RepositoryFactory<IClienteRepository>.Create();
Cliente novoCliente = rep.CriarCliente();
novoCliente.Nome = txtNome.Text;
novoCliente.CPF = txtCPF.Text;
novoCliente.Email = txtEmail.Text;
rep.Adicionar(novoCliente);
Response.Write("Cliente inserido com sucesso!");
}
No entanto, nesse momento estou pensando em implementar situações que não sejam CRUD, como efetuar um pedido por exemplo. Neste caso, mais de um objeto estaria envolvido na transação então não acredito que seja bacana fazer esse processo diretamente no code-behind. Além é claro, de ser menos bacana ainda colocar transações na camada de aplicação. Sendo assim, criei uma Service para Pedido, pois o processo de efetuar o pedido, no meu ponto de vista, não é responsabilidade do Cliente e nem do Pedido. Seria de um “funcionário” da loja, mas a título de simplicidade bastou criar o PedidoService.EfetuarPedido().
Agora as dúvidas: como tratar a criação das entidades nesse caso? Crio elas na minha camada de aplicação (code-behind), passo para o PedidoService para o processamento e posterior chamada ao repositório para atualização de dados ou PedidoService apenas modifica meus objetos e a própria camada de aplicação chama o repositório para persistência (como no exemplo do cliente ali em cima)? Minha classe PedidoService pode acessar meus repositórios? Acredito que sim, pois todos são objetos de domínio que de acordo com o que entendi tem livre acesso entre si. É isso mesmo?
Acredito que a minha principal dificuldade neste momento é tratar bem a separação das camadas de Aplicação e Domínio. Pensei em utilizar Façade, mas nesse caso o que eu retornaria para a camada de aplicação? O que a camada de aplicação iria passar para o Façade?
Desculpem o post grande e qualquer bobagem que eu tenha dito a respeito de Java.
Agradeço desde já qualquer ajuda