7 pontos por GN⁺ 2023-06-28 | 1 comentários | Compartilhar no WhatsApp
  • ORMs costumam ser criticados como “brinquedos para startups”, mas a questão real está mais no modo incorreto de uso do que no ORM em si
  • Como grafos de objetos e tabelas relacionais são modelos diferentes, surge um desalinhamento de paradigmas, mas isso por si só não basta para classificar ORM como antipadrão
  • O debate sobre violação de SRP e SOC é válido, mas como o ORM é, desde o início, uma abstração para conectar dois modelos de dados, é difícil julgá-lo apenas por possível violação de princípios
  • Problemas de desempenho costumam surgir menos do ORM e mais do padrão de combinar dados na lógica da linguagem hospedeira, e podem ser reduzidos com os recursos semelhantes a SQL do ORM
  • O principal motivo para a Lago trocar consultas do Active Record por SQL bruto não foi velocidade, e sim visibilidade e depuração; em consultas grandes, migrar para SQL bruto pode ser mais vantajoso na prática

Posição básica sobre as críticas ao ORM

  • ORMs são frequentemente atacados como “antipadrão”, mas concluir que o ORM em si é ruim é um exagero
  • Como qualquer outra abstração, ORMs não são perfeitos e podem gerar alguma perda de visibilidade e custo de desempenho
  • A Lago enfrentou problemas ao depender do Active Record, o ORM do Ruby on Rails, e isso a levou a reavaliar a forma como dependia de ORMs
  • A conclusão ficou mais próxima de tratar ORM como uma abstração com vantagens e desvantagens claras, e não de abandoná-lo por completo

Diferença entre o modelo de objetos e o banco de dados relacional

  • Os objetos com que o ORM lida se parecem mais com um grafo direcionado em que nós apontam para outros nós
  • Tabelas de bancos de dados relacionais se parecem mais com um grafo não direcionado, em que os dados se conectam bidirecionalmente por meio de chaves compartilhadas
  • Um ORM pode até simular um grafo não direcionado, mas a configuração e o comportamento nem sempre são simples
    • O objeto User pode não incluir o array Posts
    • As entidades do array Posts podem não ter uma referência de volta para o mesmo objeto User
    • Mesmo que exista referência de volta, ela pode apontar para um objeto duplicado, e não para a mesma instância
  • Por exemplo, um ORM pode retornar as postagens de um usuário em um array sem incluir, em cada postagem, a referência inversa ao usuário no papel de autor
  • Esse desalinhamento é uma boa crítica acadêmica ao ORM, mas na operação real os problemas maiores aparecem no modo concreto de uso

Debate sobre SRP e SOC

  • Princípio da Responsabilidade Única (SRP)

    • ORMs são criticados por violar o Princípio da Responsabilidade Única (SRP)
    • Isso porque podem levar uma classe ou camada a assumir vários papéis ao mesmo tempo
      • Executar operações de banco de dados e transações
      • Representar registros
      • Definir relacionamentos
      • Gerar e executar migrações
    • Mas, como o objetivo do ORM é justamente conectar dois paradigmas de dados diferentes, é difícil rejeitá-lo apenas com base em alguma violação de princípio
  • Separação de Responsabilidades (SOC)

    • ORMs também podem enfraquecer o princípio de Separação de Responsabilidades (SOC)
    • O SOC diz que um componente de infraestrutura deve ter apenas uma única responsabilidade
    • Como o ORM desloca a gestão do banco de dados para o lado do backend, há espaço para considerá-lo uma violação de SOC
    • Ainda assim, hoje em dia componentes de infraestrutura e padrões de código também combinam vários papéis por razões de desempenho, latência e organização do código
      • Agregadores de CPU dentro de bancos de dados OLAP
      • Backends-frontends de edge
      • Monorepos

Problemas de desempenho surgem mais no modo de uso do que no ORM

  • A crítica de que ORMs são sempre ineficientes é em geral incorreta
  • Muitos ORMs podem operar com muito mais eficiência do que os desenvolvedores imaginam
  • O problema é que eles facilitam combinar dados usando lógica da linguagem hospedeira como JavaScript ou Ruby
  • No exemplo com TypeORM, é tratado como padrão ruim consultar primeiro os autores de uma empresa específica, depois buscar novamente as postagens de cada autor e então salvar cada postagem separadamente
  • Uma forma melhor é montar uma única query de atualização com createQueryBuilder() do TypeORM
  • Na refatoração do SQL de faturamento da Lago, também não houve diferença de desempenho entre a versão com Active Record e a versão em SQL bruto
    • Como os recursos de composição de dados do Active Record já eram bastante usados, a consulta existente já estava otimizada
    • Reescrever em SQL bruto teve mais a ver com ganho de visibilidade do que com melhoria de desempenho

Quando o ORM pode realmente ficar lento

  • ORMs nem sempre são tão eficientes quanto SQL bruto e, em algumas situações, podem ser bastante ineficientes
  • O primeiro problema é que o ORM pode criar grande sobrecarga computacional ao converter o resultado da query em objetos
    • TypeORM é citado como exemplo desse problema
  • O segundo problema é quando, ao percorrer relacionamentos um-para-muitos ou muitos-para-muitos, várias idas e vindas são feitas ao banco de dados
  • Esse padrão é chamado de problema N+1
    • A uma query original somam-se N subqueries
    • No exemplo com Prisma, ao buscar usuários, postagens e comentários de forma aninhada, cada comentário pode gerar uma nova requisição ao banco de dados
  • O N+1 aparece com frequência em ORMs, mas com um data loader é possível reduzir N+1 queries para apenas 2
  • Boa parte dos problemas comuns de ORM pode ser evitada se seus recursos forem usados de forma completa

O problema maior é visibilidade e depuração

  • O maior ponto fraco de ORMs é a visibilidade
  • Como o ORM é, na prática, um construtor de queries, ele não é o transmissor final do erro, exceto em casos óbvios como erro de tipo primitivo
  • Quando um erro de SQL é retornado, o ORM precisa interpretá-lo e repassá-lo ao usuário
  • O Active Record teve dificuldades nesse ponto, e foi por isso que a Lago refatorou sua query de assinaturas de faturamento
  • Quando o resultado saía diferente do esperado, era preciso repetir o seguinte processo
    • Verificar a query SQL renderizada
    • Executar essa SQL novamente
    • Traduzir o erro SQL de volta para mudanças no Active Record
  • Esse vai e vem enfraquece o objetivo original de usar Active Record justamente para não interagir diretamente com o banco SQL

Avaliação prática

  • Quando usados corretamente, ORMs podem alcançar eficiência próxima à do SQL bruto
  • Muitos problemas surgem quando, em vez de usar os recursos semelhantes a SQL do ORM, se depende demais da estrutura lógica da linguagem hospedeira
  • Se consultas grandes estiverem dificultando o trabalho dos desenvolvedores e atrapalhando a depuração, migrar para queries em SQL bruto pode ser um bom investimento
  • A maioria dos ORMs oferece recursos para executar queries SQL de dentro do próprio ORM

1 comentários

 
GN⁺ 2023-06-28
Comentários do Hacker News
  • Uso ORM desde que o Hibernate apareceu no Java, mas sempre achei ruim
    A vantagem de “poder trocar de banco de dados” hoje parece quase conversa fiada, e na prática ninguém usa assim
    A ideia de que “não precisa saber SQL” também é falsa, e qualquer app não trivial que dure bastante tempo acaba exigindo ajustes em consultas específicas no nível de string
    A camada de dados funciona melhor criando e interpolando cada consulta como SQL em string, e, na minha visão, quanto mais perto de raw JDBC, melhor
    A alegação de que ORM dá suporte a um “modelo de domínio” também é um mau motivo, porque esse modelo de domínio sempre acaba virando um modelo de domínio anêmico, sem lógica
    Dá vontade de chorar pensando no tempo desperdiçado com ORM, XML, anotações, depuração do SQL gerado etc.

    • Concordo totalmente. Eu descreveria ORM como algo que “deixa as partes fáceis um pouco mais fáceis, mas torna as partes difíceis realmente difíceis”
      As partes fáceis já são fáceis, então não me interessam muito; em compensação, no pior momento, quando as consultas desmoronam ao ganhar escala, muitas vezes o trabalho ficou um milhão de vezes mais difícil porque eu ainda tinha de brigar com o próprio ORM
      Query builders não são exatamente a mesma coisa que ORM, mas gosto deste texto, https://gajus.medium.com/stop-using-knex-js-and-earn-30-bf41..., e virei fã de tecnologias no estilo Slonik
      Elas oferecem 90% do que eu quero, como binding automático do resultado em objetos e checagem de tipos forte, e mesmo assim deixam você simplesmente escrever SQL normal
      Também não entendo a ideia de que SQL seria uma linguagem misteriosamente difícil. Ela é antiga e tem defeitos, mas ainda é melhor aprender SQL do que aprender a linguagem de consulta própria criada por ferramentas de ORM
    • Desde a primeira vez que usei, há muito tempo, passei a odiar ORM pelos mesmos motivos e o vi como um antipadrão
      Na época, quando eu fazia esse tipo de crítica, outros desenvolvedores olhavam de cima para mim
      Ainda hoje há muitas ferramentas e técnicas que, como desenvolvedor, sou forçado a usar mesmo sendo antipadrões, e a triste realidade do setor é que boa parte das ferramentas amplamente usadas é ruim e incentiva antipadrões
      Na indústria de tecnologia existem alguns poucos desenvolvedores e ex-desenvolvedores bem conectados que concentram o poder de decisão, e acho que eles são bem ruins nisso
    • Você acabou começando logo por um dos piores ORMs que existem
      Há ORMs com uma relação razoável entre prós e contras, especialmente no ecossistema Python
      O Django ORM é meio bruto e o desempenho não é grande coisa, mas é bem integrado, prático, produtivo e agradável de usar
      O Peewee oferece ORM em um pacote pequeno, então, quando você não precisa de nada muito sofisticado e só quer evitar dor de cabeça, ele torna agradável escrever programinhas pequenos
      O SQLAlchemy exige mais investimento, mas é muito flexível, gera SQL limpo e funciona corretamente
      Ele também expõe query builders de nível mais baixo para quando você não quer o paradigma orientado a objetos e prefere expressar em Python uma abstração de comportamento idiomático de SQL
      No fim, isso vira uma decisão normal de engenharia baseada em retorno sobre o investimento
    • Essa história de que “precisa ajustar no nível de string” é, pela minha experiência, conversa fiada
      Faço isso há mais de 10 anos e nunca houve uma consulta que eu não conseguisse tratar melhor apenas lendo a documentação do Hibernate por 5 minutos e fazendo o que ela mandava naquela situação
      Parece que os fanboys de SQL, que acreditam que todo desenvolvedor deveria decorar tabelas de lógica de três valores e nomes de funções em estilo COBOL, na verdade não querem ter o trabalho de ler a documentação do Hibernate
    • “Não precisa saber SQL” nunca foi, para qualquer pessoa minimamente sensata, um argumento a favor de ORM
      ORM é para workloads OLTP, não para OLAP, e um dos criadores do Hibernate já disse isso
      A utilidade principal é evitar escrever manualmente consultas INSERT/UPDATE longas e propensas a erro, além de fazer o mapeamento automático de linhas SQL para objetos
      Se você for pelo caminho raw, vai acabar reimplementando boa parte disso, então isso também não é um jogo de soma zero
  • Em apps suficientemente complexos, em algum momento acaba surgindo algo como um query builder, em que várias partes da aplicação podem compor consultas de forma adiada juntas
    A estrutura passa a combinar tudo em consultas, em vez de juntar, filtrar e ordenar os dados em memória
    O ORM é uma ferramenta que facilita isso, mas também pode acabar te sabotando ao tornar muito fácil criar consultas N+1 sem perceber
    Como qualquer ferramenta, é preciso avaliar os trade-offs junto com o caso de uso real, e não recomendo manipular diretamente strings de comandos SQL em hipótese alguma

    • A experiência com ORM pode variar drasticamente dependendo da linguagem usada, do nível de integração e do tipo de trabalho
      Mesmo assim, sempre há quem ignore essas diferenças e diga de forma absoluta que ORM é bom ou ruim
      É melhor tratar isso como uma postura provocativa para chamar atenção e seguir em frente; prefiro focar em discussões que partem de “ORM tem vantagens, mas é preciso saber onde elas se aplicam e garantir que os problemas de uso não superem os benefícios”
    • Não considero óbvio que um app suficientemente complexo precise de um query builder, e não aceito isso nos meus apps
      Se os dados são necessários, vá até a camada de acesso a dados; se ela não fornece o que você precisa, crie um novo repositório, provider ou outro elemento compatível com o padrão adotado
      Seja um ORM ou um combinador de consultas feito à mão, quando o app fica a ponto de te fazer achar que “é complexo o bastante para precisar disso”, ele já ficou complexo demais para ser usado com estabilidade
      No fim, você acaba avaliando o builder na camada errada ou deixando passar que está criando consultas N+1 ao iterar pelos resultados
      ORM não é necessário
    • Vejo isso como algo próximo do que o LINQ de 2007 faz
      LINQ não é exatamente um ORM; quando você cria instruções LINQ fortemente tipadas, elas viram árvores de expressão, e depois um provedor de consultas as converte em consultas
    • Como alguém que usa tanto ORM quanto raw SQL, entendo os dois lados
      Durante o desenvolvimento, prefiro a legibilidade do ORM dentro dos modelos, mas, quando necessário, monitoreo de perto e otimizo N+1 e outras ineficiências
      O limite de quando isso é “necessário” não é claro, mas tento não otimizar cedo demais
      Em projetos novos, costumo começar pelo banco de dados e, antes de codar, pego a intuição do modelo de dados com factories, seeders e consultas em raw SQL
      ORMs como o Eloquent do Laravel têm bons métodos para resolver N+1 e fazer lazy loading, mas sempre há trade-offs
    • Também existem bibliotecas que invertem o conceito de ORM
      Em vez de permitir composição adiada de consultas, você escreve a consulta diretamente e a biblioteca gera, em tempo de compilação, o código para aquela consulta
      Por exemplo, você escreve uma consulta como getUser: SELECT * FROM users WHERE id = ?, e ela gera uma classe GetUserQuery e um método como getUser(id: String): GetUserQueryResult; acho esse modelo muito melhor
  • O principal motivo de eu não gostar de ORM é a tendência de tratar os motores SQL modernos como um depósito exageradamente burro de bits
    CTEs, joins LATERAL e cláusulas RETURNING podem simplificar muito o processamento ou eliminar a possibilidade de inconsistência de dados, mas os ORMs em geral ficam no nível de fazer um mapeamento simples de tabelas básicas e views para objetos predefinidos
    Fica pior ainda quando o ORM cria as tabelas também
    SQL é, por natureza, uma ferramenta de extração de dados e também uma linguagem de transformação, mas os ORMs quase ignoram esse lado, então muitos desenvolvedores nem chegam a saber que existe algo em SQL além de INSERT/SELECT/UPDATE/DELETE
    Existem tabelas pivô, consultas temporais, CUBE/ROLLUP, funções de janela, funções que retornam conjuntos, views materializadas, tabelas externas, processamento de JSON, tratamento de datas, restrições de exclusão, tipos como range/interval/domain, segurança em nível de linha, MERGE e mais
    É como ter uma oficina completa de ferramentas e alguém te entregar só um martelo, uma chave de fenda e um arco de serra, tentando te convencer de que isso basta, enquanto você passa a carreira sem nem saber que a poucos metros dali havia serra de bancada, tupia, lixadeira e um conjunto de cunhas

    • A maioria dos frameworks ORM tem funcionalidade para executar raw SQL, então usar ORM não significa perder acesso a esses recursos
      O ORM tende a fazer as pessoas pensarem principalmente em instruções CRUD simples, mas talvez isso seja melhor mesmo, e recursos avançados devam ser usados com parcimônia
    • Sinto que tive sorte por trabalhar principalmente em projetos sem banco de dados
      Ainda assim, quando preciso usar DB, tento de propósito usar apenas um subconjunto muito pequeno dos recursos do banco
      Isso porque vejo o “código” como uma área que posso controlar, e o “banco de dados” como uma área perigosa e difícil de alcançar, em que os erros aparecem depois, em lugares como testes de integração lentos
      A lógica que acontece dentro do DB fica fora do alcance dos testes de baixo nível, então me assusta; provavelmente eu nem usaria uma consulta select-from-select
      Deixaria com prazer a maior parte da oficina de ferramentas de lado
    • Por isso, não surpreende que muitos desenvolvedores não consigam perceber a diferença entre SQL e NoSQL
    • Em grande escala, é comum desnormalizar fortemente o banco de dados por motivos de desempenho e usá-lo como um depósito exageradamente burro de bits
    • Já participei de alguns projetos que diziam “não precisamos desses recursos sofisticados do banco de dados”, e lidar com o resultado foi frustrante
      A maior parte do tempo foi gasta criando soluções alternativas elaboradas para reinventar proteções básicas de integridade de dados
      Criar seu próprio banco de dados pode ser divertido como aprendizado, mas não em um app de produção
  • ActiveRecord sempre me pareceu bom
    Há algumas situações excepcionais, mas ele acerta bem no ponto 80/20, permite escapar para SQL quando necessário, e os hooks de ciclo de vida para organizar a lógica de domínio também são excelentes e fáceis de entender
    Gosto de ORMs pragmáticos que não escondem tudo atrás de “pacotes” nem introduzem sua própria linguagem de consulta
    Os ORMs que tentam “resolver” completamente o problema de ORM é que são difíceis de lidar

    • ActiveRecord é realmente prazeroso de usar, e, quando você encontra um caso de borda, sempre pode voltar para raw SQL
      É assim que um ORM deveria ser feito
    • É difícil imaginar refazer um grande app CRUD sem ActiveRecord; a legibilidade e a manutenibilidade piorariam
      Mas, para usá-lo corretamente, é preciso ter um bom conhecimento prévio de SQL
      Os problemas começam quando as pessoas não aprendem SQL e não entendem as consultas que o AR gera nem suas limitações
    • Não entendo muito bem as reclamações sobre ORM, mas isso pode ser porque o único ORM que usei foi o ActiveRecord
  • A premissa está errada. ORM nunca foi uma “ideia prejudicial”
    Existem ORMs horríveis de se trabalhar, mas isso não significa que o gênero inteiro seja uma má ideia
    Uso SQLAlchemy há anos com prazer justamente porque ele não tenta reinventar o próprio conceito de SQL
    Em vez disso, ele fornece uma camada conveniente para montar e passar queries, além de cuidar direito dos pequenos detalhes para que você não precise mexer neles manualmente

    • Minha experiência com ORM é quase toda com SQLAlchemy, com um pouco de aprendizado de Ecto, então ao ver esta thread fico me perguntando se todos os outros ORMs são horríveis
      Aprendendo Rust recentemente, escrever na mão o código boilerplate para lidar com CRUD simples parece doloroso e uma perda de tempo
      O ORM do SQLAlchemy pode atrapalhar um pouco em queries mais complexas ou que você quer otimizar, mas nesses casos sempre dá para descer direto para SQL
    • Faz muito tempo que eu não via alguém usar a expressão “begging the question” corretamente
    • Posso recomendar o SQLAlchemy pelo fato de ele te dar confiança para escrever SQL de um jeito em que o código corresponde bem à query
  • Como qualquer coisa, há situações em que encaixa bem e outras em que não, e tecnologia pode ser facilmente abusada ou usada de forma errada
    Por exemplo, ORMs como o Entity Framework do .NET podem ser um grande trunfo, especialmente ao trabalhar com uma abordagem database-first
    Se for um banco com centenas de tabelas e relacionamentos de chave estrangeira corretos, um ORM ajuda a navegar por esquemas complexos e fornece verificação em tempo de compilação quando há mudanças
    SQL embutido é uma faca de dois gumes que parece trazer vantagens de performance, mas é muito difícil de manter quando se trata de SQL verboso hardcoded, especialmente em joins
    Não estou falando de quando há 5 a 10 tabelas, e sim de quando há centenas
    Não pretendo convencer ninguém, mas você não deve simplesmente acreditar no que leu na internet sobre boas práticas
    As pessoas podem estar falando de coisas completamente diferentes, e sempre vai haver desenvolvedores ruins usando qualquer tecnologia

  • Se você não usa ORM nem outra interface para DB, no fim acaba escrevendo e mantendo uma por conta própria para coisas como CRUD
    E há uma boa chance de ela vir com bugs estranhos, edge cases e brechas de segurança
    Também há um problema em ensinar princípios como SOLID em disciplinas universitárias como se fossem princípios de design de software
    Na academia isso faz sentido, porque restrições como tempo, manutenibilidade, dinheiro e esforço importam menos, mas quando recém-formados entram no mercado acontece um choque bem ruim
    Porque eles se acostumam a passar o dia inteiro aparando pelo em iaque e reinventando a roda em busca da solução “perfeita”
    Se não houver desenvolvedores sêniores/líderes suficientes e competentes para conter isso, o resultado são produtos muito interessantes, estouros de orçamento, grandes incêndios, ou alguma combinação disso
    Pior ainda é quando algo criado na academia e para a academia é solto para o público em geral
    Um bom/mau exemplo clássico é o OpenStack, que tem alças e pontos de ajuste demais e componentes modularizados de forma insana para suportar os ambientes especiais do CERN e de centenas de universidades, mas é tão bizantino que é quase impossível começar a usá-lo

    • Nesta thread há muita reclamação de que ORMs não cumprem as promessas do fornecedor, e isso é verdade
      ORMs não trocam de banco sem esforço, não eliminam a necessidade de aprender e entender o SQL que geram, nem deixam o schema suave e sem atrito
      Ainda assim, a razão para usá-los é que eles são uma abstração padrão que de qualquer forma teria de ser replicada
      Eles permitem cache de acesso ao DB, algo surpreendentemente difícil de fazer em escala com SQL manual
      Junto vêm ferramentas padronizadas e boas práticas que podem tornar irrelevantes problemas como N+1
      O principal problema dos ORMs são as expectativas erradas e os ORMs ruins
      Se quiser entender o valor de um ORM, abra um projeto escrito sem ORM e tente mudar qualquer coisa
    • “No fim você acaba construindo um por conta própria” só é verdade se você insistir em estruturar a lógica com base em objetos, e não em “linhas”
      Veja https://news.ycombinator.com/item?id=36498583
    • Alguns departamentos e várias empresas sofreram ou fracassaram porque um ou alguns supergênios perseguiam a perfeição
      Nada útil avançava, ou demorava de 20 a 100 vezes mais do que uma abordagem rápida e suja
      O pior caso foi quando uma equipe de designers HTML experientes foi forçada a aprender programação funcional
      O mago da configuração de backend era uma maravilha da engenharia moderna e do design elegante, mas levou 1 ano para 10 pessoas construírem
      Dinheiro de VC deixa as pessoas estranhas
    • Ouvi tanta coisa negativa sobre SQLAlchemy que decidi fazer meu próprio query builder leve, mas 8 meses depois acabei usando SQLAlchemy mesmo
      A linguagem SQL é muito complexa, e criar um query builder realmente completo e com todos os recursos não é nada trivial
      Isso mesmo deixando de lado a parte de mapeamento relacional em si
    • É melhor usar um bom ORM; caso contrário, você acaba assumindo metade do trabalho de um ORM ruim por conta própria
  • No caso de SQL, acho que este é um daqueles casos em que o certo é “simplesmente programe essa droga você mesmo”
    Não faz muito sentido gastar tempo aprendendo SQL ou uma biblioteca ORM; é melhor aprender e usar SQL diretamente
    Acesso a banco de dados provavelmente é algo fundamental com que você vai lidar durante toda a carreira, então o melhor é aprender a tecnologia real em si
    Com CSS é parecido: em vez de aprender uma biblioteca de CSS, você deveria aprender e usar CSS
    Na verdade, isso vale para quase todos os aspectos do desenvolvimento frontend; em vez de uma “biblioteca de formulários”, basta lidar diretamente com a API de formulários do navegador
    Pessoalmente, achei SQL muito mais fácil de aprender do que qualquer ORM
    Não vale a pena desperdiçar o custo de aprender a coisa errada

    • Se você aprender SQL primeiro, também vai saber quando faz sentido usar um ORM e poderá avaliá-lo melhor
      O mesmo vale para CSS: se você conhece CSS, fica muito mais flexível e entende muito melhor quando escolhe uma biblioteca por conveniência
    • SQL já foi chamado de linguagem eterna
      Passando por mainframes, desktops, cliente/servidor, web e várias linguagens sobre essas plataformas, SQL sempre foi o fio comum
      Concordo totalmente que um desenvolvedor que entende bem a camada de dados e o que acontece por baixo é um desenvolvedor mais forte
      Se você vai gastar tempo aprendendo as peculiaridades de um ORM, fica a pergunta clássica: por que não investir esse tempo em aprender SQL?
      Os juros compostos da experiência com SQL têm grande chance de valer mais, daqui a 10 a 15 anos, do que o ORM de uma plataforma ou linguagem específica
      Há motivos para aprender e usar ORM, mas não dá para pender para esse lado só porque você não quer aprender SQL
    • A ideia central é mais “aprenda os fundamentos primeiro antes da abstração”
      Assim você sabe o que está pagando por aquela abstração. Claro, se for uma “abstração sem custo”, aí é diferente
    • Escrevo SQL diretamente desde 1992, com Pro*Pascal e CS130
      Mas hoje uso crud do azer, que acaba sendo classificado como ORM, por causa do marshaling/unmarshaling com tipos de Go
      A biblioteca padrão sql do Go é básica demais, então você praticamente precisa escrever por conta própria o marshaling/unmarshaling de objetos, o que é realmente tedioso
      Se eu usar ORM hoje em dia, provavelmente seria só para isso
  • Gosto de micro ORMs de “meio-termo”, como Dapper e Diesel
    Você escreve as queries em SQL, mas ganha tipagem forte e mapeamento automático do conjunto de resultados para objetos
    É como ter produtividade junto com uma linguagem de consulta “de verdade”, completa em recursos
    Também passei a gostar da abordagem de usar o mapeador de objetos apenas para queries de leitura
    Atualizações são feitas com um padrão de comando, isto é, stored procedures, e dá para mapear isso para parecer métodos nativos

    • Dapper foi, de longe, a solução de acesso a dados mais prazerosa que já usei
      Os desenvolvedores precisam parar de fingir que SQL não existe e simplesmente aceitar isso
    • Gosto de não precisar escrever tudo à mão para que as funções do modelo acabem mapeando só para SQL, nem de usar PHP comercial repetitivo para executar queries parametrizadas corretamente
      Eloquent abstrai bem esse trabalho braçal e permite focar na lógica
      Estou reescrevendo um app PHP “das antigas”, que só tinha arrays e queries, para uma estrutura com modelos e Eloquent, e a sensação é de mudança total de jogo
    • Gosto desse meio-termo. Em TypeScript há, por exemplo, Kysely ou o meu projeto Zapatos
    • Acho que esse é o ponto ideal
      No passado, quando usava SQLite em .NET, também criei uma biblioteca wrapper nessa linha: https://github.com/zmj/sqlite-fast
  • Esta thread mostra bem o domínio de mindshare dos ORMs
    Em quase todos os comentários, a alternativa implícita ao ORM é SQL bruto como string literal dentro do código da aplicação
    Já existiam, seis anos atrás, ferramentas que usavam SQL como uma linguagem de fato e geravam wrappers que expunham as queries como métodos na aplicação
    Coisas como queryfirst, pgtyped, pugsql e sqlc
    Isso era uma mudança de paradigma, ou pelo menos poderia ter sido, e fica claro que é uma forma superior de trabalhar, mas ORM e essa discussão interminável sugam todo o oxigênio e isso continua na periferia

    • Sim. Em Go também existe sqlc
      SQL é uma linguagem, e uma linguagem de altíssimo nível
      Tentar concatenar SQL a partir de uma linguagem de nível mais baixo é um caso clássico de “quando você tem um martelo, tudo parece prego”
      Por exemplo, se você está programando em assembly, que é de baixo nível, para interagir com um sistema grande, e a documentação desse sistema disser que as entradas só podem ser expressas em JavaScript, você tem uma escolha
      Pode trazer alguma biblioteca obscura que permita montar tudo em assembly e assim evitar dar commit em arquivos xxx.js no repositório, ou pode simplesmente usar a força da linguagem de alto nível e expressar isso em um arquivo .js
    • Depois de usar sqlc em um projeto, acho que não consigo mais voltar atrás
      Você passa a ter uma única fonte da verdade para as queries SQL em uso, e como o que você realmente escreve e mantém são as próprias queries, fica fácil fazer otimizações como criar novos índices
    • Sempre achei ActiveRecord fraco, mas sempre gostei do arel, que ele usa internamente para montar queries
      Colocar uma abstração em cima de strings de SQL bruto é muito útil, mas fingir que relações são objetos é um jeito complicado e embolado de fazer isso
    • O Enterprise Objects Framework da NeXT já dava suporte a isso há mais de 25 anos
      O TopLink provavelmente também
      Era assim que ele tratava o mapeamento entre stored procedures e entidades locais
    • Fiquei curioso para saber quais ferramentas são essas