Discordo. O princípio de separação de responsabilidade alega que quem detém a informação é o responsável pela ação. Mas os DTOs não são detentores de informação nenhuma, é só um objeto repleto de atributos distintos.
Um Aluno englobar o que é inerente ao aluno não vejo como problema. Aliás, o que há de errado em se retornar um Aluno quando se solicita um Aluno?Ao menos para mim é estranho você retornar um objeto alienígena toda vez que solicitar uma entidade.
[quote=mvcsouza]
Além disso, o cara aí em cima lembro muito bem a facilidade em usar este padrão com os frameworks MVC que assumem este que DTO será o padrão usado na modelagem das classes de dados. [/quote]
Qual framework em específico assume que você utilizará um DTO?
[quote=jdeveloper] é uma classe de cadastro…então tem nome,idade,rg,cep,cpf,etc…
enfim…tem pelo menos 20 atributos…
20 atributos + 20 get + 20 set + os métodos de negócio…é bastante, não acha?[/quote]
1 - Talvez vc possa melhor seu modelo. Por exemplo, quando houver muita coisa, talvez vc possa quebrar esta classe em outras responsabilidades. Por exemplo, vc poderia criar uma classe Endereco. Na classe endereco vc coloca o endereco, cidade, bairro, rua, cep e etc…
Tente identificar em suas classes que é possível melhorá-las, e desacoplar dados em comum em uma outra classe!
2 - Não vejo problemas caso haja 20 atributos e 40 getters e setters em sua classe. Se vc não tiver como fugir dos getters e setters, e só vc se organizar. Por exemplo:
Se organize, que cria algumas convenções como por exemplo, deixe todos os seus métodos de negócio no final da classe! Assim, se vc tiver que trabalhar em algum método de negócio, vc sabe que a única coisa a fazer é se mover para o final do arquivo e encontrar o seu método de negócio!
Com os recursos das IDE´s que temos hoje, como o eclipse por exemplo, segure o control e clique com o mouse em cima do método que ele já te leva para a implementação do método!
Não há pq separar uma classe contendo só os métodos de negócio!
E falando nisso, fazer em duas classes nao ficaria maior nao? Alem de ter um outro .java enchendo o saco.
]['s[/quote]
Se for pensar assim (quanto menos classes melhor)…então faz tudo em uma classe só…os dados do aluno as regras de negocio e os metodos de persistencia… eu acho q fica muito feio!
Você pode me dizer como? Qual a responsabilidade do DTO e do tal BO?
A responsabilidade do DTO é pegar os dados do BO e passar para outro canto? Porque você não passa o BO?
Neste modelo você vai ter lógica de negócios altamente acoplada ao DTO, DTO altamente acoplado ao BO e View altamente ao DTO.
Lembre que dependência é transitiva, então tudo continua dependendo de tudo, e com mais o DTO no meio. Talvez assim seja melhor:
Como assim?
Para você faz mais sentido criar uma classe B que é uma cópia burra de outra classe A, e que no fim B vai ser usado para gerar um A?
Por que você não gera A em primeiro lugar? Qual o benefício do itnermediário?
[quote=mvcsouza]
Além disso, o cara aí em cima lembro muito bem a facilidade em usar este padrão com os frameworks MVC que assumem este que DTO será o padrão usado na modelagem das classes de dados. [/quote]
Não existem (ou pelo menos não deveriam existir) “classes de dados” num modelo baseado em objetos.
Na verdade, me parece que o problema é um só: separação de responsabilidades. Pelo que você falou, seu entendimento de OOP o faria entupir o tipo com todos os métodos referentes a ele, na verdade você deveria separar as reponsabildiades entre outras classes.
Se você puder citar alguns casos problemáticos da tal classe, podemos trabalhar esse exemplo.
Bom, eu concordo em geral, mas não neste ponto. primeiro porque eu trabalho e trabalhei com projetos grandes e compelxos ao extremo, e os princípios de OOD foram formados baseados em projetos muito mais complexos do que eu ou a grande maioria dos frequentadores do GUJ pode sonhar em meter a mão.
Você consegue criar alunos capazes de se persistir e mantendo um código legível…
Como já rolou em outras discussões aqui no guj, Active Record é interessantíssimo, e além do mais, existem outras maneiras de seu objeto ser capaz de se persistir, desde que ele acesse uma interface que possui os métodos de persistência!
Ou seja, vc teria uma classes com seus métodos de persistência desacoplado da sua lógica de negócio, e sua classe de negócio é que diz quando ele deve ser persistido ou não!
A pergutna é, para cada objeto de negócio você pode depender apenas do objeto em questão ou gerar uma dependência desnecessária utilizando um DTO. Para um exemplo com uma classe não aprece muito, mas isso vai crescer expotencialmente num sistema de verdade, e cada vez que você alterar uma coisa, vai alterar todo o ciclo de dependência.
O ponto é: em termos de acoplamento e dependência, DTO só piora.
Isso é programação procedural e existem ferramentas melhores para programar assim do que Java.
Vamos analisar o fluxo:
1 - Com DTO
2 - Sem DTO
Semrpe existe essa possiblidade, um bom projetista vais aber avaliar o custo/beneficio de toda flexibilidade.
Nesse caso especifico, você está falando de um cenário onde um DTO é um bom negócio. O que nós estamos discutindo é onde ele não é um bom negócio.
Acho que entendi seu ponto. O poblema é que você está colocando responsabilidades demais em Aluno.
Um aluno tem por responsabilidade executar suas regras de negócio (entrar em um curso, sair do curso, retornar seu boletim, sei lá…), o que você está falando é em misturar as responsabilidades de outras classes no aluno, por isso pedi um exemplo
Code-folding são aquelas setinhas que aparecem do lado do código para poder abrir/fechar o código. Assim ficam escondidas as linhas de código que não precisa ficar olhando o tempo todo. Acho que tem no Netbeans!
Sobre setters, é exatamente o contrário do que falou hehe quebrar o encapsulamento é chamar esses getters/setters de fora. Para preencher os atributos de seu objeto, use o construtor
Sobre a ausência de getters/setters, leia meus favoritos! Isso foi amplamente discutido aqui no fórum, recomendo a leitura.
E falando nisso, fazer em duas classes nao ficaria maior nao? Alem de ter um outro .java enchendo o saco.
]['s[/quote]
Se for pensar assim (quanto menos classes melhor)…então faz tudo em uma classe só…os dados do aluno as regras de negocio e os metodos de persistencia… eu acho q fica muito feio! [/quote]
jdeveloper,
Mas estamos falando de duas classes que dizem respeito ao mesmo Objeto, no caso aluno. Nao da pra generalizar como tu fez.
mvcsouza entenda que não estamos falando que DTOs nunca devem ser usados. Só estamos dizendo que só devem ser usados em ambientes altamente distribuídos APÓS ter certeza absoluta que a carga de rede está exagerada.
E também não estamos falando para colocar todo o código dentro de Aluno. Mas é dividir as responsabilidades com coerência:
Ao inves de:
class Action {
Aluno aluno = new Aluno();
AludoDAO dao = new AlunoDAO();
dao.save( aluno );
}
Fazer:
class Action {
public void go() {
Aluno aluno = new Aluno();
aluno.save( aluno );
}
}
class Aluno {
public void save() {
dao.save( this );
}
}
Como deve bem saber por ter participado de projetos grandes, a primeira abordagem rapidamente se torna um inferno de manutenção com código repetido espalhado por todo o projeto.
Muito bém colocado! Com certeza, este é um fator que pode ser um diferencial em um projeto de grande porte!
Hoje estou fazendo refactoring em uma aplicação o o programador usou bastante buffer.write()., buffer.newLine() e buffer.flush(); sempre usando a mesma sequência! O texto que estava sendo passado dentro dos métodos Estava em inglês!
Dái, me abriram um bug para passar para Português! Pronto! Ferrou!
Essa rotina que usava 5 linhas se repete em média 12x distribuidamente em 17 queridas classes!
17 x 12 X 5 = 1020
Agora com meu refactoring, o q antes estava usando 5 linhas começara a uasr 2 linhas, entaum:
17 * 12 * 2 = 408
logo
1020 - 408 = 620
Nessa brincadeira estou eliminando 620 linhas de código desnecessárias.
Acho que este seria um exemplo simples para ilustrar como algumas rotinas repetitivas (mesmo que bém organizadas) podem ser simplificadas!
Fazer este refactoring nisso está super dispendioso, e vou com certeza levar mais de um dia para terminar!
mvcsouza, em minha opinião, acho que sempre que possível é melhor optar pela simplicidade! Apesar de vc gostar desta estrutura com TO, acredito que não usar o TO torne a aplicação mais simples, e até mesmo mais desafiador.
Isto ao meu ver especializa o código e não espalha código como alguns
colegas disseram. O desenvolvedor sabe com base no padrão onde está
cada especialidade de código, seja validação, persistência e negócio. Além
disso, a comunicaçào das mensagens entre as camadas se dá de forma
muito mais otimizada, e de quebra eu não preciso alterar o meu código se
algum dia precisar fazer uma chamada remota!
Otimizada por que?
Você cria uma classe a mais para cada classe de negocio hoje para evitar que num futuro que pode acotnecer ou não (o mais provável) você não precise criar uma classe para todas as operações remotas (que pode ser uma Session Façade, por exemplo)?
Me diz qual a vantagem de fazer isso e criar uma Façade Remota que retorna e recebe objetos “Aluno”.
E, novamente, qual exemplo você dá de uma classe que tenha tanta regra de negócio que fica impraticável utilizar OOP?
Um outro problema no codigo eh o servlet tocando a camada de persistencia diretamente, utilize uma camada de aplicação leve para isso.
Existe uma diferença entre layer e tier. Utilizar DTOs para passar entre layers é besteira se stas ficam na mesma tier. Essa é a discussão. Se você ler o tópico, vai ver que todos aqui comentaram que DTO é sim válido para chamadas remotas. É um mal necessário.
Entretanto, pelo menos num ambiente normal, dificilmente você terá interfaces remotas que justifiquem um DTO. Mesmo onde você tem tais interfaces, é conveniente utilizar um profiler, verificar o tamanho dos objetos serializados, tráfego na rede e todas as outras variáveis para definir o DTO a ser utilizado, lembro que não rpecisa haver um mapeamento de 1 para 1 entre DTO e objeto, pelo contrário, é melhor você colcoar vários objetos num só DTO para economizar recursos.
Sou contra soluções tamanho-unico, mais ainda se envolve EJB. nos projetos em que trabalho varia sempre, e semrpe tentando eliminar ao máximo de EJB em função de tecnologias mais leves.
Pergunta simples:
Sabendo que o problema em trafegar dados em um sistema distribuído numa rede é basicamente o RPC e necessidade constante de trocar dados o tempo todo, o padrão DTO é utilizado para minimizar estas chamadas. Se seus DTOs são menores que um objeto de verdade, qual a vantagem em utilizá-los ao invés de apenas mandar o objeto?
Economizar alguns bytes na transmissão? Vale a pena aumentar a complexidade do seu projeto, criando uma classe só com estado, outra só com comprotamento, só para passar menos dados numa rede?
O real problema de transmissão em sistemas distribuídos não é o tamanho dos objetos individualmente, que geralmente é insignificante, mas sim a quantidade de vai-e-vem de dados o tempo todo e o tamanho do grafo de objetos que deve ser passado, que vaid epender basicamente do que o cliente vai fazer com os objetos.
No exemplo, se AlunoDTO tem uma referencia a um CursoDTO (ou curso BO, nao sei como vc prefere relaciona-los), e CursoDTO tem referencias a diversos outros AlunoDTO, que tem referencias a outros CursoDTo que por sua vez referenciam mais AlunoDTO… como seu DTO te ajuda a melhorar o desempenho?
A discussão já está descambando para a melhor estratégia em um DTO, mas o meu ponto é que não vale a pena complicar sua camada de negocios e criar classes que não obedecem os principios basicos de OOP para um requisito que:
1 - Não é onipresente (pelo contrário, é bem infrequente. Quantos aqui tem a camada de negocios em um servidor e a de web em outro na maioria dos projetos? Quantos viram isso uma ou duas vezes? Quantos nunca viram isso?)
2 - Pode existir, mas não ser necessário o uso de DTO (POJOs podem dar cotna do recado em muitos casos)
3 - Se realmente necessário, pode ser solucionado de uma forma melhor, usando Transfer Object Assemblers em cima de objetos de negócio.
Penso, mas não consigo entender porque você não consegue distribuir isso em objetos ao invés de usar registros.
A técnica se chama Programação em Camadas e Separaçãod e Responsabilidades, você poderia implementar uma Camada de Aplicação (Application Layer) utlizando, por exemplo um façade, ao invés de acessar o DAO de vez, atropelando a Camada de Negócios.
Como falei, fazendo o teste você vai comprovar que não importa passar 50kb a menos, o que importa é minimizar a comunicação, apra isso um DTO empacota tudo que o cliente vai rpecisar, esta é sua finalidade.
Como num mesmo nó você não tem dificuldade em comunicação (está tudo no mesmo espaço de endereçamento), você não vai precisar de um DTO.
Perdão, você está certo, eu não havia vista que começava outro arquivo no meio da tag [ code ], era isso que eu estava dizendo.
[quote=mvcsouza]
A questão agora em minha mente é:
Até onde vai a inteligência da Entidade?? Aluno tem que saber fazer o que com ele mesmo? Quando eu passo para o BO??[/quote]
O BO é o aluno. Isso resume OOP. Estado e comprotamento no mesmo construto.
Agora se você está pergutnando se o aluno tem que ter toda a lógica referente a ele, a respsota é simplesmente: não. Por que? Por que muitas relações em que o aluno participa são de responsabilidade de outros objetos, e devem ser distribuídas.
Imagina o seguinte:
Pelo que eu estou entendendo do seu ponto de vista (eu posso muito bem não ter entendido nada, ams é o que eu acho), o aluno deveria ter algo assim:
class Aluno{
public void avisarAusenciaProfessor(Professor ausente){...}
}
Mas não, pdoe muito bem ser assim:
class Turma{
List<Aluno> alunosInscritos= ...
boolean vaiTerAulaHoje = true;
public void avisarAusenciaProfessor(){
vaiTerAulaHoje=false;
}
public boolean vaiTerAulaHoje(){ return vaiterAulaHoje;}
}
class Aluno{
List<Turma> turmas = ...
public void vaParaAAula(){
turma turmaDeAgora = descobrirQualTurmatemAulaAgora();
if(turmaDeAgora.vaiterAula()){
assitirAulta(turmaDeAgora();
}
else{
irAoCinema();
}
}
}
Isso foi um exemplo idiota, mas o princípio é este: separar responsabilidades.
Você não está rompendo a separação de camadas se não tocar uma camada que nãoe steja ligada, no caso do save(), não há problema.
Eu sabia que esse artigo ia causar coisas deste tipo
Eu tenho essa revista e estou inclusive escrevendo um post no meu blog sobre isso. Fernando Lozano é sim um cara muito respeitado, mas o que ele afirma não tem fundamento na literatura.
Essa coisa de “antigamente se acahva tal, hoje em dia se acha isso” sem nenhuma referência, sem nenhum motivo (caso seja ele mesmo o autor da teoria), não me parece válido.
Tivemos uma discussão sobre um outro artigo dele aqui, eu o convidei para entrar mas parece que ele não teve tempo de participar.
Eu acho terrivelmente equivocada esta abrodagem e lamento que seja divulgada num veículo tão abrangente como a Java Magazine sem qualquer referência de onde se possa ter mais informação sobre essa teoria.
Segundo o que já li, o futuro da orientação a Objetos é ser Estruturada, com dados de um lado e lógica de outro. Isso não me parece sensato.
Finalmente algum tipo de esclarecimento. Realmente eu estava confuso com este tópico, pois o artigo do Fernando Lozano foi um dos meus primeiros contatos com patterns…
Para mim sempre foi regra que: aluno.save() é ruim!