Pull to refresh
2
0
Александр Плохой @alexdoublesmile

Java Software Engineer

Send message

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

Ленивая загрузка:

если код писали настолько неквалифицированные люди, что у них сотни запросов вместо одного, то страшно представить, какой код бы у них был без JPA и кол-во проблем, созданных ими на JDBC Вы уже таким простым алгоритмом бы не исправили...

Дополнительнительные запросы:

если критически важно производительно обновлять сущности, то можно написать @Query, в 90% случаев это не нужно, т.к. вряд ли апдейты будут узким местом в адекватно написанном сервисе. Да и в целом получение по первичному ключу строки из БД - это дешевая операция, если таблицы написаны корректно и не имеют миллион столбцов.

Кэширование:

зачем кэшировать entity, если надо кэшировать данные? Например, сделать маппинг на record и можно кэшировать.

Учитесь пользоваться инструментом и сюрпризов не будет. А дизайн и ДДД, ну что ж в большинстве проектов - это вообще не аргумент, чтобы отказаться от в разыболее быстрой работы с сервисом (а читать бесконечные sql на крупном проекте это тот еще ад)

Статью с названием "Как я не стал программистом в 35 лет" можно описать одним предложением: "Вместо того, чтобы программировать, писал на хабре статьи о безуспешных попытках оправдать банальную лень и безответственность недостатком "материальной базы" или отсутствием "обеспеченных родителей" и "удачного набора обстоятельств".

Если речь именно об умении программировать (ведь так называется статья), то Автор к своим 35 годам так и не понял, что у любого стремления в чем-то развиваться два пути:

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

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

Если же речь лишь о том, чтобы устроиться работать программистом (что вообще не одно и тоже, если это не очевидно автору), то сейчас (как впрочем и всегда, ведь статья 2019 года), чтобы найти работу, достаточно только искать работу. Это единственный критерий.
А вот на каких условиях будет эта работа зависит

  • на 5-20% от твоих навыков в сфере (если это работа дева, то языки, фреймворки, тулы, умение их юзания и т.п.),

  • на 20-40% от твоего "де-юро" опыта работы в сфере (по факту это имена компаний, в которых до этого работал),

  • на 40-50% от твоего опыта устраиваться на работу в целом (сколько раз ты в жизни устраивался на разного рода работы, ходил по собесам, общался с людьми и т.п.),

  • на 20-30% от времени поиска

  • на 5-10% от удачи и совпадений. Вообще это касается любой профессии плюс-минус (ремарка для студентов и для тех, кто меньше 5 раз в жизни вообще менял работу..).

Крутая статья! Пара небольших замечаний относительно Concurrent Evacuation фазы, т.к. барьер, помогающий при эвакуации(Load Reference Barrier), вроде как работает немного иначе:

  1. Он срабатывает при каждой попытке загрузить ссылку, независимо для чтения или для записи в объект.

  2. Даже если поток хочет только читать данные объекта, если forwarding pointer установлен, но объект еще не эвакуирован, будет осуществлена попытка атомарно установить копию самим барьером

  3. Если барьер успешно устанавливает копию в forwarding pointer, текущая ссылка на объект после этого также будет обновлена, не дожидаясь фазы Update Reference, причем тоже атомарно

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

По факту у нас нет "сборки мусора" в привычном понимании, а скорее лишь "сборка и перемещение достижимых объектов"

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

Не думал, что среди программистов есть настолько талантливые комики. Автор, ты мой кумир. Пошел изучать С++

Страшно представить, какая боль это дебажить, добавлять фичи и искать баги, особенно после того, как на подобном начнет работать какой-нибудь реальный проект (с адекватной БД и синхронизацией транзакций между всей этой событийной мешаниной)

P.S. статья, кстати, классная, интересно расписано

Статья ни о чем, да еще и на сомнительных аргументах. Все проще: каждому интсрументу свое применение, Java - писать программы, Python - поиграться или заниматься околопрограммистскими движухами (прототипирование, рисеч, мониторинг и т.п.)

Единственный надежный способ сохранить информацию - глинянные таблички. Проверено тысячелетиями. Ваши книги с 99,999% вероятностью не переживут и десяти поколений, а при "сценарии апокалипсиса" все "тепличные" представители нашего вида, типа тех, кто читает эту статью, неизбежно вымрут быстрее, чем эти книги превратятся в прах, человечество будет состоять из тех, кто живет сейчас в лесах, охотится, не пользуется электричеством и т.п.. И для них любые научные книги из бесполезной бумаги получат исчезающе малую возможность стать чем-то большим в лучшем случае через несколько сотен, а возможно и сотен тысяч поколений (зависит от уровня апокалипсиса).

Молодец! С их дилетантским подходом к обучению не растерять энтузиазм - это похвально. Напиши мне в телегу, я дам теоретический и практический материал по любой теме, связанной с Java (alexdoublesmile). И помогу с разбором

от такого clean code у любого Java разработчика глаза прослезятся

Вам стоит почитать, что такое Spring Boot вообще, ибо понимание нулевое.

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

Спасибо за статью. Пара имхо замечаний:

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

  2. а описывать все скрипты по созданию схемы лучше сразу в виде миграции (Liquibase, Flyway, etc.)

  3. mappedBy свойство не имеет отношения к генерации схемы, оно указывает как работать с сущностями при ORM-маппинге. Если указано над entity, то его поле с указанным именем используется для связи с текущей entity при маппинге. А уже встроенный механизм hbm2ddl при его активации парсит эти свойства и применяет при генерации

  4. аналогично для @JoinColumn - ее свойство value лишь указывает на имя колонки в БД, на которую осуществляется маппинг текущего поля при работе с entity. Default namnig strategy также можно менять, но имя лучше явно указывать для наглядноси.

  5. двусторонняя связь на уровне БД не может быть нужна. Как правило связь указывается в зависимой сущности.

  6. непонятно, с какой целью в примере используется @Transactional - она не имеет реализованного функционала в чистом Hibernate, но даже при использовании, например, Spring реализаций, она ни к чему над этим методом.

  7. в качестве naturalId лучше использовать не синтетические поля, а любое поле сущности имеющее констрейнт unique (типа username etc.). Синтетические поля вообще дурная практика - они просто засоряют логику и понимание кода.

  8. деталь: над интерфейсом, наследующим JpaRepository нет смысла ставить @Repository

  9. деталь: чтобы IDEA понимала твои маппинги, стоит добавить связь с твоей БД (для sql это тоже делается - Alt+Enter -> Inject language)

  10. непонятно также, с какой целью автор описывал громоздкий именованный граф над сущностью и доставал сущности через find, если у него при этом очевидно используется Spring Data JPA на скрине выше, где к тому же очевидно используется свойство attrıbutePath, которое не работает с именованными графами. Т.е. как говорится, Вы либо крестик снимите, либо трусы наденьте.

  11. BatchSize использовать можно не только над коллекциями. Можно поставить над типом entity(тогда все запросы сущностей с которыми связаны помеченные сущности в единичном экземпляре будут подтягиваться батчем)

  12. использовать H2 - не лучшая практика, т.к. при тестировании луше использовать более схожую с боевой среду. Лучше использовать test containers

Не могу понять одного, чем этот метод лучше простого наследования repository от QuerydslPredicateExecutor (вместо наследования JpaSpecificationExecutor)? Ведь в его методы можно передавать адекватные предикаты, которые хотя бы читаемы в отличие от этого хаоса Specification и выглядят как нормальный код (без кучи дженериков, магических названий, констант, приведений типов и пр., не говоря уже про сомнительные правила для клиента, по типу передачи названия полей таблиц в виде строк...? серьезно?). Это, видимо, для м̶̶а̶з̶о̶х̶и̶с̶т̶о̶в̶ фанатов Criteria API способ создания фильтров или тут есть еще какой-то смысл помимо незнания querydsl?

Спасибо за статью, только не совсем понятна пара моментов:

  1. При использовании аннотации TestContainers будет создаваться новый docker-container с базой для каждого тестового класса, зачем нам это? Не разумнее ли запустить одну базу для всех тестов (например из общего тестового класса осуществить BeforeAll container.start())?

  2. Почему не наполнять тестовую БД данными из какого-нибудь sql-скрипта, а не осуществлять BeforeEach repo.save()? Ведь это во-первых, лишнее взаимодействие с логикой, которое никак не проверяется, я уже молчу что в каждом классе прописать надо не забыть этот сетап..

  3. Зачем вообще осуществлять repo.deleteAll, если по умолчанию в Spring Test все транзакции и так откатываются?

  4. Зачем регистрировать username и password, если в тестовой БД будут и так значения по умолчанию "test", которые просто можно прописать в пропертях?

  5. Для тестирования API не удобнее ли пользоваться гораздо более подходящим mockMvc механизмом?

Прикольные задачки) Только они скорее арифметические, математика по большей части не имеет ничего общего с числами

Спасибо за статью!

Что дальше и можно ли что-то улучшить..:

...

  1. "Немножко" над clean code поработать, чтобы этим кодом можно было пользоваться больше одного раза.

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

Только не стоит забывать, что O'Reilly, "используя весь свой огромный опыт издания учебников и проведя исследования с привлечением психологов и теоретиков педагогики.. " не заитересованы кого-то чему-то научить. Их единственная цель - заработок, а такие книги продаются лучше не потому что они могут что-то вам дать, а потому что они банально не напрягают мозг читателя, ведь у него лапки (только по совместительству отсутствие напряжения также нивелирует развитие).

А насчет бесполезности книги: в статье изложено лишь мнение автора, кто-то может быть с ним не согласен. Я вот согласен на все сто - как по мне эта книга полезна может быть разве что тому, кто хочет просто по фану полистать какую-нибудь ерунду на тему программирования (сам так люблю делать вечерком)), но точно не как серьезное учебное пособие или справочник по Java для начинающих. Имхо, начинать стоит с практики, а не с веселых картиночек

Information

Rating
Does not participate
Location
Симферополь, Республика Крым, Россия
Date of birth
Registered
Activity