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

34 respostas
BiraBoy

Gente, pensando em DDD, é correto instanciar uma classe de domínio na camada de visão?

Pensei nisso porque pode haver, pensando em CRUD, uma Entity que tenha muitos atributos e seria melhor instanciar e popular na visão e então passar ao Service que orquestra a persistência. Criar um método com dezenas de parâmetros não parece adequado.

E da mesma forma se for uma atualização, popular o objeto com os atributos de atualização na visão.

Se isso for incorreto em Domain-Driven Design, qual seria a melhor saída?

34 Respostas

rodrigoy

Não é incorreto, as camadas só separam conceitos. Não é uma separação física.

C

BiraBoy:
Gente, pensando em DDD, é correto instanciar uma classe de domínio na camada de visão?

Pensei nisso porque pode haver, pensando em CRUD, uma Entity que tenha muitos atributos e seria melhor instanciar e popular na visão e então passar ao Service que orquestra a persistência. Criar um método com dezenas de parâmetros não parece adequado.

E da mesma forma se for uma atualização, popular o objeto com os atributos de atualização na visão.

Se isso for incorreto em Domain-Driven Design, qual seria a melhor saída?

Fala BiraBoy,

Essa é uma questão que surgiu recentemente no meu trabalho. A minha opinião é a seguinte:

Não diria que é incorreto do ponto de vista DDD mas acredito que o melhor é, sempre que for possível, manter os metodos do Service da aplicação com parametros de tipos básicos. Se você tem um entity com muitos atributos talvez esteja na hora de quenrar esse objeto de domínio em outros formando um agregado. Isso é correto do ponto de vista DDD!

Outra coisa, cuidado ao pensar em CRUD e DDD ao mesmo tempo!

Abs,

rodrigoy

cmoscoso:
A minha opinião é a seguinte:
Não diria que é incorreto do ponto de vista DDD mas acredito que o melhor é, sempre que for possível, manter os metodos do Service da aplicação com parametros de tipos básicos.

O que ganhamos com isso?

C

rodrigoy:
cmoscoso:
A minha opinião é a seguinte:
Não diria que é incorreto do ponto de vista DDD mas acredito que o melhor é, sempre que for possível, manter os metodos do Service da aplicação com parametros de tipos básicos.

O que ganhamos com isso?

Se você tem uma facade na aplicacao vai ganhar uma interface simples do ponto de vista do cliente

  1. long criaUsuario(String name);

  2. long criaUsuario(Usuario usuario);

Pra quem está programando o cliente qual das duas opcoes lhe parece melhor? Afinal se aplicacao orquestra deixemos ela orquestrar!

Repito, não é errado do ponto de vista das regras de negocio, o que esta vazando na opcao 2 provavelmente é regra de aplicacao. Mas daí pra vazar regras de negócio é um pulo.

Quanto a quantidade de parametros necessarios para persistir um entity…

Sera mesmo que todos esses parametros sao necessários para apenas persistir o entity, ou seja, cria-lo no seu sistema? (geralmente vc precisa apenas de identificadores pra isso)

Deixando o CRUD de lado… Ou são todos esses parametros necessários para a execucao de alguma regra de negocio que tal entity participa?

Neste ultimo caso, modele o objeto de dominio em questao considerando a possibilidade dele existir no sistema mas nao estar pronto para alguma atividade de negocio relacionada. Tipo um usuario existe no sistema mas não pode fazer nada ainda pq nao preencheu um cadastro detalhado.

No caso de uma atualizacao nao vejo problemas em passar o proprio objeto de dominio a ser atualizado. Neste caso ele já é conhecido pelo usuarioda interface.

BiraBoy

Saquei,

Obrigado

Alessandro_Lazarotti

A assinatura de um método em DDD tem que dizer seu propósito, independente da infraestrura.
Se para isso for necessário passar um objeto populado que assim seja. Se para o negócio é mais claro tipo simples, tudo bem também.

Só não concordo em pensar:

… quem armazena informações no DDD são os Repositories. Eles não armazenam ou coletam identificadores, eles trabalham com Entities.

C

Lezinho:
… quem armazena informações no DDD são os Repositories. Eles não armazenam ou coletam identificadores, eles trabalham com Entities.

Como estamos falando de camada de visão, abstraia repositorios por um momento…

Na opcao 1 do exemplo que usei o cliente do service da aplicacao passa apenas um identificador do entity a ser criado e persistido (o nome do usuario).

Alessandro_Lazarotti

Camada de visão e aplicação não é domínio, portanto de nada tem haver com DDD. Pode usar EntityManager, Session, SQL direto na página via JSTL … Eu quando tenho CRUD simples sem intervenção do negócio não escrevo uma linha de código java, utilizo o DAO declarativo do Seam.

Mas tudo isso, de nada tem haver com DDD … [2]

C

Um dos problemas de utilizar a opção 1 é que ela deixa explícitas todas as propriedades que um usuário tem, de modo qua assinatura do método tende a ficar muito grande e horrível de usar. Além disso, você perde totalmente a idéia de orientação a objetos, onde os atributos de determinada entidade do mundo real ficam em objetos, e não soltas em forma de parâmetros.

Os objetos de domínio de sua aplicação geralmente transitam entre todas as camadas.

Att.

C
public class Usuario {
    private long id;
    private String name;
    private Date nascimetno;
    private char sexo;
    ...
    ...
    ...

    // construtor e metodos de usuario
}

public class AppService {
    public long criaUsuario(String name) {
        Usuario usuario = new Usuario(name);
        // código que persiste usuario e retorna id
    }
}

Onde tem “parâmetros soltos”?

Se você quiser instanciar e então passar o objeto de dominio para o método de AppService você estará fortalecendo a camada de visão, nada a ver com perder OO uma vez que não estamos falando da camada de domínio. Se isso é bom ou não, depende de cada caso, mas lembre-se que Smart UI é anti-pattern.

Por favor, releia meu último post para o BiraBoy.

sergiotaborda

Não é realista isso que vc falou.
Se eu persisto a entidade eu quero que todos os campos - inclusive os que não são entidade e inclusive os que dizem respeito a VO e/ou outras entidades sejam persistidos junto.
Se vc não fizer isso, vc terá que reler o objeto entity do banco ( que virá apenas com os identificadores) , copiar os campos que quer persistir e persistir de novo. Ups! a persistencia só guarda os identificadores, logo nunca ira guardas os dados. O que vc escreveu não é realista.
A persistencia persiste todos os dados da entidade. Se eles estão vazios, paciencia. Mas a persistencia é controlada pela validação dos campos e alteração dos valores, e não apenas pela ordem do programador de persistir.

Do ponto de vista do DDD é errado usar partições da entidade quando o processo diz respeito a ela.

validaUsuario ( String username, char[] senha) (1)
validaUsuario ( Uusario usuario ) (2)

Voce pode achar que pode ter um façade cuja assinatura seja 1
Mas isso apenas encapsula a criação do objeto usuário que tem que ser possivel recriar apenas com aquelas informações. Mas o façade faz parte da camada da aplicação onde o DDD não mete o nariz.
Mas na camada de dominio usar (1) é errado , já que isso seria o mesmo que usar 2 DTO que é exactamente o que DDD não quer.

Portanto (1) está certo na camada de aplicação e errado na de dominio. (2) pode estar certo em qualquer camada. Pode estar certo ou errado dependendo do isolamento que vc quer. Se vc quiser isolar os objetos do dominio, então estão certo. Mas isolar as entidades rápidamente degenera em usar assinaturas imensas onde todos os campos são passados . Isso é errado.

sergiotaborda
public class Usuario {
    private long id;
    private String name;
    private Date nascimetno;
    private char sexo;
    ...
    ...
    ...

    // construtor e metodos de usuario
}

public class AppService {
    public long criaUsuario(String name) {
        Usuario usuario = new Usuario(name);
        // código que persiste usuario e retorna id
    }
}

Onde tem “parâmetros soltos”?

Se você quiser instanciar e então passar o objeto de dominio para o método de AppService você estará fortalecendo a camada de visão, nada a ver com perder OO uma vez que não estamos falando da camada de domínio.

A camada de aplicação não pode persistir o entity. O que ela faz é adicionar o entity no repositorio. ( o repositorio irá persistir se, e apenas se, for necessário)

Vamos pensar que o usuario tem obrigatoriamente de ter uma password além de username e um perfil. Perfil é uma outra entidade.
(usuário não tem genero nem data de nascimento porque pode ser outro sistema)

A tela teria um campo para cada um com o perfil sendo um combobox.

Se eu fizer o que está sugerindo o sistema vai dar erro porque não é aceitável criar um usuário apenas com o nome. Ai eu tenho que passar o nome, a pass e o perfil no método para que ele crie o objeto internamente.
Isso é verboraico e rápidamente degenera para o uso de DTO ( por exemplo, passar um map com os valores)

Não é isto que queremos.

Depende do caso, existem diferentes “smarts” na ui.
Se a UI é MVC o model tem toda a liberdade de conversar com o resto do sistema usar as entities para isso.
A conversão entre os campos da tela e o entity é feita no proprio model ( que por def é um objeto de dominio) e portanto não ha nenhum problema nem ncessidade de usar façades com metodos com um monte de parametros.

Resumindo, não defensável que uma aplicação baseada em DDD use metodos com parametros em vez das entities, já que fazer isso é usar um mecanismo de DTO que é contrário a DDD.

C

Você não vai persistir apenas o login do usuário: vai querer diversas outras informações, como nome, email, etc. Vai passar tudo isso por parâmetro, como String e inteiros individuais? O seu código ficará horrível, com uma imensidão de parâmetros que são todos relacionados a um usuário, contudo, independentes do objeto usuário (ou seja, “soltos”).

Contudo, pelo que vi a sua intençao é criar o usuário apenas com o essencial, no caso de seu exemplo o identificador login, e depois popular as demais informações, certo? Qual é o sentido prático disso? Tudo isso para não permitir que sua entidade seja construída na camada de visão? Qual é o problema disso? Você está realmente disposto a fazer um acesso adicional desnecessário ao mecanismo de persistência?

O sergiotaborda explicou muito bem a questão.

C

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

feliperod

Eu não vejo problema nenhum na camada de visão estar acoplada ao domain. Na verdade o problema é quando o domain está acoplado à camada de visão. Se você estiver usando um framework que faça o bind recusivo pra você, o framework já fará isso pra você quando receber os parametros. Um framework que faz isso é o Struts2. Ele tem uma interface que se chama ModelDriven e que permite que a Action seja tratada como um wrapper para uma classe de Domain. Algo assim:

public class SuaAction implements ModelDriven {

   private Usuario user;

   public Usuario getModel(){
       return user != null ? user : new Usuario() 
   }

}

Dessa forma quando sua action receber um parametro nomeado "nome" ela executará

suaAction.getModel().setNome(request.getParameter("nome"))

Mas isso é transparente pra você.

Abração

feliperod

Lezinho:
Camada de visão e aplicação não é domínio, portanto de nada tem haver com DDD. Pode usar EntityManager, Session, SQL direto na página via JSTL … Eu quando tenho CRUD simples sem intervenção do negócio não escrevo uma linha de código java, utilizo o DAO declarativo do Seam.

Mas tudo isso, de nada tem haver com DDD … [2]

Isso não acaba gerando regras de negócio fora do domain? Acho que o domain é reponsável por tratar e resolver todo o problema do sistema, e o CRUD está incluso como problema do sistema.

Alessandro_Lazarotti

feliperod:
Lezinho:
Camada de visão e aplicação não é domínio, portanto de nada tem haver com DDD. Pode usar EntityManager, Session, SQL direto na página via JSTL … Eu quando tenho CRUD simples sem intervenção do negócio não escrevo uma linha de código java, utilizo o DAO declarativo do Seam.

Mas tudo isso, de nada tem haver com DDD … [2]

Isso não acaba gerando regras de negócio fora do domain? Acho que o domain é reponsável por tratar e resolver todo o problema do sistema, e o CRUD está incluso como problema do sistema.

Se vc preenche um formulário, clica no botão e os dados são persistidos e validados sem você precisar programar, não existe mal que isso fique em um framework (acredite, isso é possível com frameworks como o Jboss Seam). Não é preciso DDD para isso pois Domain Driven é para construir o Design do código, mas já que você não precisou codificar, portanto não precisou do design.

Se seu CRUD ficar mais complexo, então neste momento você constrói classes para isso com DDD… mas note que você não precisou disto no primeiro momento e pode ser que nao precise para o sistema inteiro. Programação incremental é uma ótima aliada a metodologias ágeis e não fere preceitos de design.

feliperod

Lezinho:

Se vc preenche um formulário, clica no botão e os dados são persistidos e validados sem você precisar programar, não existe mal que isso fique em um framework (acredite, isso é possível com frameworks como o Jboss Seam). Não é preciso DDD para isso pois Domain Driven é para construir o Design do código, mas já que você não precisou codificar, portanto não precisou do design.

Se seu CRUD ficar mais complexo, então neste momento você constrói classes para isso com DDD… mas note que você não precisou disto no primeiro momento e pode ser que nao precise para o sistema inteiro. Programação incremental é uma ótima aliada a metodologias ágeis e não fere preceitos de design.

Concordo com você em relação à aplicação ser simples o suficiente pra não usar DDD. Mas numa aplicação complexa, onde já estamos usando DDD, deixar o CRUD fora do domain não seria bobagem? O CRUD não acrescenta muito código ao domain.

E no caso de não utilizar o Seam? Mesmo caso. Você não terá um framework para isso.

Outra situação é se o domain é o mesmo para várias interfaces, então é bom que seu domain faça o trabalho todo do sistema, deixando só a persistência e a visão para ser trocada.

Alessandro_Lazarotti


Concordo com você em relação à aplicação ser simples o suficiente pra não usar DDD. Mas numa aplicação complexa, onde já estamos usando DDD, deixar o CRUD fora do domain não seria bobagem?

Mas eu não me referi a aplicações simples, nem para aplicações que não usam DDD. Me referi a frameworks que lhe dão subsídios para que você não perca tempo com o arroz e feijão.

Você pode ter complexas aplicações modeladas em DDD e mesmo assim utilizar recursos prontos de terceiros que lhe dão produtividade e não impactam em sua modelagem. CRUD é CRUD, se alguém me oferece isso de graça, eu não quero gastar nenhuma linha de código para isso… SE precisar e QUANDO precisar especializar este processo, isso será feito sem impacto algum. Este processo pode ser simples ao Domínio, mas é muito rotineiro o que acaba impactando na produtividade.

Obviamente, caso não trabalhe com algum framework que ofereça estes serviços, a melhor saída é se manter com a própria modelagem… ou desenvolver seu próprio framework caseiro que cuide disso.

rodrigoy

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.

feliperod

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.

C

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.

C
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 !

C

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.

C

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. :)

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.

sergiotaborda

cmoscoso:

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

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.

C

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.

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.

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.

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.

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

C

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

sergiotaborda

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.

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.

brunohansen

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.

rodrigoy

Hum… e os Action Frameworks?

sergiotaborda

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.

brunohansen

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.

sergiotaborda

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.

Criado 8 de novembro de 2007
Ultima resposta 28 de nov. de 2007
Respostas 34
Participantes 8