Instanciação de Entity, classe de domínio, DDD Evans, onde é correto?

Só para constar, uso também essa técnica do Lezinho. E as vezes meus repositórios vão para a view. (espero que não tenha inquisitores de plantão). Porém, na minha opinião não é DDD que estamos largando mão, já que é um Entity que estamos manuseando na view. Na minha opinião estamos deixando de usar a camada de aplicação para ganhar produtividade e simplicidade.

Acho válido tratar o CRUD deste jeito. E acho que pode ser a primeira abordagem em um projeto. Como o leozinho falou, se o CRUD complicar um pouco, ou aparecer a necessidade de portar a logica do CRUD para outra aplicação, aí pensamos em resolver.

Não vejo problemas na view conhecer e depender da persistência, afinal de contas a view nunca é portável. Mas acho que temos sempre que nos preocupar se o domain está completo e se ele é independente. Se tratar o CRUD “por fora” não impedir que o domain resolva o problema todo do sistema de forma independente, então tudo bem. Mas se um CRUD for fundamental para que o Domain resolva o problema do sistema, este deve ser tratado dentro do Domain, caso contrário não podemos dizer que estamos usando DDD. Também não seria errado, só não seria DDD.

Concordo também quando o Rodrigo diz que não estamos abrindo mão do DDD ao chamar o Repository direto da View, pois o repository pode ser um service simples. E talvez até faça sentido expor o repository para a view, pois que é responsável por forncer um objeto é o repository do tipo que queremos. Por exemplo, o responsável por fornecer um objeto Pessoa é o PessoaRepository e se a view precisa de um objeto desses, deve pedir ao repository. Mas isso não quer dizer que não estamos utilizando o Domain, pois o repository faz parte do Domain. Mas repito que regras de negócio devem ficar no Domain. Regras de infraestrutura não precisam.

E pra terminar, quero lembrar de que o Repository é diferente do DAO. Repository fica no Domain e o DAO na persistência, portanto o repository pode ser chamado de qualquer parte, mas a persistência deve ser preferencialmente isolada. O Repository deve encapsular a chamada à persistência para que possamos dizer que usamos DDD.

Isso sim não é realista. Você não entendeu este ponto.

Eu não usei um exemplo que valida um usuário que ja existe no sistema. Meu exemplo cria um novo usuário. Nessas situações eu uso (1) na camada de app. para não ter que instanciar usuário (regra de app) na camada de visão.

Desnecessário repetir mais uma vez de novo que não estou discutindo camada de domínio.

public class AppService {
    public long criaUsuario(String name) {
        Usuario usuario = new Usuario(name);
        // código na camada de aplicacao que persiste usuario!
        return repositorioUsuario.add(usuario);
    }
}

Você esperava o que ? você mudou o exemplo !

criaUsuario(String nome, String pass, long perfilId);

Parece bom pra mim…mas também pode ser:

criaUsuario(String nome, String pass, Perfil perfil);

Neste caso o cliente não vai instanciar perfil para passar. Ele ja possui a referencia para tal objeto.

Hmmm… não vejo assim. A relação do M de MVC com o modelo de domínio é de dependência. Um usa o outro, mas um não é o outro. MVC, IMHO, é todo camada de visão.

Mas essa é outra discussão.

Eu só falei em tipos básicos da linguagem e objetos de domínio. DTOs é por sua conta !

Certo. O login seria essencial neste caso pq ele deveria ser unico para o usuario que sera criado.

Exatamente. Se não houver camada de aplicacao não há problemas. Se ela existe prefiro usa-la.

Pra mim não é desnecessário.

[quote=carneiro]Uma vez vi um código em que as informações iam e viam da visão para as demais camadas através mapas e coleções de tipos primitivos. Vi um caso de uma coleção de mapas, rsrs. O desenvolvedor argumentou que isso reduzia tremendamente o acoplamento, pois as classes de visão não conheciam as entidades do domínio.

Ou seja: ele confundiu acoplamento com coesão. :)[/quote]

Ou não… talvez o objetivo dele fosse o desacoplamento mesmo…

O que talvez ele não soubesse é que não há problema na visao depender do dominio.

[quote=cmoscoso]
Desnecessário repetir mais uma vez de novo que não estou discutindo camada de domínio.[/quote]

Vc não precisa discutir camada de dominio, mas eu precisei exemplificar a diferença da assinatura dos métodos
conforme a camada em que são usados.

String , Date, Number , Boolean tb são DTO. Apenas são DTO com um so valor. DTO é um padrão de responsabilidade e uso e não de implementação. Quando vc escreve:

criaUsuario(String nome, String pass, long perfilId);

Vc está usando 3 DTO com 1 valor cada um. Se vc escrever

Map map
map.put(“nome”,nome);
map.put(“pass”,pass);
map.put(“perfilId”,perfilId);
criaUsuario(Map map);

Vc está usando 1 DTO com 3 valores.

Se vc está seguindo o tema do topico e tentando responder à pergunta “Instanciação de Entity, classe de domínio, DDD Evans, onde é correto?” então vc deve saber que usar DTO, qualquer que seja, é contra a filosofia DDD. Já que a UI pode conhecer o dominio (através do model do MVC) use-se a entidade e pronto.
Mas mesma a entidade pode estar sendo usado como DTO. Tudo bem desde que não exista um objeto cuja unica responsabilidade é ser um DTO. Um entidade, por definição, tem mais responsabilidades do que apenas portar dados.

Eu estou partindo da ideia de que a UI está sobre um modelo MVC. Se não estiver , ou o sistema é muito simples e nem ha o que discutir, ou está mal feito. O M do MVC não pertence ao UI, pertence ao dominio. Ele é responsavel por intrepretar alterações no modelo e passar isso à UI e intrepretar alterações na UI e passar ao modelo. O M do MVC tem acesso total às regras do negocio e do dominio e é a peça inteligente do UI (o smart)
A View e o Controlo são apenas automações da UI que nada têm a ver com o dominio.

DTOs são objetos tipo “estruturas de dados” que só possuem métodos relativos a armazenagem e obtencao desses dados.

String, Date, Boolean são imutáveis e possuem métodos que operam sobre os seus dados. Eles são Value Objects.

[quote=sergiotaborda]
Se vc está seguindo o tema do topico…vc deve saber que usar DTO, qualquer que seja, é contra a filosofia DDD…Mas mesma a entidade pode estar sendo usado como DTO. Tudo bem desde que não exista um objeto cuja unica responsabilidade é ser um DTO.[/quote]

Ficou confuso. Afinal pode ou não pode usar DTO?

Eu respondo:
Quando eu digo que esse tópico não é sobre a camada de domínio especificamente significa por exemplo que você poderia utilizar os DTOs na interface da sua camada de aplicacao sem prejudicar o seu modelo de domínio. Mas em nenhum momento eu defendi este uso de DTOs como parametros ou seja la como for, nem mesmo na camada de aplicacao.

[quote=sergiotaborda]
Eu estou partindo da ideia de que a UI está sobre um modelo MVC. Se não estiver , ou o sistema é muito simples e nem ha o que discutir, ou está mal feito. O M do MVC não pertence ao UI, pertence ao dominio. Ele é responsavel por intrepretar alterações no modelo e passar isso à UI e intrepretar alterações na UI e passar ao modelo. O M do MVC tem acesso total às regras do negocio e do dominio e é a peça inteligente do UI (o smart)
A View e o Controlo são apenas automações da UI que nada têm a ver com o dominio.[/quote]

Essa é a sua visão de MVC e camadas… Como já disse, eu não a compartilho.

A propósito, estava eu procurando outra coisa e acabei achando o seguinte trecho na pag. 144

Não.

São objetos que transportam dados entre processos com o objetivo de reduzir o numero de chamadas a metodos. É o uso do objeto que o torna um DTO e não a estrutura interna o a interface do objeto. Sequer é
a necessidade de implementar Serializable.
Portanto, qualquer objeto usado para o fim de passar dados entre processos é um DTO.
Claro que , para ser util, o objeto tem que conter várias informações , mas isso não é uma necessidade para que o objeto seja considerado um DTO.

Ser Value Object não tem nada a ver com DTO. Um objeto pode ser um VO e ser usado como um DTO.

[quote]

Vc pode criar entities na camada de apresentação , desde que nos objetos que , nessa camada , representam o dominio. Vc pode passar esses objetos para outros lugares como um DTO.
O que vc não pode fazer, em DDD, é criar um DTO burro , cujo objetivo é apenas transportar dados e que não contém nenhuma logica de dominio, ou seja, um objeto que não é uma Entidade.

Em outras palavras: vc pode passar Entities como se fosse DTO, mas não pode passar DTO como se fossem Entities.

Então a sua View pode criar DTO ( aliás o objeto Request é um DTO) e ele pode ser usado tranqüilamente na camada de UI (ou em outras camadas). Pode usar DTO dessa forma até que ele chegue no dominio. Aqui, sempre que houver comunicação com o dominio ( aka “o resto do sistema”) Esses DTO têm que ser convertidos em Entidades( ou outros objetos de dominio - como VO ou Specifications ) de forma que o resto do sistema so veja Entities. Por isso que são necessárias Entity Factories.

Acho que esta errado afirmar isso.

Acho que o correto seria: Portanto, qualquer objeto usado para o fim de passar dados entre processos de forma mais eficiente (ex.: reduzindo o número de chamadas) é um DTO.

Porque ao meu ver o DTO tem que reduzir o número de chamadas, reduzir o número de dados enviados ou fazer qualquer outra coisa que torne a comunicação entre processos mais eficiente mas, isso só é usado quando se tem tiers.

Hum… e os Action Frameworks?

Imagine que vc tem este método

Vc chama este método no seu sistema 1 unica vez quando o sistema inicia.

Agora imagine este

Que vc tb só chama 1 vez ,mas em que C é

class C { A a B b }

C é um DTO ?
E A e B ?

Não ganhamos nenhuma eficiência usando C. A unica coisa que ganhamos é diminuir o numero de argumentos.
Mas ao forçar o uso de C forçamos que A e B sejam sempre encapsulados em C para usar o método
A comunicação entre processos não mudou em nada, apenas a lista de argumentos.
Mesmo assim é aceita-se que C seja um DTO.
Agora, porque vc não aceita que A e B sejam DTO ?

Só para que conste um DTO verdadeiro é um objeto que evita a repetição de chamadas como Fowler escreveu, ou minimize o custo das chamadas e apenas isso. Mas o termo é usado também para qq coisa que agrupe dados no intuito de minimizar argumentos em métodos.
E é disso que estamos falando.

Acho que o exemplo não demonstra o intuito do DTO.

Ao meu ver o intuito seria melhor expressado assim:

Vc tem uma classe remota que oferece os dois métodos

metodo1 ( A a )
metodo2 ( B b )    

Por algum motivo vc descobre que chamar esses dois métodos em separado é ineficiente. Então você decide oferecer um novo método e criar um DTO para tornar as coisas mais eficiente.

metodo3 ( DTOAB AB )

class DTOAB {
A a
B b
}

Agora vc pode me perguntar:

Não seria a mesma coisa usar um método assim:

metodo3 ( A a, B b )

Não, não é. Com o método desta maneira vc não justifica(comunica) o motivo de vc estar passando os dois parâmetros em um único método, pode parecer que seu método simplismente não esta coeso.
Agora com o método utilizando um DTO vc justifica(comunica) que o método esta daquela maneira para tornar mais eficiente uma chamada.

Eu acredito que C não é aceito como DTO pois, ele não torna nada mais eficiente.

Neste caso o termo esta sendo usado de forma incorreta. O correto seria usar um objeto parâmetro, que pode ser consultado em Fowler Refatoração.

O que vc disse em relação ao uso do DTO é completamente correto. É isto que dá tentar sem conivente…
Para deixar claro então: O nome verdadeiro do padrão a que me estou a referir é TO (Transfer Object , ou Transport Object) Que é um objeto cujo objetivo é agrupar dados para que possam ser passados como um bloco.
O DTO tb é um TO , mas como vc disse realmente o objetivo dele não apenas agrupar dados, é agrupar de forma que haja um ganho de eficiencia.
O problema de ser conivente é que eu usei o termo DTO em vez de TO porque é o termo DTO que normalmente se usa quando falamos de DTO e Entidades(Entity x DTO) . Já que esse uso é comum, eu usei para facilitar e para que se entenda o que escrevi. Mas como parece que só complicou, então foi realmente um erro ter usado o termo DTO.

O que eu estava dizendo é que:
1)Um Entity do DDD pode ser usado como um TO, mas um TO não pode ser usado como um Entity. Ou seja, simplesmente agrupar os dados não é criar um Entity.
2)Qualquer objeto pode ser passado entre camadas e/ou processos. Isso faz dele um TO. Como eu falei antes esse objeto só é util quando ele tem várias informações. Eu falei que Date, String , Integer , etc eram DTO no sentido que eles são passiveis de ser passados entre processos e camadas com o objetivo de encapsular certa informação. Ele podem não parecem muito uteis pq só contêm um dado , afinal são Value Objects (DDD), mas continuam sendo TO (Transport Objects)

3)Ao invocar um método com N campos ou um com 1 campo é sempre mais simples usar o de 1 campo e por isso que se inventaram os TO e DTO. Aliás isso é uma regra de OO: mantenha juntos os dados que existem juntos. Bom, então é simples entender que o método validaUsuário ( username, password) é pior que validaUsuario ( x). O que está em causa é : x pode ser um Entity ou não ?
Em que camada / momento x pode ser um entity e quando não pode ?
Quanto a isso eu tentei explicar que x sempre pode ser um Entity. Mas ele pode tb ser um Value Object ( por exemplo UserCredencials) ou um Specification (não se aplica no exemplo ,mas pode aplicar em geral). O que nunca pode acontecer é x ser um TO ( aka DTO) QUANDO o método pertence à camada de dominio.

  1. Quando um método pertence à camada de dominio ? Quando ele opera sobre a camada. Ou seja, usa objetos da camada de dominio.
    4.1) É correto instanciar um entity na view do UI ? Não. A view não pertence à camada de dominio, pertence à de aplicação.
    4.2) É correto instanciar um entity no model da UI ? Sim. O model pertence , por definição, na camada de dominio.

Levar estas regras à risca pode ser complicado e é ai que entra o bom senso. Só que bom senso não é algo que se tem, é algo que se adquire. E sem regras claras o bom senso tente a ser ruim.

Esclarecido isto, espero que se entenda agora o que venho tentado dizer.