Size: a a a

NodeUA - JavaScript and Node.js in Ukraine

2020 July 20

Т

Тёмыч in NodeUA - JavaScript and Node.js in Ukraine
👌
источник

s

std::Veetaha in NodeUA - JavaScript and Node.js in Ukraine
Использовать джаваскрипт тоже не стыдно
источник

AL

Andrey Listochkin in NodeUA - JavaScript and Node.js in Ukraine
Выше @ellenaua правильно написала. Не возьмешь ОРМ - скатишься к тому, что напишешь свой. Только у TypeORM / Bookshelf / Sequelize за плечами тысячи человеко часов ушедших на отлов багов, закрытие юскейсов, работу над эргономикой АПИ, а у твоего - пара десятков.

Есть проблема с доками - как написал @nikita_ua доки либо не полные, либо люди не тратят время, чтобы в них разобраться.

На практике это приводит к тому, что люди решают, что выбранный ОРМ их юскейс не покрывают и “вынуждает” их писать свои голые SQL-запросы. Но это не проблема, если у тебя нет видения того, что “ОРМ = все через ОРМ, никакого сиквела в коде”. А если к орму относиться прагматично, то замечаешь, как много простого и рутинного кода он тебе экономит.

Не нравится ормовский API для запросов - да не используй. Задеклалрируй таблицы им, юзай его для миграций, для простых инсертов-апдейтов, а все сложое делай SQLом. Но если ты писать свою абстракцию, а взять готовую, то ты получишь много приятных штук:
- миграции
- тайпчеккинг для твоих объектов
- FK и индексы, которые за тебя генерят
- коннекшен пулинг, логирование сгенеренного SQLа

Нах тратить время, чтобы все это ре-имплементить в твоем проекте - жизнь слишком коротка, чтобы писать логгер для запросов в базу.
источник

EM

Eugene Mikeshin in NodeUA - JavaScript and Node.js in Ukraine
Timur Shemsedinov
Официальная позиция метархии: использовать ORM - не стыдно, используйте, но повторяйте себе каждый день, что это не стыдно
👏
источник

TS

Timur Shemsedinov in NodeUA - JavaScript and Node.js in Ukraine
Andrey Listochkin
Выше @ellenaua правильно написала. Не возьмешь ОРМ - скатишься к тому, что напишешь свой. Только у TypeORM / Bookshelf / Sequelize за плечами тысячи человеко часов ушедших на отлов багов, закрытие юскейсов, работу над эргономикой АПИ, а у твоего - пара десятков.

Есть проблема с доками - как написал @nikita_ua доки либо не полные, либо люди не тратят время, чтобы в них разобраться.

На практике это приводит к тому, что люди решают, что выбранный ОРМ их юскейс не покрывают и “вынуждает” их писать свои голые SQL-запросы. Но это не проблема, если у тебя нет видения того, что “ОРМ = все через ОРМ, никакого сиквела в коде”. А если к орму относиться прагматично, то замечаешь, как много простого и рутинного кода он тебе экономит.

Не нравится ормовский API для запросов - да не используй. Задеклалрируй таблицы им, юзай его для миграций, для простых инсертов-апдейтов, а все сложое делай SQLом. Но если ты писать свою абстракцию, а взять готовую, то ты получишь много приятных штук:
- миграции
- тайпчеккинг для твоих объектов
- FK и индексы, которые за тебя генерят
- коннекшен пулинг, логирование сгенеренного SQLа

Нах тратить время, чтобы все это ре-имплементить в твоем проекте - жизнь слишком коротка, чтобы писать логгер для запросов в базу.
Жизнь слишком коротка, чтобы говнокодить, возми готовый говнокод
источник

AL

Andrey Listochkin in NodeUA - JavaScript and Node.js in Ukraine
Именно.
источник

Т

Тёмыч in NodeUA - JavaScript and Node.js in Ukraine
Timur Shemsedinov
Жизнь слишком коротка, чтобы говнокодить, возми готовый говнокод
а чего сразу knex?
источник

DT

Dan The Great 🔥 in NodeUA - JavaScript and Node.js in Ukraine
Andrey Listochkin
Я юзаю TypeORM для работы с базой. Он тоже умеет миграции. Генерит файл с 2мя функциями.

К запросам у меня вопросов нет. Если есть связь между сущностями, и ты ее объявил как

projects: Project[] // внутри User

То TypeORM будет генерить left join “project” всегда, когда ты просишь юзера.

А если объявить как

projects: Promise<Project[]>

то проекты по умолчанию догружаться не будут.

И с TypeScript оно работает из коробки
тайпорм - та еще помойка
у них даже нет нормального createdAt/updatedAt автоматического апдейта, хоть в документации написано, что должно апдейтить
хуки вообще не работают и кучу багов (чекай ишьюз в гитхабе)
приходится все писать в билдере, но уже легче обычный sql написать (это кстати один из примеров, когда действительно, ормка- зло)

но в других случаях, например, когда нужно использовать какой-то findOne или findAll и where, ордерами и реляциями, то ормка справляется (не думаю, что кто-то в 2020 будет ныть на то, что ормка сьедает на условных килобайт больше, при том, что вы на джсе пишите)
нужно понимать, что ормка - удобная абстракция над sql запросами, поэтому если вы выбираете неизвестную никому ормку и ноете, что она лагает или в ней много багов - вы идиот, так как уже легче написать все на sql
аналогично, если ормка жрет кучу ресурсов бд, то это означает, что или запрос слишком жирный (и его надо написать на sql для оптимизации), или вы неправильно/не до конца написали метод ормки (например, вы жалуетесь, что ормка по дефолту берет все атрибуты модели, то есть все колонки таблицы, а на самом деле можно было указать, чтобы возвращать только такие колонки или например возвращать все не в модели ормки, которая жрет много памяти и много всего неочевидного, а в raw json и потом работать с этими данными)

но так-то помните, что в 99% случаях проблема сидит в 30 см от монитора
источник

Т

Тёмыч in NodeUA - JavaScript and Node.js in Ukraine
Dan The Great 🔥
тайпорм - та еще помойка
у них даже нет нормального createdAt/updatedAt автоматического апдейта, хоть в документации написано, что должно апдейтить
хуки вообще не работают и кучу багов (чекай ишьюз в гитхабе)
приходится все писать в билдере, но уже легче обычный sql написать (это кстати один из примеров, когда действительно, ормка- зло)

но в других случаях, например, когда нужно использовать какой-то findOne или findAll и where, ордерами и реляциями, то ормка справляется (не думаю, что кто-то в 2020 будет ныть на то, что ормка сьедает на условных килобайт больше, при том, что вы на джсе пишите)
нужно понимать, что ормка - удобная абстракция над sql запросами, поэтому если вы выбираете неизвестную никому ормку и ноете, что она лагает или в ней много багов - вы идиот, так как уже легче написать все на sql
аналогично, если ормка жрет кучу ресурсов бд, то это означает, что или запрос слишком жирный (и его надо написать на sql для оптимизации), или вы неправильно/не до конца написали метод ормки (например, вы жалуетесь, что ормка по дефолту берет все атрибуты модели, то есть все колонки таблицы, а на самом деле можно было указать, чтобы возвращать только такие колонки или например возвращать все не в модели ормки, которая жрет много памяти и много всего неочевидного, а в raw json и потом работать с этими данными)

но так-то помните, что в 99% случаях проблема сидит в 30 см от монитора
@BeforeUpdate()
 updateTimestamp() {
   this.updatedAt = new Date;
 }
источник

DT

Dan The Great 🔥 in NodeUA - JavaScript and Node.js in Ukraine
Тёмыч
@BeforeUpdate()
 updateTimestamp() {
   this.updatedAt = new Date;
 }
Скатываемся к проблеме, что хуки не работают))
Точнее в одних методах ормки они работают, а в других нет
А-ля в апдейте не сработает, а в сейве - да
(Это еще хуже, чем если бы они просто не работали)
источник

AL

Andrey Listochkin in NodeUA - JavaScript and Node.js in Ukraine
> хуки вообще не работают и кучу багов (чекай ишьюз в гитхабе)

Хуки - в принципе странная хрень. Я в транзакции серию запросов делаю или триггеры юзаю.

> приходится все писать в билдере, но уже легче обычный sql написать (это кстати один из примеров, когда действительно, ормка- зло)

имхо это проблема любого embedded-языка. Если в ноде из JS вызывать shell или рендерить html-фрагменты, то тоже выгялидит жутко. Я большие запросы тоже в raw sql держу, чтобы код читался лучше. Одна длинная стринга с SQL всегда будет читаться лучше, чем суп из .a(‘bcd’).d(‘efg’)...

> createdAt/updatedAt

такое нормально нигде не работает. Ни в Java / Hibernate, ни в Ruby / ActiveRecord, ни в Python / SqlAlchemy. Есть один рабочий способ - триггеры в базе, я всегда так и делаю.
источник

DT

Dan The Great 🔥 in NodeUA - JavaScript and Node.js in Ukraine
вот странно, люди считают что ормки - это зло, а значит хранимые процедуры и триггеры - нет))
источник

DT

Dan The Great 🔥 in NodeUA - JavaScript and Node.js in Ukraine
Andrey Listochkin
> хуки вообще не работают и кучу багов (чекай ишьюз в гитхабе)

Хуки - в принципе странная хрень. Я в транзакции серию запросов делаю или триггеры юзаю.

> приходится все писать в билдере, но уже легче обычный sql написать (это кстати один из примеров, когда действительно, ормка- зло)

имхо это проблема любого embedded-языка. Если в ноде из JS вызывать shell или рендерить html-фрагменты, то тоже выгялидит жутко. Я большие запросы тоже в raw sql держу, чтобы код читался лучше. Одна длинная стринга с SQL всегда будет читаться лучше, чем суп из .a(‘bcd’).d(‘efg’)...

> createdAt/updatedAt

такое нормально нигде не работает. Ни в Java / Hibernate, ни в Ruby / ActiveRecord, ни в Python / SqlAlchemy. Есть один рабочий способ - триггеры в базе, я всегда так и делаю.
> Хуки - в принципе странная хрень. Я в транзакции серию запросов делаю или триггеры юзаю.

как по мне, хуки - это те же самые триггеры, только на стороне приложения, а не бд
их легче отслеживать, так как они лежат в vcs, легче менять и они будут всегда работать (имеется ввиду, что исключается случай, когда какой-то кретин удалит триггер с бд)


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

но, тем не менее, заслуживают на жизнь в некоторых кейсах. Главное не переборщить

> имхо это проблема любого embedded-языка. Если в ноде из JS вызывать shell или рендерить html-фрагменты, то тоже выгялидит жутко. Я большие запросы тоже в raw sql держу, чтобы код читался лучше. Одна длинная стринга с SQL всегда будет читаться лучше, чем суп из .a(‘bcd’).d(‘efg’)...

нет. если у вас настроен линтер, то адекватно отображается чейнинг (если конечно, он действительно не состоит из оверсложных действий).
ну так а если делаешь то же самое, но на плюсах или шарпах, разве не также само используешь билдер? не совсем понял, причем тут js вообще, я привел конкретно фичу ормки, что можно юзать ее методы, а можно писать костыль в виде скл билдера, хотя на скле легче

> такое нормально нигде не работает. Ни в Java / Hibernate, ни в Ruby / ActiveRecord, ни в Python / SqlAlchemy. Есть один рабочий способ - триггеры в базе, я всегда так и делаю.
во первых, хотел сказать, что суть не в том, работает или нет, а в том, что в тайпорме четко прописано
Special column that is automatically set to the entity's insertion time. You don't need to write a value into this column - it will be automatically set. Example:

Это означает, что подобный функционал обязан работать
но по факту получаем или баг, или просто откровенную ложь, что вообще не позволительно

так-с, а теперь давайте посмотрим, как достичь этого в разных тулзах:
https://sequelize.org/master/manual/model-basics.html#timestamps
в Hibernate достигается с помощью хуков (не написано, что такой функционал есть)
в ActiveRecord тоже кстати с этим свои приколы, но частично есть обновление колонок: https://tech.lendinghome.com/keeping-data-in-sync-with-activerecord-updatedat-95bd76955a01
аналогично, в SqlAlchemy достигается путем хуков
источник

AL

Andrey Listochkin in NodeUA - JavaScript and Node.js in Ukraine
> как по мне, хуки - это те же самые триггеры, только на стороне приложения, а не бд
их легче отслеживать, так как они лежат в vcs, легче менять и они будут всегда работать (имеется ввиду, что исключается случай, когда какой-то кретин удалит триггер с бд)

код в бд тоже в VCS. Он в файлах миграций живет или в файлах схемы.

> также на хуках можно писать комплексные решения, чего не сделаешь на триггерах.

сложные вещи я кладу рядом в основном коде. Пример из пальца: создали юзера - отправили мейл. У меня отправка мейла не будет лежать в хуке на сохранение юзера, а в том месте, где мы его сохраняем, рядом будет вызов на мейлер.

> но, тем не менее, заслуживают на жизнь в некоторых кейсах.

у меня видимо таких кейсв нет.

> нет. если у вас настроен линтер, то адекватно отображается чейнинг (если конечно, он действительно не состоит из оверсложных действий).

проверил по приложению. Запросы на 50+ строк sql написаны в raw sql. Запросы на ~10-20 строк - местами raw sql, местами через билдер. Часть из них руки чешутся переписать на raw sql, чтобы читалось лучше.

мой поинт был в том, что это не проблема ORM, а проблема “вставим в язык А язык Б”

> получаем или баг, или просто откровенную ложь, что вообще не позволительно

тогда это везде баг и “непозволительно”. В любом ОРМе на любом зыке если ты через raw запрос изменишь значение в базе, поле updatedAt не поменяется.

А с триггером поменяется не зависимо от того, делаешь ты запрос средствами ОРМа или нет. Поэтому для таких вещей они - в самый раз.
источник

DT

Dan The Great 🔥 in NodeUA - JavaScript and Node.js in Ukraine
Andrey Listochkin
> как по мне, хуки - это те же самые триггеры, только на стороне приложения, а не бд
их легче отслеживать, так как они лежат в vcs, легче менять и они будут всегда работать (имеется ввиду, что исключается случай, когда какой-то кретин удалит триггер с бд)

код в бд тоже в VCS. Он в файлах миграций живет или в файлах схемы.

> также на хуках можно писать комплексные решения, чего не сделаешь на триггерах.

сложные вещи я кладу рядом в основном коде. Пример из пальца: создали юзера - отправили мейл. У меня отправка мейла не будет лежать в хуке на сохранение юзера, а в том месте, где мы его сохраняем, рядом будет вызов на мейлер.

> но, тем не менее, заслуживают на жизнь в некоторых кейсах.

у меня видимо таких кейсв нет.

> нет. если у вас настроен линтер, то адекватно отображается чейнинг (если конечно, он действительно не состоит из оверсложных действий).

проверил по приложению. Запросы на 50+ строк sql написаны в raw sql. Запросы на ~10-20 строк - местами raw sql, местами через билдер. Часть из них руки чешутся переписать на raw sql, чтобы читалось лучше.

мой поинт был в том, что это не проблема ORM, а проблема “вставим в язык А язык Б”

> получаем или баг, или просто откровенную ложь, что вообще не позволительно

тогда это везде баг и “непозволительно”. В любом ОРМе на любом зыке если ты через raw запрос изменишь значение в базе, поле updatedAt не поменяется.

А с триггером поменяется не зависимо от того, делаешь ты запрос средствами ОРМа или нет. Поэтому для таких вещей они - в самый раз.
вы сами можете решить: использовать хуки или триггеры в вашей инфрастуктуре
но использовать хуки - куда легче, так как сразу видишь в коде, что происходит, а триггеры, если их нет в vcs (когда бд была еще до приложения), нужно дебажить и додумываться, что есть триггер, который как-то неадекватно ломает логику

> сложные вещи я кладу рядом в основном коде. Пример из пальца: создали юзера - отправили мейл. У меня отправка мейла не будет лежать в хуке на сохранение юзера, а в том месте, где мы его сохраняем, рядом будет вызов на мейлер.

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

> тогда это везде баг и “непозволительно”. В любом ОРМе на любом зыке если ты через raw запрос изменишь значение в базе, поле updatedAt не поменяется.

нет, вы неправильно поняли, о чем я говорю
у ормы есть фича добавить декоратор на аттрибут модели, чтобы определить ее как createdAt/updatedAt/deletedAt и сама орм занимается их обновлением, согласно ее документации.
в тайпорме это тоже прописано, но на практике не работает :)
причем тут raw запрос вообще не понял, мы ведь про ормки говорим

с другим всем согласен
источник

АН

Александра Неважно... in NodeUA - JavaScript and Node.js in Ukraine
А откуда, позвольте уточнить, вообще взялись сомнения по поводу полезности ORM? Они, как и (почти) все остальное, являются инструментом, который можно использовать, но как бы никто не заставляет. И у каждого проекта могут быть специфичные нужды.

Допустим, миграции - удобный инструмент, если мы говорим про проект с CI/CD или про проект, который должно быть по возможности легко деплоить, для проекта с версиями. Можно и дамп структуры БД прикладывать, можно даже писать ALTER ручками, но зачем?

Допустим, хуки - очевидно, что они тоже иногда бывют полезны. Например, если на них висит что-либо с относительно тяжелыми вычислениями, или же просто не хочется размазывать бизнес-логику приложения по собственно приложению, SQL итд. Опять же, никто не заставляет.

Допустим, запросы, даже трехэтажыне, с кучей join - если на проект заходят полтора человека в год, потери в производительности будут несущественны, ну займет запрос 0.08 сек вместо 0.01 - и что? А на выходе имеется уже готовый объект, без дополнительных велосипедов. Главное - этот велосипед еще и отлаженный.

Допустим, какой-нибудь жесткий хайлоуд и/или что-то совсем уж нестандартное - если есть смысл в своем велосипеде - вперед. Но, опять же, если есть смысл. А какой смысл делать то, что не нужно? Или же наоборот, тянуть в очередной hello world жирные зависимости ради одного запроса не имеет смысла.

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

Допустим, автор проекта лютый новичок, у которого не получается что-то - повод ли это гнать на ORM, мол, лишняя сущность, перегруженность, что-то не выходит, или повод пойти и подучить матчасть?
источник

ES

Elena Sharovar in NodeUA - JavaScript and Node.js in Ukraine
Правильно. Потому что если вы работаете на рынок - то основная задача - это в приемлемые сроки и с приемлемым качеством решить бизнес-задачу клиента, а не написать идеальный код или ORM с нуля за 100500 часов и столько же денег ))) Если ORM именно для проекта NNN дает приемлемое качество то юзайте на здоровье.
источник

DT

Dan The Great 🔥 in NodeUA - JavaScript and Node.js in Ukraine
Elena Sharovar
Правильно. Потому что если вы работаете на рынок - то основная задача - это в приемлемые сроки и с приемлемым качеством решить бизнес-задачу клиента, а не написать идеальный код или ORM с нуля за 100500 часов и столько же денег ))) Если ORM именно для проекта NNN дает приемлемое качество то юзайте на здоровье.
даже если не на рынок - если вы не пишите специальное приложение, которое заточено под взаимодействие с БД - ормка сейвит кучу времени, которое может быть потраченое впустую на изобретение своего велосипеда
источник

Ⓟⓐⓥⓔⓛ in NodeUA - JavaScript and Node.js in Ukraine
Elena Sharovar
Правильно. Потому что если вы работаете на рынок - то основная задача - это в приемлемые сроки и с приемлемым качеством решить бизнес-задачу клиента, а не написать идеальный код или ORM с нуля за 100500 часов и столько же денег ))) Если ORM именно для проекта NNN дает приемлемое качество то юзайте на здоровье.
Четка
источник

АБ

Артур Бердыев... in NodeUA - JavaScript and Node.js in Ukraine
Ну да, ну да, а потом мы удивляемся, почему пакеты в npm в стиле нахождение остатка от деления набирают миллиарды загрузок
источник