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

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

1,56,00,00,000

Это точно был Гугл? Мой выдает правильное группирование - 1,290,000,000.

Кстати, это 1,56 араб или 156 крор в индийской нумерации. ¯\_(ツ)_/¯

Странно, что результаты разные...

Чей Гугл больше?
Чей Гугл больше?

Поздравляю, этот roadmap, как мне кажется, может сделать даже из новичка Java-разработчика с эквивалентом 7-8 лет

В годах Меркурия считаете?

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

Улыбнуло)

А если я сначала прочитаю вот это всё, а потом 4 года от строчки до строчки, что получится?

А если сначала четыре года, а потом начать читать?

:-)

Честно говоря, Kotlin не имеет минусов перед Java, но имеет поюсы.

Ужасающая многословность java превращает код в череду проверок на налл, где постоянно будут ошибки из-за копипастов, а также ужасный JPA и практика использовать геттеры-сеттеры

Всё, что сейчас добавляют в Джаву, сделано позже, чем в Котлине, но при этом лучше, чем в Котлине. Целая команда крутых архитекторов сильно продумывает фичи, и как правило, делает несколько PoC, прежде, чем выпустить фичу. И получается очень хорошо: и с записями, и с value-типами, и проектом Loom, и много с чем ещё. Loom вообще хороший пример, как надо делать фичи. В Котлине корутины сделаны раньше, но далеко не так элегантно, приходится размечать асинхронный код.

Главная проблема проекта Loom — в том, что он нужен был 10 лет назад.

Мне нравится как сейчас развивается Java, но писать по-прежнему приятнее на Kotlin. Потому что Kotlin - это в первую очередь про сахар, а большинство JEP'ов - про низкоуровневый функционал.

В целом я вижу только плюсы - в итоге можно будет писать на Kotlin с использованием всех новых плюшек

а также ужасный JPA

А JPA то вам чем не угодил?

и практика использовать геттеры-сеттеры

Как геттеры и сеттеры мешают программисту?

очень легко мешает.

Если есть сеттеры - обьект мутабельный.

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

При переносе с ДТО в энтити и наоборот вы контролируете количество полей исключительно руками, когда allArgsConstructor требует все (нужные) поля.

JPA требует конструктор без аргументов и не final переменные (hibernate позволяет обойти, но через костыли).

Составные ключи через костыли.

Кастомные типы, массивы и даже егамы не поддерживаются по дефолту, не говоря про незаменимый jsonb.

Есть способы и готовые библиотеки заставить jsonb работать, но абсолютно через задницу, синтаксиса по работе с полями jsonb нет, надо использовать нативыные запросы.

Как происходит получение вложенных списков?

Например пользователь со списком привязанных к нему банк. карт.

Идет join , запрос возвращает количество строк равное количеству карт, orm по хэшу пользователя их группирует. Как только списков становится несколько - оно перестает работать. ORM банально не может знать что к чему группировать, это же просто набор строк. Не говоря, что это затратные операции. При этом вы в sql можете вернуть список карт как массив или jsonb. Избегая n+1 проблемы, кстати.

У вас есть транзакция. Большинство операций читающие. Вы создали энтити. Есть 1 операция, где надо изменить сумму. Как вы это реализуете? JPA подталкивает вас не думать об этом, сделать trx.setSum(trx.getSum()+diff)

Только вот у нас есть параллельные транзакции? Вы повесите select for update на всю энтити? Сделаете несколько энтити на разные операции, чтения/обновления? Очень удобный маппинг выйдет. При это м sql вам даже не надо читать обьект, просто update trx t set sum=t.sum+:diff. Оно вынуждает вас городить кучу ненужного, запутывающего кода на простейшие операции

Lazy поля. Иногда вам не нужен внутренний список, иногда нужен. Вы или делаете lazy, теряя перформанс на лишний запрос, или получаете список там, где могли этого избежать. При этом мы обязаны помнить про лэйзи поля, работа с ними должна быть в той-же транзакции. Что это за абстракция такая, которая течет не начав работать?

Если есть сеттеры - обьект мутабельный.

Ааа, акцент на сеттерах, а геттеры просто были упомянуты за компанию. Я не так понял ))

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

В том числе поэтому мы мапим энтити в ДТО.

JPA требует конструктор без аргументов и не final переменные (hibernate позволяет обойти, но через костыли).

Hibernate позволяет возвращать из запросов ДТО, или можно сразу использовать Spring Projections.

Как только списков становится несколько - оно перестает работать.

Тут надо уточнить, что речь о том, что у пользователя может быть список карт и ещё, допустим, список машин. И тогда у ОРМ будет проблема выбора этого списка одним запросом. Из-за ограничений классического SQL.

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

При этом вы в sql можете вернуть список карт как массив или jsonb.

Если использовать такие штуки, как массивы и jsonb для формирования полей в ответе, то можно добиться примерно того же эффекта, что Hibernate производит с помощью @BatchSize . Времени придётся потратить больше, кода написать больше, но да, возможно даст похожие результаты.

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

Может быть получится выиграть немного производительности или уменьшить количество трафика между БД и приложением. А может и нет, не уверен.

Избегая n+1 проблемы, кстати.

Как и в случае с @BatchSize

У вас есть транзакция. Большинство операций читающие. Вы создали энтити. Есть 1 операция, где надо изменить сумму. Как вы это реализуете?

Update Trx t set t.sum = t.sum + : diff

JPA подталкивает вас не думать об этом, сделать trx.setSum(trx.getSum()+diff)

Можно и так, особенно, если энтити уже всё равно вычитаны.

Только вот у нас есть параллельные транзакции?

В смысле что-то, что одновременно меняет сумму в одной транзакции? Так они же специально создаются, чтобы засунуть туда только одно изменение. Может вы про то, что нужно изменять сумму, доступную на счету?

Вы повесите select for update на всю энтити?

На эту СУБД-транзакцию, да.

При это м sql вам даже не надо читать обьект, просто update trx t set sum=t.sum+:diff.

Прямо как в JPQL, да.

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

Мы всегда делаем lazy и используем join fetch или энтити графы или @BatchSize, когда не хотим делать лишних запросов ))

Что это за абстракция такая, которая течет не начав работать?

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

В смысле что-то, что одновременно меняет сумму в одной транзакции? Так они же специально создаются, чтобы засунуть туда только одно изменение. Может вы про то, что нужно изменять сумму, доступную на счету?

у вас же не serializeble изоляция?

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

Иначе очень легко.

Транзакция 1 - читает из БД. Сумма=1

Транзакция 2 - читает из БД. Сумма=1

Транзакиция 1 увеличивает сумму на 2.

Транзакиция 2 увеличивает сумму на 3.

В итоге имеем 4 вместо 6ти.

А разве при попытке закоммитить вторую транзакцию проблем не будет?

нет, откуда?

нет, откуда?

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

так транзакция прочитала commited (старое) значение. У нее нет проблем. Откуда бд знать что вы хотите сделать.

Для падения необходимо оптимистичные блокировки использовать на уровне ОРМ/руками.

так транзакция прочитала commited (старое) значение. У нее нет проблем. Откуда бд знать что вы хотите сделать.

В комментарии ниже вы сами ответили на это замечание )) . Ну и как я написал выше - изоляция должна быть сильнее чем READ_COMMITTED

Для падения необходимо оптимистичные блокировки использовать на уровне ОРМ/руками.

Да, именно так, Hibernate это умеет ))

Ошибка будет на Repeatable Read и выше. Но обычно это не то, чего мы хотим от приложения.

Ошибка будет на Repeatable Read и выше. Но обычно это не то, чего мы хотим от приложения.

Но вот в рассматриваемом случае похоже именно этого мы и хотим ))

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

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

Чтобы использовать select for update с jpa нужно написать

query.setLockMode(LockModeType.PESSIMISTIC_WRITE)

Не то чтобы это сильно отличается по удобству от вставки for update прямо в запрос

И нет, batch size делает вообще не это, batch size делает ровно то, чего от нее ожидаешь по названию

"@BatchSize specifies a "batch size" for fetching instances of this class by identifier. Not yet loaded instances are loaded batch-size at a time (default 1)."

Я же говорю про inner select и CTE.

Hibernate можно постараться приказать делать inner select, только он будет игнорировать указания в ряде случаев (и не упадет с ошибкой)

*также можно использовать группировку.

В общем вы просто можете получить вложенный список как вложенный список (чудо).

И нет, производительность не немного отличается, а очень-очень сильно отличается. Это легко можно или проверить, или загуглить.

В общем вы просто можете получить вложенный список как вложенный список (чудо).

Можем, да.

И нет, производительность не немного отличается, а очень-очень сильно отличается.

Вот это прямо интересно, может у вас есть ссылки на тесты?

Это легко можно или проверить

Вы проверяли? Какую СУБД использовали? Может быть есть ссылка на гихаб?

И нет, batch size делает вообще не это

Не это? А что вы имеете в виду? Непонятно о чём речь. Непонятно на какой кусок из моего комментария вы возражаете. Я писал, что @BatchSize помогает одновременно порешать проблему декартова произведения и проблему n + 1 . Так оно и есть.

Я же говорю про inner select и CTE

Сложно сказать, что вы имеете в виду. Я сначала думал, что речь о том, чтобы с помощью подзапрос вытащить все элементы коллекции и преобразовать их в jsonb, но дальше вы пишите, что Hibernate умеет делать inner select. Наверное вы имели в виду subselect, но в Hibernate он отвечает за другое. Было бы круто пример какой-нибудь

Hibernate можно постараться приказать делать inner select, только он будет игнорировать указания в ряде случаев (и не упадет с ошибкой)

Можно пример?

Проектов на Kotlin и Spring Data JPA не существует?!?

Существует, но JPA это стандарт Java

Как геттеры и сеттеры мешают программисту?

Раздуванием кода.

  • Во-первых, я обязан использовать lombok (или генерить десятки-сотни однотипных аксессоров в IDE, что еще хуже)

  • Во-вторых, весь код напичкан префиксами get/set. И это не приносит абсолютно никакой пользы, просто увеличивает длину строк

Я считаю, что `getX / setX` - это подход полезный 20 лет назад, когда код писали в блокноте. Так же как и именование переменных с префиксом типа (`iVar, sVar`) и прочие конвенции. Но в современном мире, где у нас есть отличные IDE с подсветкой синтаксиса, автокомплитом, поиском по коду и т.д. это просто не нужно

Никто ж не заставляет так писать (ну, кроме тимлида наверно). Если это так бесит, можно сделать public поля и писать прямо в них. Или использовать records. Не?

А собственно в чем вопрос?
Беглый гуглеж показал что в Kotlin нет своего ORM подобного JPA (возможно я плохо искал). Но есть аналог Jooq.
Если вам не нравится один инструмент есть другой.
Зачем страдать? Пользуйтесь чем умеете и не страдайте.

Каждый инструмент имеет проблемы и недостатки, поэтому их и много. Важно уметь работать с разными и понимать какой инструмент нужен в определенной ситуации.

После прочтения тонны макулатуры, почти каждый сможет обсуждать язык на уровне разработчика с опытом в 3–5–7–9 лет.

Но писать код они по-прежнему будут на уровне джуна с нулевым опытом.

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

Подтверждаю. Как раз изучаю java и действительно, одно дело знать что-то и совсем другое написать код, используя эти знания. Плюс, всегда вылезает куча каких-то моментов, которые вскрываются при написании кода)

на примерах с книгами и студентами все красиво и хорошо, а в реальных бизнес кейсах все почему-то не так стройно))

Как раз и важно знания теоретические. ChatLGBT / Cock-pilot купил за условные 20 евро. Ты ему даёшь нормальное ТЗ, он тебе ответ. Ты его проверяешь и дальше уточняешь у нейросети.

А по питону есть такие родмапы?

Я думал тут будут БД, кубы, облака... Что за разработчик с 4 годами опыта который только джаву знает? Свой инструмент конечно надо знать на отлично, но важно знать не только его. Хотите переплюнуть профессиональных разработчиков прочитав пару книг и не решив ни одной задачи бизнеса? А ещё наверное на синьера собеситься можно после этих книг?)

Я запутался, какой это слой постиронии?

Крайне спорный подход - изучать крайне тонкие нюансы программирования на Java (чтобы "казаться" разработчиком с 5-7-летним опытом) и при этом полностью игнорировать Spring, работу с БД, фреймворки для написания тестов и вообще принципы написания тестов.

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

имхо главное в хорошем разработчике вместо "не сталкивался" начинать гуглить. Столкнулся ведь, только что :)

Профессионал пишет коммерческий код за деньги. Чтение книг без практики никак не поможет его переплюнуть. И тем более никак не поможет заработать на разработке денег. Теории не приносят денег. Так же профессионал, это специалист любого уровня, даже самого низкого, получающий за свой труд деньги. Подбор книг к роадмапу по джава тоже имеет мало отношения. Статья из раздела "юмор"?

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

А ссылки на индийский Амазон - это какой-то особо изысканный юмор?

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