Acabei de participar de um BOF com Emmanuel Bernard, Gavin King, Pete Muir, Max Andersen e mais uma dezena de pessoas.
O assunto era desenvolvimento de aplicações usando Hibernate, Seam e outras coisas mais da Red Hat. Dentre as várias coisas que foram discutidas, falamos sobre o Hibernate Validator.
O Hibernate Validator me incomoda, e é um pouco complicado de explicar o motivo, mas eu vou tentar. Na verdade não é o Validator em sí, mas as suas annotations. Vejamos um exemplo de código traduzido da página Validator. A sintaxe é muito simples e mesmo que você não saiba exatamente como funciona provavelmente conseguirá entender:
public class Endereco { @NotNull private String rua; private String cep; private String estado; @Length(max = 20) @NotNull private String pais; @Range(min = -2, max = 50, message = "Andar invalido") public int andar; ... }
Na minha concepção, quando usamos o Hibernate Validator dessa forma, passamos a ter regras de negócio/validação do objeto fora do seu controle, e essas regras não estão fortemente encapsuladas. A verificação de que um endereço deve ter no máximo 20 caracteres, por exemplo, deveria estar encapsulada dentro de um método que cria/atualiza o endereço, e não numa annotation.
Existe uma discussão muito grande sobre isso. De um lado, os “puristas” acreditam que colocar annotations num objeto de domínio significa acoplar esses objetos à infraestrutura e implementações específicas. Do outro lado, os “práticos” acham que isso não tem o menor problema, que na prática o efeito colateral disso é nulo.
Eu sinceramente fico meio dividido. O que eu sei é que isso de alguma forma me incomoda. Estou acostumado a pensar de um modo “Domain-Driven Design”, e para mim o mais natural e certo seria que essa regra estivesse dentro de algum método.
Se você pensar que sua aplicação pode usar todas essas coisas juntas com esses quilos de annotations (Seam, Hibernate, Validator, Guice, etc, etc), no final você vai ter objetos de domínio altamente acoplados à toda a infraestrutura da aplicação. Pior ainda quando essas annotations tem regras de negócio. Os objetos vão acabar se tornando meros “fantoches” controlados por annotations… Isso definitivamente não parece ser bom.
Tags: Annotations, BOF, Domain-Driven Design, Emmanuel Bernard, Gavin King, Guice, Hibernate, Hibernate Validator, JBoss World, Max Andersen, Pete Muir, Seam
Assunto polêmico… Eu sou contra esse tipo de uso das anotações, na verdade sou à favor da codificação da *regra de negócio* em algum método. Posso estar dando um tiro no meu pé, mas acho que a testabilidade do artefato ficaria mais complicada usando esta abordagem do validator.
Quanto a simplicidade das anotações, acho imbatível, porém o acoplamento com o middleware é algo que não me agrada muito.
E mais: eu não programo “em anotações”. Acho que as anotações estão sendo usadas de forma exagerada ultimamente, indo para o mal caminho… Algo que me preocupa. O negócio é usar anotações na medida certa, o caminho do meio
Eu sou a favor das anotações Guillerme, utilizadas corretamente. Por exemplo:
public Class Pessoa {
…
private int idade;
…
}
Uma pessoa pode ter idade negativa? Todos sabemos que não. Porém, ao ver a classe Pessoa do jeito que esta, a pessoa poderia ter idade negativa, então me parece que não esta modelando corretamente uma pessoa de verdade.
O fato que a idade seja positiva não e uma coisa que alguem define, simplesmente é assim. Agora, a quantidade de caracteres que pode ter um endereço é sim algo que as pessoas definem, Tudo bem, possivelmente eu posso ir no meio do mato e criar uma rua e dar um nome gigante pra ela, mas se quiser registar ela, o mais provável e que o nome deva ter um limite, nesse caso isso é pra mim regra de negocio é não deveria como anotação na classe.
@Andre
Boa observação. Me esquecí de falar da testabilidade, mas com certeza é mais um ponto negativo de colocar anotações desse tipo…
Também tenho essa mesma sensação sua que as anotações estão sendo utilizadas a torto e a direito e isso de alguma forma pode ser prejudicial.
[ ]s, gc
Também não sou muito a favor disso não. A complexidade dos XML´s só foi transferida de lugar. E o auto acoplamento com o conteiner? É realmente questionável.
Imagine o cenário de uma empresa de software com produtos de prateleira, os quais devem ter o mínimo, senão nenhum acomplamento com determinado conteiner ou fabricante.
Isso rende muita discussão ainda.
Dae gurizada..
Bom, eu já acho interessante encapsular regra de negócio, em um Modelo.
Sei que há várias possiblidades, mas ter um objeto que seja responsável por ele mesmo é muito interessante. Repito, há casos.
Podemos ter um serviço sendo utilizado por vários objetos distintos. Esse só pode ser utilizado para objetos válidos. Mas cada objeto se valida de uma forma diferente.
Vocês iram validar isso em um méto do?? Um monte de “if obj instanceof..” ??? Fazer todos objetos implementar uma interface com método “public void isValid()” ?
Isso sim é complicado.
Realmente o fato do acoplamento incomoda. Alem de que annotation não e programada. Mais cedo ou mais tarde existirá um caso que não poderemos utilizar as anotações.
Ah, e outra.. AutoAcoplamento com conteiner ?? Tu pode usar Hibernate Validator em aplicação Swing sem problemas. Não vejo acoplamento com conteiner…
Gostei do tópico. Parabéns!
Quem bom que estão se preocupando com isso. Fico do lado dos puristas.
Este é o tipo de coisa que me faz abandonar um framework, simplesmente por deixar o modelo dependente do framework. Frameworks devem ser acoplados ao seu modelo e não o seu modelo ao framework. O modelo é o ser supremo, deve funcionar sem framework algum.
Além do mais, este tipo de anotação estão mistura as limitações do banco de dados (ou, da estrutura que foi criada nele para representar o modelo) com regras do negócio e com regras de interface.
[]s
É uma comparação meio exagerada, mas isso se assemelha a deixar, por exemplo, a deixar validação para ser feita no banco, via constraints.
A validação neste ponto, ao meu ver, está num lugar inadequado.
Um abraço,
Guilherme, Eu concordo plenamente contigo sobre o mau uso das anotações. Só tem um porém nessa história: Em alguns cenários, ainda não vi nada muito prático a não ser as anotações. Ex: No próprio hibernate (o core), é ridiculamente simples usar as annotations para tornar os objetos persistentes. Eu achava muito trabalhoso e nada prático criar dezenas de XMLs, o que não acoplava a classe ao framework e sim o framework a classe (se é que eu expliquei direito). Agora, vamos ser práticos: Existe um jeito mais prático?
Abraço !!
@Emerson
Não sei
Realmente eu não conheço uma forma mais prática de fazer, e é por isso que eu hoje em dia uso annotations. A questão é que isso continua me incomodando, ams eu não quero ter que voltar para o XML ou XDoclet.
Finalizando, não sei exatamente qual seria a solução ou a alternativa. A única coisa que eu sei é que esse acoplamento não está certo.
[ ]s, gc
Esse sentimento que te rodeia eu tb tenho
Voltar pro XDoclet nem pensar hehehehe Chega dessa tranqueira. Quando penso nele lembro dos EJBs 2.x quando só com XDoclet (apesar de eu ter fieto alguns por completo na unha.
[]s
Guilherme, as anotações do Hibernate Validator podem vir bem acalhar para garantir o estado do seu objeto de domínio.
Tenho uma idéia um pouco diferente de você sobre estas regras não estarem em métodos de negócio. Se você assumir que as restrições impostas pelos validadores são contratos das invariantes do seu objeto, elas estarem diretamente anotadas nos atributos garante o estado da entidade em toda sua vida, ou pelo menos as pré-condições do contrato para qualquer método, o que é ótimo de todo o jeito. Normalmente um método de negócio delega a checagem do estado… isso estar provido em metadados foi uma ótima sacada ao meu ver.
Bom, é apenas uma opinião.
Abraços
Alessandro
Sou a favor do Hibernate validator. Usar as annotations no modelo é definir a estrutura do modelo, como criar a tabela no banco de dados e setar o tamanho e tipo das colunas.
Pra que eu vou fazer a validação de certos atributos do meu modelo se o banco de dados já faz isso pra mim? Pra que eu vou verificar se um usuário já existe se eu posso dizer que ele é unique e o meu banco de dados validar isso pra mim?
Na camada de negócio eu posso fazer outros tipos de validação e operações e poupar esse trabalho de validar atributos simples do meu modelo.
É a minha opinião.
Abraços
Marcos Filho
Sou a favor desta abordagem.
Você não define o tipo do campo, pq não colocar o tamanho do campo tb ?