O ORM é uma ferramenta ruim para estruturas de banco de dados semelhantes a árvores?

8

Eu sei que essa pergunta pode ser encerrada como baseada em opiniões, mas o que eu preciso no momento são algumas opiniões suportadas por argumentos.

Estou construindo um aplicativo com Postgres e Ecto (Elixir) como a camada de persistência. Existe uma entidade que se refere a si mesma para que você possa construir uma estrutura semelhante a uma árvore. Quanto mais eu estou tentando fazer isso com Ecto, mais frustrado fico.

Os ORMs são simplesmente uma ferramenta ruim para criar estruturas de banco de dados complexas com muitas associações? A maneira orientada a objetos que o ORM tenta aplicar nos dados relacionais parece ser uma abordagem ruim aqui. Objetos são isolados. Se eles interagem com outros objetos, eles (supostamente) enviam mensagens. Seus detalhes internos devem permanecer ocultos. Os dados relacionais formam um gráfico aberto e transparente. Esses dois mundos parecem ser completamente incompatíveis comigo.

No entanto, ORMs são muito comuns e populares. A maioria dos aplicativos da Web trabalha com entidades bastante isoladas que funcionam bem com o ORM, ou por que? Parece-me que, se você deseja implementar qualquer modelo ERD médio complexo usando uma estrutura ORM, é necessário sacrificar código ou desempenho conciso.

Adam Libuša
fonte
1
Cada sistema de banco de dados pode ter uma implementação ligeiramente diferente para suportar uma árvore ou estrutura de dados "hierárquica". Por exemplo, o Oracle possui START WITH e CONNECT BY e o Sql Server possui Common Table Expressions (CTEs). Portanto, antes de escolher um ORM, deve-se determinar se ele possui o suporte adequado para esses tipos de estruturas de dados. Alguns oferecem muito bom suporte, enquanto outros podem não cobrir esses cenários. Esta pergunta deve ser reformulada: Ecto suporta estruturas de árvores?
Jon Raynor
Desde que você mencionou postgres especificamente, ele suporta consultas recursivas para este tipo de coisa (embora eu não usei isso mesmo)
Izkata
1
Obviamente, os ORMs são uma ferramenta ruim. Já existe uma linguagem para expressar expressamente consultas em bancos de dados: SQL.
Route de milhas
Rota do @Miles Na maioria dos casos, quando você usa SQL simples em vez de um ORM, está se repetindo bastante.
Jimmy T.
@JimmyT. Isso é falso.
Miles Rout

Respostas:

9

No final do dia, um ORM é apenas uma abstração que gera sql para você e mapeia os dados para seus objetos. Salvando (tm) um código de "placa da caldeira".

Portanto, não há nada em que as ORMs como um todo necessariamente sejam ruins por definição. O problema é que você não usa ORMs como um todo, precisa escolher um específico e usá-lo!

Um ORM individual pode muito bem não fazer uma coisa específica muito bem. Procs armazenados, sql dinâmico, campos calculados, junções complicadas etc. podem ser áreas problemáticas.

Um problema mais sutil é que, quando um ORM tenta lidar com todos esses cenários de uma maneira genérica, fica maior e mais complicado de usar.

Se você tiver um aplicativo grande ou complicado, é provável que em algum momento você encontre um problema com o ORM escolhido. Portanto, faz sentido planejar isso com antecedência e garantir que você oculte o ORM atrás de um repositório. Dessa forma, você pode trocá-lo por uma alternativa ou voltar ao SQL codificado manualmente, se necessário.

Ewan
fonte
1
Deve-se notar que, em muitos ORMs (pelo menos em todos os que eu usei ), você pode gravar e executar SQL bruto . Portanto, se o ORM não satisfizer bem alguma restrição, você sempre poderá fazer isso com SQL nativo, enquanto reduz simultaneamente as operações 'clichê' SELECT * FROM some_table WHERE x = whateverque são extremamente comuns. As estruturas hierárquicas são bem tratadas em algumas ORMs e terrivelmente em outras, portanto, esse tipo de consideração deve ser pesquisado antes de se decidir renunciar inteiramente às ORMs.
22817 Chris Cirefice
você geralmente pode fazer isso, mas nem sempre funciona da maneira que deseja! Recentemente, tive este problema exato com nHibernate e mapeamento de campo anulável
Ewan
Eu nunca usei o nHibernate, mas usei alguns como ActiveRecord do Rails, OrmLite (Java) e ActiveJdbc (Java). Cada uma destas alças execução SQL matéria de forma diferente, por exemplo ActiveRecord torna realmente fácil, e OrmLite tornou realmente difícil. O ActiveRecord está em desenvolvimento há anos e anos, com certeza isso tem algo a ver com isso. Todas essas pequenas nuances são parte de testes de viabilidade, mas às vezes você perca as pequenas coisas que voltar a morder-lhe mais tarde ...
Chris Cirefice
Sim, é por isso que eu digo, coloque um invólucro em volta dele. você ainda pode usar o ORM, mas você não está trancado em se deixa para baixo, de alguma forma
Ewan
Saving (tm) - Eu ri um pouco disso.
precisa saber é o seguinte
7

Os ORMs são simplesmente uma ferramenta ruim para criar estruturas de banco de dados complexas com muitas associações?

Não. Como exemplo, o Ruby on Rails usa o ActiveRecord, que lida com associações. No exemplo aqui: /programming/5109893/rails-how-do-self-referential-has-many-models-work , a estrutura em forma de árvore é realizada com 2 linhas de código.

Então, eu diria que é muito mais fácil do que tentar rolar suas próprias consultas sql.

A maioria dos aplicativos da Web trabalha com entidades bastante isoladas que funcionam bem com o ORM, ou por que?

Provavelmente não, mas isso é apenas suposição. As ORMs existem em um ecossistema em que estão prosperando, sugerindo que estão sendo usadas. Eu usei ORMs para sistemas com mais de 20 modelos associados e achei que eles estavam bem. Eu nunca forcei os objetos a serem isolados apenas com a passagem de mensagens.

Como uma opinião resumida, se você estiver criando modelos ERD "complexos", não há ferramenta que os facilite. Somente ferramentas que os fazem funcionar.

cmonkey
fonte
Sim - usei o Entity Framework para um projeto que tinha CustomerId (PK) e ParentCustomerId (FK anulável apontando para a tabela do cliente) para criar n níveis de árvores de hierarquia de clientes. Não tive nenhum problema aqui (embora muitas verificações nulos / .Any()instruções LINQ)
USER_8675309
O Hibernate (Java) é outro bom exemplo de um ORM que pode lidar com árvores sem problemas, exigindo praticamente zero esforço extra . A complexidade da consulta está oculta do cliente. Pais e filhos podem ser preguiçosos. O ID do objeto pai é apenas mais uma coluna no banco de dados. Uma lista ordenada de nós filhos também pode ser suportada de forma transparente, com a adição de uma coluna que contém um índice de lista. (Não ordenada vs considerações coleção ordenada não são exclusivos de árvores aqui.)
Jason C
Não posso deixar de sentir que esta é uma resposta enganosa. Como um ORM lida com esse caso, não significa que os ORMs em geral possam lidar com isso. De fato, um google rápido mostra que o registro ativo DEVE pegar
Ewan
@Ewan - Estou aberto a reformular minha resposta, mas acho que responde adequadamente à pergunta se as ORMs em geral são ruins. É uma questão diferente perguntar se todos os ORMs podem lidar com esse caso ou se são a melhor solução. A existência de uma ferramenta ORM menos adequada ou de um bug em uma versão não altera a generalização. Eu também sei que tive bugs no meu SQL também.
cmonkey
5

Conforme observado em pelo menos uma outra resposta aqui, todos os ORMs não são os mesmos. Alguns ORMs fazem suposições muito significativas sobre como o banco de dados deve ser estruturado. As ferramentas devem fornecer algum suporte para sair deste modelo, mas quanto mais você sair desse modelo, menor será o valor do ORM. Se você estiver trabalhando com uma ferramenta ORM mais dominadora, terá uma experiência muito melhor se projetar o banco de dados com base em suposições implícitas.

Eu realmente nunca entendi por que os ORMs são vistos por muitos desenvolvedores e arquitetos como essenciais. Isso pode dever-se ao fato de eu quase nunca ter um banco de dados de campo verde para trabalhar e o tempo e o esforço necessários para concluir o mapeamento ORM foi muito mais trabalhoso do que escrever o SQL. O mapeamento era simples (e o SQL também) ou era complicado e eu precisava do SQL (ou algo semelhante) de qualquer maneira. O 'suporte' transacional incluído no ORM tem sido mais uma fonte de erros e problemas do que uma ajuda, na minha experiência.

Sua milhagem pode variar, mas acredito que é melhor pensar na persistência do banco de dados apenas como um caso especial de serialização de dados. E, assim como acho que não faz sentido acreditar que você pode "enviar" um objeto pela rede, não acho que faça sentido pensar em escrever objetos em um banco de dados. Eu até acho que é completamente válido ter várias representações de objetos dos mesmos dados para diferentes necessidades. O mapeamento de objetos para tabelas e vice-versa tornou-se um fim para si mesmo, em vez de uma solução para um problema. Não estou convencido de que a maioria das pessoas que usa essas ferramentas tenha um motivo claro para querer fazê-lo. Tornou-se um padrão.

JimmyJames
fonte
1
totes concordar, uma vez que você se resignar a digitação o sql e mapear raramente demora mais a longo prazo e você tem o controle total
Ewan
@ Ewan Para ser justo, acho que é preciso um pouco de experiência para saber como criar as abstrações apropriadas entre a lógica e o banco de dados. ORMs podem ajudar os desenvolvedores a obter algo viável rapidamente. É a ideia de que os objetos podem ser traduzidos para tabelas e vice-versa, que é onde eu acho que há problemas. É verdade para um subconjunto de modelos de dados e modelos de objetos, mas não em geral.
precisa saber é o seguinte
1
@JimmyJames É verdade se tudo que você precisa é muito simples por operações CRUD da tabela. Além disso, um ORM não micro é uma maldição. (E eu pessoalmente acho a idéia de criar um objeto para cada conjunto diferente de colunas voltando para um micro-ORM a ser irritante, embora possa ser o menor de coisas irritantes em uma linguagem de tipagem estática.)
jpmc26
1
@ jpmc26 Eu quero dar um passo lateral no atoleiro estático vs. dinâmico, mas acho que você está destacando o tipo de coisa que estou falando. Se tudo o que eu quero fazer é extrair alguns dados, transformá-los minimamente e retornar como JSON, por exemplo, eu realmente não preciso mapear objetos para fazer isso. O objeto não possui funcionalidade real. Ele atua como um mapa onde os dados são armazenados momentaneamente. Mas já vi ORMs usados ​​para resolver esse tipo de problema. Freqüentemente, a resposta é gerar as classes para esses objetos, mas acho que isso apenas destaca o quanto eles são desnecessários.
precisa saber é o seguinte
De alguma forma, deixei de lado o que pretendia dizer originalmente: a situação não é melhor com um novo banco de dados que você está desenvolvendo. Depende apenas do tipo de consulta que você precisa escrever. Para CRUD muito simples por tabela, pode economizar um pouco de tempo. Mas se você tiver consultas que misturam e combinam dados de diferentes tabelas ou consultas complexas (agrupamentos complexos, CTEs, subconsultas), qualquer coisa que não seja micro é automaticamente muito mais problemática do que vale a pena. Mesmo se você puder se safar com CRUD muito simples no começo, está apostando que o sucesso não levará a uma complexidade maior.
jpmc26