Loucura minha ou faz sentido?

Olá pessoal,

Inicialmente, sou novo nesse fórum e na parte de arquitetura. Ainda tenho MUITO o que estudar, e vou fazê-lo. Ademais, gostaria de pedir que caso eu fale alguma boa abobrinha, me perdoem pois sou realmente novo na parte de arquitetura.

Mas bem, eu estava pensando aqui e vi que na aplicação nós temos muitos POJOs, muitos DTOs, e todos eles com vários getters e setters. E bem, eu entendo o pojo como sendo apenas o repositório de dados da coisa toda, logo, nenhum Getter/Setter na minha opinião deve conter lógica alguma, nem uma conversão sequer. E bem, eu estava pensando em fazer algo mais ou menos assim:

Pojo: Student.java

package xyz;

public class Student {
	private String studentName;
	private String studentGrade;

	public Student(String studentName, String studentGrade) {
		this.studentName = studentName;
		this.studentGrade = studentGrade;
	}
}

DataExtractor: StudentExtractor

package xyz.extractor;

public class StudentExtractor{

	//método básico de getInstance();
	
	public String getStudentName(Student student){
		//Por reflection, muda a permissão do atributo do objeto
		//e assim consegue retornar o resultado como quiser, ex:
		Student readableStudent = Utils.unlockObject(student);
		return student.studentName + "teste";
	}
}

Nesse caso, eu teria getters e setters em apenas um objeto, separado, não pelas instâncias dos objetos, assim como o meu simples POJO seria Lock e essa classe de Extractor, por ex, não seria acessível à todos os commiters do projeto, por exemplo. O POJO serviria apenas como depósito mesmo de dados, nenhuma lógica e nem getter e setter nessa história.

Obviamente teria como trabalhar melhor essa classe de Extractor, criando uma superclasse ou até mesmo um abstract.

O que me preocupa aí talvez é o tempo que a JVM levaria pra converter a permissão do atributo de private p/ public.

Faz sentido ou é loucura minha mesmo? rs. O que vocês acham?

Obrigado!

A mairoria dos frameworks Java requerem obrigatoriamente gets e sets seguindo a convenção de nomenclatura da Sun.

Logo sua solução tornaria-se inviável diante a necessidade de usar JPA, JSF, etc…

[quote=Giulliano]A mairoria dos frameworks Java requerem obrigatoriamente gets e sets seguindo a convenção de nomenclatura da Sun.

Logo sua solução tornaria-se inviável diante a necessidade de usar JPA, JSF, etc…[/quote]

Olá Giulliano,

Obrigado. Você está certo, não havia me dado conta disso.

[]'s!

Sem contar que seu objeto seria imutável, uma vez que para alterar o nome do estudante eu teria que criar outro objeto na memória. Aí vc poderia criar um método trocarNome(String nome); que não passa de um setNome(String nome)

;0

Giulliano, a questão da imutabilidade colocada por você é relevante. Mas quanto à obrigatoriedade de getters e setters, é preciso lembrar que o Hibernate/JPA não a exige, desde que os atributos da entidade sejam anotados ao invés dos getters.

Fiquei 10 minutos olhando minunciosamente o código para tentar descobrir o que ele faz. Achava que havia alguma coisa especial nesse extrator, mas não, era apenas porque você queria separar os getters/setters do próprio objeto. Minha opinião: não faz sentido nenhum! Qualquer coisa que não seja inteligível de bate-e-pronto é uma má idéia. Imagine o cara de manutenção precisar de 10 minutos em cada classe pra poder entender um mecanismo tão básico. O nível de produtividade vai ao chão!

Além disso, existe um conceito que você não está considerando: métodos são polimórficos, atributos não são! Essa diferença está sendo esquecida na sua implementação de Extrator, e pode ser fonte de bugs sutis.

O problema fundamental é um conceito bastante equivocado:

Um Pojo é qualquer classe não contenha conceitos de infraestrutura, ou seja, pode ter getters/setters com e sem lógica, pode ter métodos sem o padrão JavaBeans. A sua classe Student teria os atributos, alguns getters e setters, métodos de conversão, lógica e qualquer coisa relacionada a estudante.

Sinceramente, para aplicações web, usar JavaBeans puro é idiotice. Eu não faço isso em minhas aplicações, e o sistema não ficou com menos performance, escalabilidade, manutenibilidade ou qualquer-outra-abobrinha-lidade.

Quando eu disse que o JPA requer getters e setters não estava me referindo às anotações e sim ao modo o qual o framework obtem os valores do objeto. Se vc tem uma entidade com dois atributos privados como eu faço para acessar seus valores atráves de outro objeto ???

Pra isso serve o get e set. Metaprogramação e Relection.

[quote=Leonardo3001]Fiquei 10 minutos olhando minunciosamente o código para tentar descobrir o que ele faz. Achava que havia alguma coisa especial nesse extrator, mas não, era apenas porque você queria separar os getters/setters do próprio objeto. Minha opinião: não faz sentido nenhum! Qualquer coisa que não seja inteligível de bate-e-pronto é uma má idéia. Imagine o cara de manutenção precisar de 10 minutos em cada classe pra poder entender um mecanismo tão básico. O nível de produtividade vai ao chão!

Além disso, existe um conceito que você não está considerando: métodos são polimórficos, atributos não são! Essa diferença está sendo esquecida na sua implementação de Extrator, e pode ser fonte de bugs sutis.

O problema fundamental é um conceito bastante equivocado:

Um Pojo é qualquer classe não contenha conceitos de infraestrutura, ou seja, pode ter getters/setters com e sem lógica, pode ter métodos sem o padrão JavaBeans. A sua classe Student teria os atributos, alguns getters e setters, métodos de conversão, lógica e qualquer coisa relacionada a estudante.

Sinceramente, para aplicações web, usar JavaBeans puro é idiotice. Eu não faço isso em minhas aplicações, e o sistema não ficou com menos performance, escalabilidade, manutenibilidade ou qualquer-outra-abobrinha-lidade.
[/quote]

Concordo plenamente com o Leonardo, nao tem porque separar dados da regra, alias tem muitos porques pra deixa-los juntos.

Outra coisa que chamou a atencao, e como o Leonardo ja citou, foi a sua definicao de POJOs. POJOs sao classes simples que nao implementam nenhuma interface e nao extendem nenhuma classe por pre-definicao. Implementam ou extendem se voce quiser que facam, nao porque algum framework obriga.

A intenção inicial disso é não deixar que todos os desenvolvedores tenham acesso direto às regras. Seria meio que por várias libs. Em sistemas bancários por exemplo, por exigência do cliente, não é bom que todos os desenvolvedores conheçam as regras. Os arquitetos sim, mas os desenvolvedores não. Por exemplo se fosse usar algo como DDD. Não me chutem, mas tem clientes que exigem este tipo de coisa, e na minha idéia pessoal o desenvolvedor DEVE conhecer todo o código ou se especializar bem em algumas coisas, pois agiliza muito bem.

Sobre polimorfismo, os atributos realmente não são, mas os mesmos métodos do Extractor poderiam ser polimórficos.

E lembrando que Student é um exemplo muito simples, e apenas um rascunho.

[]'s!

Olha só…eu acho que o Analista Desenvolvedor deve conhecer toda a regra de negócio referente ao módulo que ele trabalhe e quando houver fronteiras entre o módulo que ele desenvolve com algum outro módulo basta que ele saiba o que enviar e o que receber.

Conhecer toda a regra de negócio só é possível quando falamos de sistemas médios a pequenos. Imagina conhecer toda a regra de negócio de um banco (incluindo aí seguro de vida, previdência, empréstimo, segurança, análise de riscos, e por aí vai).

Já o programador não precisa conhecer regra de negócio apenas codificar aquilo que lhe foi passado justamente para que ele não mude uma implementação por achar que conhece a regra.

Quando eu disse que o JPA requer getters e setters não estava me referindo às anotações e sim ao modo o qual o framework obtem os valores do objeto. Se vc tem uma entidade com dois atributos privados como eu faço para acessar seus valores atráves de outro objeto ???

Pra isso serve o get e set. Metaprogramação e Relection.[/quote]

Se o framework que vc esta falando é o Hibernate, realmente não precisa de get e set, ele vai por reflection, então com relação a persistência, não teria problema não termos o get e set, já na parte web, ai sim temos problemas, que a maioria do framework web, segue este padrão “burro” de get e set.

Quando eu disse que o JPA requer getters e setters não estava me referindo às anotações e sim ao modo o qual o framework obtem os valores do objeto. Se vc tem uma entidade com dois atributos privados como eu faço para acessar seus valores atráves de outro objeto ???

Pra isso serve o get e set. Metaprogramação e Relection.[/quote]

Se o framework que vc esta falando é o Hibernate, realmente não precisa de get e set, ele vai por reflection, então com relação a persistência, não teria problema não termos o get e set, já na parte web, ai sim temos problemas, que a maioria do framework web, segue este padrão “burro” de get e set.[/quote]

Só uma correção: nos frameworks, independente de ir por get/set, é usada a reflexão. A diferença é que sem o get/set é necessário deixar o objeto Field acessível pelo método setAccessible, já com os métodos é feita uma chamada ao método invoke do objeto Method correspondente ao método desejado.

Lembrando que deixar o objeto acessível não é torná-lo público pois apenas a instância de Field destravada pode ser acessada para leitura e, desde que não seja “final”, alteração de valor.

Ah, reparei numa coisa…

Vc falou q vcs tem muitos DTOs. Existe MESMO a necessidade de usá-los ? O único case em Java q eu conheço que REALMENTE precisa de DTO é usando EJB 2.1 (que já é meio antigo… )

[]´s

[quote=asaudate]Ah, reparei numa coisa…

Vc falou q vcs tem muitos DTOs. Existe MESMO a necessidade de usá-los ? O único case em Java q eu conheço que REALMENTE precisa de DTO é usando EJB 2.1 (que já é meio antigo… )

[]´s[/quote]

Não. DTO você pode usar em outras coisas, como por exemplo, uma aplicação com EJB3 remoto ou quando você precisa de transformações nos objetos e afins.

[quote=garcia-jj][quote=asaudate]Ah, reparei numa coisa…

Vc falou q vcs tem muitos DTOs. Existe MESMO a necessidade de usá-los ? O único case em Java q eu conheço que REALMENTE precisa de DTO é usando EJB 2.1 (que já é meio antigo… )

[]´s[/quote]

Não. DTO você pode usar em outras coisas, como por exemplo, uma aplicação com EJB3 remoto ou quando você precisa de transformações nos objetos e afins.[/quote]

No caso do EJB3, não precisa não : a própria entidade pode ser trafegada, sem crise. Quando você precisa de transformações nos objetos? Humn… boa pergunta, não consigo imaginar um caso real, mas acredito que um façade deveria resolver.

O lance do EJB3 dá pra conferir no http://www.guj.com.br/posts/list/97993.java

Segundo PoEAA:

[quote=http://martinfowler.com/eaaCatalog/dataTransferObject.html]
When you’re working with a remote interface, such as Remote Facade (388), each call to it is expensive. As a result you need to reduce the number of calls, and that means that you need to transfer more data with each call. One way to do this is to use lots of parameters. However, this is often awkward to program - indeed, it’s often impossible with languages such as Java that return only a single value.

The solution is to create a Data Transfer Object that can hold all the data for the call. It needs to be serializable to go across the connection. Usually an assembler is used on the server side to transfer data between the DTO and any domain objects.

Many people in the Sun community use the term “Value Object” for this pat-tern. [/quote]

DTO tem seu uso em qualquer tecnologia com invocação remota, não importa se é EJB 2, EJB 3, SOAP/WS-*, REST ou raw sockets.

[quote=asaudate]No caso do EJB3, não precisa não : a própria entidade pode ser trafegada, sem crise. Quando você precisa de transformações nos objetos? Humn… boa pergunta, não consigo imaginar um caso real, mas acredito que um façade deveria resolver.

O lance do EJB3 dá pra conferir no http://www.guj.com.br/posts/list/97993.java[/quote]

asaudate, negativo. Até porque essa coisa de trafegar entidade persistente entre camadas funciona para aplicações simples e quando o módulo WEB está conectado direto no módulo EJB. Quando você tem, no caso do meu atual projeto, um módulo EJB e uma série de projetos clientes que acessam esse módulo EJB remoto você não pode ser dar ao luxo de mandar a entidade persiste. Até porque assim você expõe toda sua persistência.

E como você resolve os casos de lazy-load? Não existe lazy-load após sair da camada EJB. O que existe é umas gambiarras com o open-session-in-view que não existe como fazer em módulo EJB stand-alone.

Além disso, um exemplo de um projeto escolar, se eu tenho uma tela que preciso das informações do boletim do aluno, do proprio aluno e da escola. Como faço? Fico chamando um a um causando um overhead de trafego? Não, aí eu uso DTO carregando os dados que eu preciso, transformando, e devolvendo isso no método.

Usar DTO naqueles caso que você tem um site e afins não faz sentido, até porque tudo que você retorna basicamente estão nas entidades. Porém em projetos maiores e mais complexos normalmente você precisa de dados de forma diferente, precisa muitas vezes transformar e inclusive trazer dados de mais de uma entidade.

Um outro exemplo é quando você precisa expor seus dados em um webservice. Você vai serializar seu projo de usuário com senha e tudo? Mesmo que criptografada a senha não é legal isso. Então você cria um DTO com os dados e envia ao webservice.

No tópico que você mandou diz exatamente isso. :thumbup:

Abraços

[quote=garcia-jj][quote=asaudate]No caso do EJB3, não precisa não : a própria entidade pode ser trafegada, sem crise. Quando você precisa de transformações nos objetos? Humn… boa pergunta, não consigo imaginar um caso real, mas acredito que um façade deveria resolver.

O lance do EJB3 dá pra conferir no http://www.guj.com.br/posts/list/97993.java[/quote]

asaudate, negativo. Até porque essa coisa de trafegar entidade persistente entre camadas funciona para aplicações simples e quando o módulo WEB está conectado direto no módulo EJB. Quando você tem, no caso do meu atual projeto, um módulo EJB e uma série de projetos clientes que acessam esse módulo EJB remoto você não pode ser dar ao luxo de mandar a entidade persiste. Até porque assim você expõe toda sua persistência.

E como você resolve os casos de lazy-load? Não existe lazy-load após sair da camada EJB. O que existe é umas gambiarras com o open-session-in-view que não existe como fazer em módulo EJB stand-alone.

Além disso, um exemplo de um projeto escolar, se eu tenho uma tela que preciso das informações do boletim do aluno, do proprio aluno e da escola. Como faço? Fico chamando um a um causando um overhead de trafego? Não, aí eu uso DTO carregando os dados que eu preciso, transformando, e devolvendo isso no método.

Usar DTO naqueles caso que você tem um site e afins não faz sentido, até porque tudo que você retorna basicamente estão nas entidades. Porém em projetos maiores e mais complexos normalmente você precisa de dados de forma diferente, precisa muitas vezes transformar e inclusive trazer dados de mais de uma entidade.

Um outro exemplo é quando você precisa expor seus dados em um webservice. Você vai serializar seu projo de usuário com senha e tudo? Mesmo que criptografada a senha não é legal isso. Então você cria um DTO com os dados e envia ao webservice.

No tópico que você mando diz exatamente isso. :thumbup:

Abraços[/quote]

Tem razão, não tinha pensado no caso de vários tipos de clientes remotos. Aí, até vale a pena você esconder algumas coisas e expôr outras de um jeito diferente. No lance do lazy-loading, penso eu que (pra sistemas simples), é melhor forçar a carga no façade… pra sistemas complexos, não tem jeito, é DTO mesmo.

Abraços

[quote=Rubem Azenha]Segundo PoEAA:

[quote=http://martinfowler.com/eaaCatalog/dataTransferObject.html]
When you’re working with a remote interface, such as Remote Facade (388), each call to it is expensive. As a result you need to reduce the number of calls, and that means that you need to transfer more data with each call. One way to do this is to use lots of parameters. However, this is often awkward to program - indeed, it’s often impossible with languages such as Java that return only a single value.

The solution is to create a Data Transfer Object that can hold all the data for the call. It needs to be serializable to go across the connection. Usually an assembler is used on the server side to transfer data between the DTO and any domain objects.

Many people in the Sun community use the term “Value Object” for this pat-tern. [/quote]

DTO tem seu uso em qualquer tecnologia com invocação remota, não importa se é EJB 2, EJB 3, SOAP/WS-*, REST ou raw sockets.[/quote]

O que o Fowler está citando é o caso de múltiplas chamadas. Quanto a isso, é válido, vc encapsula parâmetros em um objeto pra fazer a invocação, mas no EJB 3 vc não realiza uma invocação de rede quando está usando os POJOS que voltaram de uma chamada remota. Foi isso q eu quis dizer com o caso do EJB 3 - em comparação com EJB 2, vc SEMPRE precisa fazer DTOs . Em EJB 3, nem sempre. Quanto ao caso de retorno de listas… bem, interfaces e classes abstratas e façades existem pra isso ^^

[]´s