Gostaria de saber se posso mudar de Java para Scala em um projeto Spring + Hibernate para tirar proveito de alguns recursos do Scala, como correspondência de padrões, Option e o que me parece uma sintaxe mais limpa em geral. Eu tenho procurado o ORM por padrão no ecossistema do Scala e achei pensado como Activate (mas, principalmente, tento descobrir se o Hibernate pode ser usado com o Scala). Pesquisando isso, li isso na documentação do Play sobre JPA + Scala.
Mas o ponto mais importante é: você realmente precisa de um mapeador Relacional para Objetos quando tem o poder de uma linguagem funcional? Provavelmente não. O JPA é uma maneira conveniente de abstrair a falta de poder do Java na transformação de dados, mas realmente parece errado quando você começa a usá-lo no Scala.
Eu não tenho um conhecimento profundo de como usar a programação funcional para criar um aplicativo completo (é por isso que pretendo usar o Scala para que eu possa entender isso de forma incremental, pois combina OO + Funcional), para que eu não possa descobrir por que eu não precisaria de um ORM com uma linguagem funcional e qual seria a abordagem funcional para lidar com a persistência do modelo de domínio.
Uma abordagem DDD para a lógica de negócios ainda faz sentido com Scala, não é?
fonte
Respostas:
Bem, uma coisa que é importante fazer sempre que tivermos uma discussão como essa é distinguir claramente entre mapeadores relacionais de objetos ("ORM") e camadas de abstração de banco de dados . Um ORM é um tipo de camada de abstração de banco de dados, mas nem todas as camadas de abstração de banco de dados são ORMs. Uma boa ferramenta para estudar para entender isso é a popular biblioteca SQLAlchemy do Python , que se apresenta como um "kit de ferramentas SQL e o Mapeador Relacional de Objetos" (meu negrito), com a idéia de que essas são coisas diferentes. Como eles colocam na página de recursos principais :
A primeira página descreve o ORM assim:
A idéia principal de um ORM é tentar colmatar a famosa incompatibilidade de impedância objeto-relacional . Isso significa definir relacionamentos entre classes definidas pelo usuário para tabelas em um esquema de banco de dados e fornecer operações automáticas de "salvar" e "carregar" para as classes do seu aplicativo.
Por outro lado, as camadas de abstração de banco de dados que não são do ORM tendem a ser mais comprometidas com o modelo de dados relacional e com o SQL, e nada com a orientação a objetos. Portanto, em vez de apresentar "mapeamentos" entre tabelas e classes e ocultar o esquema do banco de dados do programador, eles tendem a expor o banco de dados ao programador, mas com melhores APIs e abstrações. Por exemplo, os construtores de consultas SQL permitem gerar consultas SQL complexas programaticamente, sem manipulação de cadeias, como este ( um exemplo da biblioteca jOOQ para Java ):
Agora, o framework Play não parece 100% compatível com o que acabei de descrever , mas o argumento deles parece estar neste espaço geral: trabalhe diretamente com o modelo relacional em vez de traduzi-lo para as classes e voltar a partir dele.
A biblioteca jOOQ vale a pena estudar como um contraponto à ORMs. Eles também têm algumas entradas de blog relevantes que valem uma leitura:
fonte
É meio difícil de explicar até que você tenha feito muita programação funcional. Na programação orientada a objetos, seus dados ficam meio presos em um objeto e permanecem lá. Esse objeto é transmitido um pouco e modificado um pouco, mas você geralmente trabalha fundamentalmente com a mesma "identidade" durante a vida útil desses dados.
ORMs geralmente são projetados em torno desse paradigma. Você recupera alguns dados do banco de dados, coloca-os em um objeto, modifica-os potencialmente e, quando terminar, você ainda tem o mesmo objeto que pode gravar no banco de dados.
A programação funcional funciona de maneira diferente. Seus dados não mantêm uma identidade única durante a vida útil. Ele é dividido, copiado, compartilhado e transformado. Ele meio que flui através de várias funções e, eventualmente, é remontado na forma de saída que você precisa. Para qualquer API de banco de dados parecer natural em uma linguagem funcional, é necessário levar isso em consideração, e o JPA não.
fonte
No scala, ainda é útil mapear tabelas de banco de dados para objetos, e existem várias maneiras de fazê-lo.
Um quadro popular no mundo de Scala é liso . Não é um ORM, porque faz menos (a saber, não busca relacionamentos sem ser instruído a fazer associações explicitamente).
Portanto, você ainda mapeia objetos para linhas do banco de dados, mas seus objetos são imutáveis (portanto, não há liberação de estado) e executa explicitamente consultas usando uma DSL monádica. O resultado é que você obtém várias partes "boas" de um ORM sem os problemas de mutabilidade e problemas imprevisíveis de N + 1.
Deve-se notar que as pessoas obtiveram grande sucesso usando bibliotecas muito mais finas, como anorm ou JDBC direto, usando técnicas funcionais para manter o código bonito.
Uma biblioteca fantástica que aplica técnicas funcionais sobre o JDBC também é doobie .
Portanto, você tem muitas opções para acessar o banco de dados, mas o Hibernate (que parece ser o ORM de fato) não é um dos melhores, devido à tendência à mutabilidade.
fonte
Você não precisa de um ORM, mesmo em linguagens orientadas a objetos.
Primeiro, quem disse que seus dados devem ser fisicamente copiados do armazenamento persistente para o objeto? Alan Kay , um homem por trás do Smalltalk, queria que os objetos se livrassem dos dados . Ele sugeriu que um objeto pode ter apenas uma referência a alguma área em que seus dados são armazenados.
Segundo - qual é a melhor maneira de conseguir isso? Eu recomendo identificar seus objetos por suas responsabilidades , e não pensar nos dados que eles possuem. Se você já ouviu falar sobre a abordagem de cartões CRC, é usado exatamente para isso.
E, finalmente, no caso de você retornar ao campo OO, aqui está uma maneira de implementá-lo .
fonte