Por que eu não precisaria de um ORM em uma linguagem funcional como o Scala?


30

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 é?


3
Esta é uma pergunta baseada em opinião. O Scala não é puramente funcional, é também uma linguagem OO, de modo que explicaria por que você ainda deseja usar uma ferramenta ORM. Para mapeamento de banco de dados, consulte, por exemplo: Slick , SORM , Anorm .
Jesper

Não estou procurando uma opinião, estou perguntando a algo com profundo entendimento do paradigma funcional qual é o caminho para alcançar a persistência. Sei que Scala é um híbrido e quero usar sua parte OO para DDD. Então você diz que, se eu adotar uma abordagem DDD, mesmo com Scala, um ORM é o caminho a seguir?
Gabrielgiussi

Nas linguagens funcionais, você lida principalmente com valores que não têm identidade como os objetos. Portanto, você não precisa do rastreamento de alterações, que é um dos principais trabalhos de um ORM.
25415 Lee


5
Você não precisa de um ORM em nenhum idioma principal.
GrandmasterB

Respostas:


30

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 :

Não é necessário ORM

O SQLAlchemy consiste em dois componentes distintos, conhecidos como Core e ORM . O Core é ele próprio um kit de ferramentas de abstração SQL completo, fornecendo uma camada suave de abstração sobre uma ampla variedade de implementações e comportamentos DBAPI, além de uma linguagem de expressão SQL que permite a expressão da linguagem SQL por meio de expressões generativas em Python. Um sistema de representação de esquema que pode emitir instruções DDL, bem como examinar os esquemas existentes, e um sistema de tipos que permite qualquer mapeamento de tipos Python para tipos de banco de dados, complementam o sistema. O Object Relational Mapper é então um pacote opcional que se baseia no Core.

A primeira página descreve o ORM assim:

O SQLAlchemy é mais famoso por seu ORM (Object-Relational Mapper), um componente opcional que fornece o padrão do mapeador de dados, no qual as classes podem ser mapeadas para o banco de dados de várias maneiras abertas - permitindo que o modelo de objeto e o esquema do banco de dados se desenvolvam bem dissociada desde o início.

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 ):

// Typesafely execute the SQL statement directly with jOOQ
Result<Record3<String, String, String>> result =
    create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
          .from(BOOK)
          .join(AUTHOR)
          .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
          .where(BOOK.PUBLISHED_IN.equal(1948))
          .fetch();

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:


19

É 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.


11
+1000 As pessoas que insistem em usar o Scala como se fosse Java ++ me deixam com medo do futuro da linguagem :(
Andres F.

9

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.


0

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 .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.