Как стать автором
Обновить

Комментарии 30

Здравствуйте, ActiveRecord это ORM-подход.

В статье предлагается не-ORM подход и, цитата,

Query пишется на нативном языке базы (например, SQL)

поэтому, нет

Не очень понял последнее предложение.

В dapper можно использовать параметризированные запросы и анонимные типы. И это считается лучшей практикой, чем добавлять значения в строку.

У dapper есть возможность работать с динамической типизацией (dto не нужен при этом).

Еще есть dapper query builder. Это можно использовать в качестве построителя запроса.

а также pdo для php или аналоги из любого другого языка, т.к упомянутая в посте абстракция базовая для большинства языков

  • Query пишется на нативном языке базы (например, SQL)

В случае SQL - не просто на нативном языке, а на конкретном его диалекте, соответствующем используемой СУБД, а зачастую ещё и конкретной её версии.

  • Query проверяется на этапе компиляции, типы аргументов тоже

Угу... то-то регулярно попадаются вопросы типа "в штатном клиенте работает, а из программы нет". Для проверки нужно, чтобы в приложении работал полноценный парсер-валидатор, опять же учитывающий конкретную версию конкретной СУБД. К тому же некоторые СУБД используют "мягкую" систему типов.

Диалект и версия СУБД? А почему эта проблема должна перекладываться на бэк-разраба? Извините-подождите, вы решили поставлять свою новую, самую быструю и удобную СУБД - реализуйте пожалуйста драйвер по принятым стандартам SQL, чтобы у всех все работало.

вы решили поставлять свою новую, самую быструю и удобную СУБД - реализуйте пожалуйста драйвер по принятым стандартам SQL, чтобы у всех все работало

Так в рамках стандарта-то как раз у всех работает (да, бывают редкие отклонения, типа уникального NULL в SQL Server - но это всё же исключения, как правило исторически обоснованные). Фигня в том, что минимум половина, а обычно ещё больше, эффективных конструкций стандартом не покрывается и требует использования СУБД-специфичных кодовых конструкций.

А почему эта проблема должна перекладываться на бэк-разраба?

А вот не нужно экономить и валить всё и вся на одного разработчика. Пусть работает в тандеме с SQL-разработчиком.

Слава богу, я не один с такими мыслями...
Надоела эта куча промежуточных слоеностей их фреймворков, библиотек, паттернов.
Все программирование сводится к изучению нашлепок, а не самого ЯП и алгоритмов.

Если кому-то не нравится ORM - есть куча других решений. Начиная с JDBC и заканчивая JOOQ, QueryDSL, i/my Batis, SpringData - имя им легион.

Чем предлагаемое решение отличается от имеющихся пока не ясно, если честно.

Да, эти решения можно отнести к другой категории. Тем не менее, они тоже предоставляют очень большой API, и не реализуют концепций, указанных в третьем разделе настоящей статьи. Что, их и приводит к довольно малой рыночной нише

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

connection.fetch(query, args) -> result - норм тема, особенно если в query вызов хранимки, надо что-то похожее на универсальные хранимки до уровня БД, пока идея ждет своего героя.

Каждый раз когда я вижу нужно отказаться от ORM люди не понимают зачем они нужны. Они просто занесли их в проект потому что все так делают. Если ORM мешается вам на проекте перестаньте его использовать. Сила ORM проявляется только когда у вас 100500 CRUD есть с которыми вам надо работать. Плюс уменьшаются накладные расходы на DTO. Если же у вас этого всего нет зачем вы тащите в проект ORM?

Мне кажется, но в мире dotnet этих проблем уже нет. Хочешь быть поближе к базе, то есть dapper и linq2db. Хочешь удобств и функциональности, то есть ef core:

свой язык декларации схемы данных

Миграции ef core: один язык для разных СУБД. В идеале модели не меняются, для другой СУБД надо только сконфигурировать новый контекст.

свой язык запросов (Criteria Api, HQL, JPQL)

LINQ -- это лучше, чем учить t-sql, pl/sql и pgplsql. Но если очень хочется, то есть возможность выполнить raw sql.

свой оптимизатор (anti N+1)

Здесь от провайдера зависит, в текущих реализациях не сталкивался с такой проблемой.

свой pl/SQL - API вокруг Entity Manager, Sessions со скриптингом на Java

DbContext, DbSet, IQueryable, Expression -- вполне понятные стабильные api.

connection.fetch(query, args) -> result

Идея хорошая, но есть ряд проблем:

  • нужна поддержка на уровне языка, у шарпа есть source generators, а в мире java что?

  • где брать метаданные для вывода типов? что делать если sql динамический или СУБД не умеет отдавать эти данные?

Начнешь эти проблемы решать и сделаешь еще один орм, только с сырым sql :)

В предложенной концепции, схема декларируется в SQL скриптах миграции. Все запросы пишутся "по месту", то есть с базы получаются нужные проекции в виде dto. Сами dto это рекорды или классы с final полями - никаких аннотаций на них нет. Поля dto инферятся автоматически, исходя из запросов. Все решение 100% typesafe

Концепция хорошая, но не новая :) В ef core есть scaffold, который по существующей базе сгенерирует dto и контекст бд, в linq2db есть шаблоны для генерации dto. Для проекций dto в linq изначально имеет анонимный тип, который при необходимости с помощью рефакторинга превращается в именованный тип. Не удивлюсь, если для hibernate и jooq можно также всё настроить.

Да, так и есть, однако если посмотреть на market share этих технологий, то мы увидим тотальное доминирование ORM. Значит, на это есть причины. И, как нам кажется, причины в деталях реализации. Кстати, можете рассказать что на практике значит "при необходимости с помощью рефакторинга превращается в именованный тип" ? Как выглядит такой рефакторинг?

Было:

Стало после рефакторинга "To named type" в Rider:

И да, dbContext и тип Sign получены командой `dotnet ef dbcontext scaffold` из существующей БД.

Нам надо, чтобы имея dto - классы объектов, и таблицы базы данных, сохранять и доставать в/из базы одним вызовом. При этом dto не должно обременяться барахлом из ОРМ, то есть, детали реализации persistence не должны вылезать дальше слоя persistence. При этом dto и таблицы базы могут различаться, иногда весьма значительно (диктуются деталями реализации хранения в базе). Какая еще генерация?

Кроме того, надо реализовать множество срезов таблицы, когда в dto должно попадать только часть полей исходной таблицы (по требованиям производительности). А еще надо сохранять отдельные поля. Много и часто.

Хибернат при таких условиях - тяжкие гири, потому что приходится воротить классы entity, трансляцию dto в entity и обратно, сохранение отдельных полей в виде достать объект - изменить поле - сохранить объект.

Интерес представлял Spring Data JDBC. Вектор отличный. Но и он недостаточно хорош, потому что детали реализации persistence лезут в бизнес-слои в виде необходимости классы dto загрязнять @Entityи @FifthColumn

В связи с этим материал автора представляет большой интерес, но нужно больше информации. Как задается dto в persistence, где указывается соответствие полей dto полям таблиц? Для нас размещение такой информации в базе и генерация по ней кода неприемлемо, потому что необходимо менять слой persistence от базы к базе и даже к nosql, при этом требуется, чтобы слои бизнеса не менялись.

Да, возможно dto я зря употребил, читай как entity. Но в ef core entity можно описывать без атрибутов/аннотаций, вся конфигурация будет в DbContext. Про java не скажу, но не понятно, почему не рассматриваете jooq https://www.jooq.org/doc/latest/manual/sql-execution/fetching/pojos/.

Для нас размещение такой информации в базе и генерация по ней кода неприемлемо, потому что необходимо менять слой persistence от базы к базе и даже к nosql, при этом требуется, чтобы слои бизнеса не менялись.

Если у вас entity и dto сильно отличаются, то здесь без написания кода не обойтись.

Ну, для селектов это хорошо работает, да. Но орм-ы то и вводят свой уровень сложности для того, чтобы мочь не только селекты выполнять. (Но с мыслью, что это вторая субд по объему доки я очень согласен, разработчиками орм декларируется, что разработчику сложно изучить нативный уровень бд и пусть он лучше изучит «простой» орм, но реальность приводит к тому, что нужно экспертно владеть и базой и орм, чтобы мочь разбираться в возникающих проблемах).

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории