Григорий Мясоедов @grisha9
Java Developer, Open Source Contributor
Information
- Rating
- 548-th
- Location
- Рязань, Рязанская обл., Россия
- Date of birth
- Registered
- Activity
Specialization
Specialist
Lead
Java
SQL
Database
Android development
Java Developer, Open Source Contributor
Во первых не у меня, а достаточно посмотреть трезвым взглядом вокруг что происходит. И автор в статье рассуждает о реальных проблемах образования и к чему это ведет и в чем видит пути выхода из сложившейся ситуации. А не рассуждает абстрактно как вы - за все хорошее против всего плохого, уцепившись за одну фразу про "человеческий материал" и отбросив весь остальной смысл статьи. Хотя повтороюсь эта фраза, как писал выше, в том контексте, никого не оскорбляет, а называет вещи своими именами.
Давайте для начала добавлю контекста:
Автор говорит, о разрушении образования в РФ, что его превращают в тест(ЕГЭ), в ущерб "инновационной" деятельности мозга, что из за этого люди становятся менее способными к созданию нового. Далее идет приведенный вами фрагмент.
Из которого по моему мнению также, логично следует, что отвечать этому вмешательству в образование извне, проще с более образованными людьми. Но из за разрушения образования, его общий уровень у людей упал. О чем и говорит автор.
Или вас смущает только фраза о человеческом материале? Или вы будете спорить с тем что люди по своим способностям не равны? Т.е. по вашему любой кто захочет как то воспитать людей, автоматически будет записан в "ругаемый запад"? Т.к. в процессе воспитания так или иначе приходится иметь дело с человеческим материалом, т.е. исходными данными. Не вижу тут никаких оскорблений и противоречий.
Давайте теперь представим ситуацию о которой говорите вы:
Допустим на какой то территории N, люди решили жить по принципу за все хорошее, против всего плохого, каждый занимается тем что ему по душе, без всякой указки извне. По моему совершенно очевидно и вся тысячелетняя история человечества это доказывает, что найдется другая группа людей M, которые объединены конкретной идеологией (не важно со знаком + или -) и как следствие добились большего прогресса в "инновационной деятельности", и поэтому им не составит труда поглотить группу N и навязать им свой образ мыслей и заставить делать то что нужно доминирующей группе.
Для тех кто выбрал такой путь развития "что "материалу" возможно уже поперек горла стоит эта инновационная деятельность" история придумала и доказала на практике ряд афоризмов: "Если ты выглядишь как еда, то тебя обязательно съедят" и "Удел тех, у кого нет идеологии — пикник на обочине Истории"
Совершенно случайно, никак не связано с данной публикацией, читал на днях статью Ильинского И.М. (на данный момент президент МГУ) "Образование в целях оглупления". Оставлю на всякий случай ссылку тут, может кому то еще будет интеренсо - читать
Сильное утверждение... что без нее никак. Это лишь деталь вашей реализации роутинга. В обмен на простую реализацию, вы получаете лишний запрос. Но можно сделать свою имплеменатцию на основе ThreadLocal, да так будет больше кода, но перфоманс будет выше. Быстрый поиск показал что люди в целом там и делают (там правда не совсем про это). Да и обычный Spring Transaction также реализован через ThreadLocal, подробнее тут.
Как следует из названия плагина - "Explyt Spring" он добавляет поддержку Spring. В статье про это подробно описано. Разве в community есть поддержка данного фрейморка? можете дать ссылку на плагин который за это отвечает?
Давайте еще раз уточним нашу позицию:
Цели и приоритеты
Как я упоминал выше, у нас изначально не стояла задача поддерживать именно *.http формат из IDEA. Мы пришли к идее сделать собственный клиент уже после того, как получили OpenAPI-файлы.
Экономия времени и упор на готовые инструменты
Использование Swagger UI сразу дало нам готовый пользовательский интерфейс, к которому многие уже привыкли. Это экономит массу времени и усилий как в разработке, так и в дальнейшей поддержке — нет необходимости поддерживать собственный DSL или веб-клиент.
Почему не *.http
Чтобы интегрировать *.http-синтаксис, нам потребовалась бы официальная открытая грамматика (BNF) от его авторов. Мы такой не нашли. Конечно, можно было бы написать её самим, но вопрос в том, насколько это оправдано с точки зрения конечного результата: мы получили бы функциональность, очень похожую на уже имеющиеся решения, при этом затратив немало ресурсов на поддержку.
Выбор в пользу простоты
Мы выбрали более простой путь, ориентируясь на проверенные инструменты и формат (OpenAPI + Swagger UI). Это позволило нам быстрее достичь цели и при этом не «изобретать» ещё один стандарт для написания HTTP-запросов.
Надеюсь, так яснее, почему мы приняли именно такое решение.
Отчасти я могу с вами согласиться, но это все таки немного разные истории. Мы прежде всего Spring плагин и изначально наш клиент “родился” из задачи генерации OpenApi файлов по Spring Controllers. Это в целом достаточно распространенная задача и есть множество её реализаций, а далее прикрутить к этому делу Swagger UI не составило никаких проблем и мы за очень дешево получили полнофункциональный веб клиент с готовым UI, приложив минимум усилий.
А реализовывать полноценную поддержку idea http языка - его парсинг, выполнение, UI для работы с результатами запрсов… это задача совсем другого калибра.
В списке отображаются все языки зарегистрированные в IDEA. Фильтровать по названию, может быть не совсем корретно, т.к. нет никаких гарантий что в имени языка будет подстрока SQL и мы так уберем лишнее. Также например, пользователь сможет там выбрать JPQL-EXPLYT для подсветки нативного SQL синтаксиса, да это м.б. не совсем валидно т.к. JQPL != SQL, но лучше чем ничего, если не установлено никаких других плагинов с поддержкой SQL. Так мы получаем базовые комплиты и подсветку, хотя синтаксис может распознаться не совсем верно.
Причем тут дистрибутив IDEA? Explyt это не форк IDEA CE. Explyt - это набор плагинов для IDEA: Spring, Test и форк DBN.
И то что скачивается дистрибутив CE, вовсе не значат что плагины скачиваются также легко без VPN из маркетплейса JB
Вот и все закрыли запрос) С комментарием что этим должна заниматься spring-core команда. Но не уточнили будет ли...
Поддерживаю. Подход выбранный Java намного более прагматичный. А ключевые слова типа async/await и suspend это также допольнитая "раскраска(colored)" кода. О всем этохо хорошо расказал Иван Углянский в своем докладе. И сделал сравнение по имплеменатции "легковесных" потоков во многих языках https://www.youtube.com/watch?v=kwS3OeoVCno
Завел issue - https://github.com/spring-projects/spring-boot/issues/43208
Поставили статус - "for: team-meeting" Видимо ничего готового для этих целей нет.
Я не нашел. Хотя пытался, когда реализовывал данный функционал. Может быть плохо искал...
Возможно стоит завести им issue на этот счет.
У них есть плагины для билд систем https://docs.spring.io/spring-boot/build-tool-plugin/index.html
Как мне видится это должно быть реализованно именно там. Т.к. приложение надо изначально собрать. А далее выполнить определнный таск, который распечатает мета-информацию о текущем контексте приложения. Например как это сделано в мавен для анализа зависимостей:
maven dependency:tree
И так можно реализовать IDE независмое решение для поддержки спринг в любой среде разработки. В целом это можно сделать и сейчас, используя ихние готовы плагины Maven/Gradle для сборки и запуска, добавать нашу библиотеку в classpath и поменять точку запуска, но это как вы правильно заметили, требует больших телодвижений.
промахнулся с ответом, написал в общий тред) продублирую тут ссылкой: https://habr.com/ru/companies/explyt/articles/854304/comments/#comment_27542688
Спасибо, вы сделали правильный вывод!
Если разработчики Spring добавили бы один метод, который срабатывал после завершения построения bean definitions, в интерфейс SpringApplicationRunListener о котором я упомянул в статье, то было бы сильно проще.
И тут кстати можно продолжать аналогии с билд системами, в том же Maven есть AbstractEventSpy, где в onEvent в нетипизированном виде приходят все необходимые события о этапах сборки. Который я и использовал в своем плагине GMaven, чтобы получить данные о проектной модели. А Spring (Spring Boot в частности) можно назвать по сути такой же "билд-системой". Только которая работает на уровень выше и отвечает за "сборку" приложения в момент старта. У нее также есть конфигурационные файлы, которые необходимо прочитать перед запуском, и на основании всех конфигов построить конечное приложение. И действительно, было бы не плохо, иметь там больше точек интеграции с внешним миром и это практически напрашивается... У них уже есть определнные тулзы для разработчиков, но они для этой задачи мне не подошли, я их изначально рассматривал.
И поэтому еще кстати, эта идея так легко легла на External System API ИДЕИ, которое было задумано как общее флоу для билд систем, на ней основываются такие плагины как Gradle, SBT - Scala, мой альтернативный мавен плагин GMaven. Что уже в процессе разработки я понял, что эти аналогии не лишены оснований. Если изначально, я использовал External System API с целью быстрее выкатить прототип, то по итогу я даже сам удивился, как легко и непринужденно эта идея легла на текущее API ИДЕИ для билд систем, что весь процесс разработки занял буквально несколько дней и у меня не возникло в процессе никаких затыков. Это был как раз тот случай, когда несколько недель изучаешь и думаешь как сделать, и потом за пару дней кодинга, получаешь готовое решение.
Вопрос не ко мне, но попробую оветить за автора) На этот счет уже были хорошие публикации. Раз и два.
Вы не правы. В Spring 5 маханизм проксирования не менялся, также как и в Spring 6.
Изменения есть в Spring Boot начиная с версии 2. И это поведение меняется одной настройкой в application.properties. Об этом же и говорит Борисов в своем выступлении, начиная с 36 минуты.
А зачем? Чтобы вместо БД, ходить в редис и получать по сути туже сетевую операцию, с передачей данных по сети? получается то же на то же. Я как то занимался этим и пришел к выводу, что это не имеет смысла. т.к. кешируются в основном неизменяемые справочные сущности. И сделать запрос что в бд по id, что в редис сути не меняет. Основное время займет передача данных по сети. Я даже делал замеры и результаты были одинаковые. Основная суть кеша чтобы убрать обращение к внешней системе по сети и хранить данные в памяти. А не в том чтобы заменить одну внешнюю систему на другую, концептуально ничего не улучшив и сделаться заложником доступности еще одного внешнего хранилища. К томуже современные СУДБ также имеют настраиваемый memory cache где хранят часто запрашиваемые сущности.
Возможно это будет открытием, но именно так и происходит. Если выполнить какую нибудь операцию к БД, и выше по стеку нигде не будет открытой транзакции, то будет выполнен запрос к бд с параметром autocommit=true(true дефолтное значение). Это как бы база… (Более подробно я рассказывал про autocommit в своей статье про транзакции). Так будет на чистом JDBC и springJdbcTemplate. Другие технологии где куча специфики и неявной логики вроде JPA я в расчет не беру, разговор не про них. И если вы явно не указали транзакцию, то БД так или иначе сама ее откроет в режиме autocommit - по другому никак.
Это опять не соответствует действительности. Откуда такая информация? Выше я уже ответил также и на это. По вашей логике нельзя выполнить никакой запрос к бд, не поставив аннотацию Transactional? Но это не так) Далее я докажу вам это.
Транзакции я считал на стороне БД. Давайте рассмотрим еще раз на примере. Создал методы как писал выше. Полный код.Также добавил метод currentTxId который возвращает текущий номер транзакции на стороне БД (Более подробно про это тут.)
Первый тест с последовательным выполнением, результат:
Откуда видно что была ровно одна транзакция на стороне БД. Небольшое уточнение - каждый вызов currentTxId также делает инкремент транзакции на стороне бд. Поэтому надо учитывать его вызов. Показал это на тесте - testTxIdIncrement. Каждый вызов insert видит что в threadLocal есть инфо о открытой транзакции, и он просто переиспользует ее и не создает новую.
Второй тест с параллельным выполнением, результат:
Видно что было 10 транзакций. Для метода update10TxParallel транзакция не создалась на стороне БД т.к. он по факту в ней ничего не модифицировал и постгресс такие транзакции считает условно “readonly” и счетчик для них не модифицирует. Тут каждый вызов insert ничего не находит в threadLocal и выполняет транзакцию с новым коннектом и параметром autocommit=true, что создает новую транзакцию в бд.
*Я заменил update на insert чтобы не заполнять бд значениями. Т.к. если выполнить апдейт для несуществующей строки, то транзакция также не будет учтена т.к. ничего не поменяла. Мне было лень заполнять бд значениями. Но вы можете это протестировать сами на моем примере.
Да, до моей формулировки можно докопаться, но и вы не правы. Если сделать уточнение - что метод
update
вызывается не из форк джоин пула, то количество транзакций всегда будет 101, независимо от того сколько в нем потоков. Каждый вызовupdateDb
будет выполнен в новой транзакции. И даже если на одном потоке будет выполенено скажем 10 вызововupdateDb
то по итогу будет 10 транзакций в БД. Т.к. каждый запрос сам откроет и закроет ее по завершению на стороне БД.