O que é Hibernar? Fundamentos da implementação do Hibernate Core

Publicados: 2013-04-17

Exemplo de hibernação Java

Hibernate é um projeto de framework de persistência Java de código aberto. Execute mapeamento relacional de objeto poderoso e bancos de dados de consulta usando HQL e SQL.

Em geral, as bibliotecas amplamente utilizadas são bem projetadas e implementadas, e é muito interessante aprender com elas algumas práticas recomendadas de codificação.

Vamos dar uma olhada dentro da biblioteca principal de hibernação e descobrir algumas de suas chaves de design.

Neste post o Hibernate Core é analisado pelo JArchitect para aprofundar seu design e implementação.

Pacote por recurso

Package-by-feature usa pacotes para refletir o conjunto de recursos. Ele coloca todos os itens relacionados a um único recurso (e somente esse recurso) em um único diretório/pacote. Isso resulta em pacotes com alta coesão e alta modularidade, e com acoplamento mínimo entre pacotes. Os itens que funcionam juntos são colocados próximos uns dos outros.

O núcleo do Hibernate contém muitos pacotes, cada um relacionado a um recurso específico hql, sql e outros.

Pacotes principais do Hibernate - Crunchify.com

Acoplamento

O baixo acoplamento é desejável porque uma mudança em uma área de uma aplicação exigirá menos mudanças em toda a aplicação. A longo prazo, isso pode aliviar muito tempo, esforço e custo associados à modificação e adição de novos recursos a um aplicativo.

Aqui estão três principais benefícios derivados do uso de interfaces:

  • Uma interface fornece uma maneira de definir um contrato que promove a reutilização. Se um objeto implementa uma interface, então esse objeto deve estar em conformidade com um padrão. Um objeto que usa outro objeto é chamado de consumidor. Uma interface é um contrato entre um objeto e seu consumidor.
  • Uma interface também fornece um nível de abstração que torna os programas mais fáceis de entender. As interfaces permitem que os desenvolvedores comecem a falar sobre a maneira geral como o código se comporta sem precisar entrar em muitos detalhes específicos.
  • Uma interface impõe baixo acoplamento entre os componentes, o que facilita a proteção do consumidor da interface de quaisquer mudanças de implementação nas classes que implementam as interfaces.

Vamos buscar todas as interfaces definidas pelo Hibernate Core, para isso usamos CQLinq para consultar a base de código.

jboss11- Crunchify.com

Se nosso objetivo principal é impor baixo acoplamento, há um erro comum ao usar interfaces que podem matar a utilidade de usá-las. É o uso das classes concretas ao invés de interfaces, e para explicar melhor esse problema vamos pegar o seguinte exemplo:

A classe A implementa a Interface IA que contém o método calculate(), a classe consumidora C é implementada assim

A Classe C ao invés de referenciar a interface IA, ela referencia a classe A, neste caso perdemos o benefício de baixo acoplamento, e esta implementação tem duas grandes desvantagens:

  • Se decidirmos usar outra implementação de IA, devemos alterar o código da classe C.
  • Se alguns métodos forem adicionados a A não existentes em IA e C os usarem, também perderemos o benefício contratual de usar interfaces.

O C# introduziu o recurso de implementação de interface explícita na linguagem para garantir que um método do IA nunca seja chamado de uma referência a classes concretas, mas apenas de uma referência à interface. Essa técnica é muito útil para proteger os desenvolvedores de perder o benefício de usar interfaces.

Com o JArchitect podemos verificar esse tipo de erro usando CQLinq , a ideia é buscar todos os métodos de classes concretas usadas diretamente por outros métodos.

Detalhes do hibernate2 - Crunchify.com

Por exemplo, o método getEntityPersister de SessionFactoryImpl que implementa a interface SessionFactoryImplementor está preocupado com este problema.

Vamos procurar métodos que invoquem diretamente SessionFactoryImpl.getEntityPersister.

Tutorial de hibernação - Crunchify.com

Métodos como SessionImpl.instantiate invocam diretamente getEntityPersister, ao invés de passar por interface, o que quebra o benefício de usar interfaces. Felizmente, o núcleo de hibernação não contém muitos métodos com esse problema.

Acoplamento com frascos externos

Quando libs externas são usadas, é melhor verificar se podemos facilmente alterar uma lib de terceiros por outra sem afetar toda a aplicação, existem muitos motivos que podem nos encorajar a alterar uma lib de terceiros.

A outra lib poderia:

  • Tenha mais recursos
  • Mais poderoso
  • Mais seguro

Vamos pegar o exemplo da antlr lib que costumava analisar as consultas hql, e imaginar que outro analisador mais poderoso que o antlr foi criado, poderíamos trocar o antlr pelo novo analisador facilmente?

Para responder a essa pergunta, vamos pesquisar quais métodos do hibernate o usam diretamente:

Detalhes da hibernação - Crunchify

E quais usaram indiretamente:

Hibernate Funda - Tutoriais Java - Crunchify

Muitos métodos usam o antlr diretamente o que torna o core hibernate altamente acoplado a ele, e trocar o antlr por outro não é uma tarefa fácil. este fato não significa que temos um problema no design de hibernação, mas temos que ter cuidado ao usar uma lib de terceiros e verificar se uma lib de terceiros deve ser baixa ou não com a aplicação.

Coesão

O princípio da responsabilidade única afirma que uma classe deve ter um, e apenas um, motivo para mudar. Essa classe é dita coesa. Um valor alto de LCOM geralmente indica uma classe pouco coesa. Existem várias métricas LCOM. O LCOM assume seus valores no intervalo [0-1]. O LCOMHS (HS significa Henderson-Sellers) assume seus valores no intervalo [0-2]. Observe que a métrica LCOMHS é frequentemente considerada mais eficiente para detectar tipos não coesos.

O valor de LCOMHS superior a 1 deve ser considerado alarmante.

Em geral, as classes mais preocupadas com a coesão são as classes que possuem muitos métodos e campos.

Vamos procurar por tipos com muitos métodos e campos.

hibernate6 - Crunchify

Apenas alguns tipos estão preocupados com esta consulta, e para todos eles o LCOMHS é menor que 1.

Usando anotações

O desenvolvimento baseado em anotação alivia os desenvolvedores Java da dor da configuração incômoda. E nos dê um recurso poderoso para liberar o código-fonte do código clichê. O código resultante também é menos provável de conter bugs.

Vamos procurar todas as anotações definidas pelo núcleo de hibernação.

hibernate7 - Crunchify.com

Muitas anotações são definidas, o que torna a hibernação fácil de usar pelos desenvolvedores, e a dor de cabeça dos arquivos de configuração é evitada.

Conclusão

O Hibernate Core é um bom exemplo de projetos de código aberto para aprender, não hesite em dar uma olhada nele.