Спасибо. Помимо времени запуска интересно еще было бы посмотреть время компиляции, а также возможность и время "горячей перезагрузки".
Micronaut на самом деле удивил по времени загрузки в 4сек. На сайте уверяют, что оно должно быть вообще моментальным, ибо вся сборка делается на этапе компиляции, а не в рантайме. Возможно это из-за Котлина.
микрофреймворк
Отсутствуют “из коробки” некоторые необходимые для промышленной разработки компоненты, например, внедрение зависимостей и реализация Service Discovery.
Ну, во-первых, в Helidon Microprofile все-же реализован CDI. А во-вторых, по большей части это скорей плюс, а не минус. Делает только то, что должен делать, не завязывает на конкретную технологию и дает полную свободу выбора.
Создать сеттер и с помощью его вызова устанавливать продавцу магазин:
Это заведомо плохое решение, т.к. сразу позволяет создавать "ненастроенные" объекты как продавец без магазина. Сеттеры еще можно использовать для опциональных полей, но для обязательных — т.е. тех, при которых объект не будет работать — лучше использовать конструктор и final-поля. Именно он, собственно, и задают dependencies.
И, наконец, мы подобрались к спрингу: он предоставляет еще один способ внедрять зависимости.
А это самый быстрый и самый плохой способ. Все ваши объекты становятся въявную завязанными на контейнер и без него уже не способны работать. Ни протестировать нормально ни переиспользовать потом.
Возможно вы сейчас думаете, зачем все эти сложности. Но представьте, что у нас приложение не из 2 классов, а на несколько порядков больше и управление зависимостями уже становится не самой тривиальной задачей.
Уж поверьте, еще более нетривиальной задачей это становится со спрингом. Особенно когда в проекте несколько разрабов. Когда все внеявную завязано на текущих настройках и умолчаниях, любое изменение либо не тупо работает, либо что-то рушит. Поэтому типичный проект на спринге связывает не более десятка бинов, и используют его совсем не из-за DI, а из-за легкого бутстрапа различных технологий из коробки.
В общем случае никакой синхронности/асинхронности не существует. Эти термины возникают, когда появляется понятие "поток выполнения" и связанные с ним термины: контекст выполнения, состояние, стек, etc… Возьмите любой нормальный функциональный язык программирования, и внезапно куда-то исчезнет вся "последовательность выполнения".
Есть два способа реализации асинхронного выполнения:
Тикет: когда при старте асинхронной задачи основному процессу возвращается тикет-объект, при помощи которого он сможет запрашивать состояние выполнения задачи.
Колбек: при старте асинхронной задачи основной процесс указывает какой код вызвать при ее завершении.
Очень сильно экономит время разработки. Он вызывается прямо во время компиляции, когда классы уже распарсены, но реально еще не сгенерированы. Решает проблемы:
не нужен вызов сторонней тулзы после каждого изменения класса
решена проблема с поиском аннотированных классов — компилятор уже знает их все
нет необходимости грузить классы из classpath, чтобы интроспектировать их с помощью reflection
скорость работы на порядки выше
Недостатки:
вместо reflection используется компиляторный mirror api
Есть куча примеров как написать простой annotation processor.
Меня беспокоит затронет ли это уже существующие компоненты JavaEE? Например у Eclipse Foundation была и есть годная имплементация JPA/JAXB под названием EclipseLink/MOXy...
Если вы действительно программируете, а я видел среди списка задач только типа "отправить книгу Коле", то должны знать, что программирование любой фичи требует максимальной концентрации на решаемой задаче. Требуется постоянно держать в памяти структуру проекта, модель функционирования, идеи и план реализации, возможные методы тестировния — и все это параллельно с устранением проблем и поском новой информации. И при том, что ресурсы межушного нервного узла сильно ограничены. И вот хуже нет, когда данный процесс прерывают искусственно и бросают на другую задачу. Переключение контекста и для железа стоит дорого — а для головы это вообще непосильный труд, приводящий к нервным расстройствам. И если вы можете параллельно и качественно концентрироваться на разных задачах, то вы сцуко Юлий Цезарь, и место вам в музее.
Заключения не будет
Хаоса будет больше. Привыкайте и не стремитесь все упорядочить.
Шума тоже будет больше. Научитесь его игнорировать.
Экономьте силы. Концентрируйтесь только на реально необходимых задачах. Все остальное либо подождет, либо пройдет само.
Не пытайтесь адаптироваться под условия. Адаптируйте условия под себя.
Там проблема в другом. Сильный нейтронный поток радикально изменяет свойства материалов вплоть до механической деформации. Поэтому конструкция реактора должна быть хоть как-то ремонтопригодной и частично обновляемой. Вот вроде бы упомянутая статья: https://habr.com/ru/post/365991/
Ха! Вот только за последние три месяца (специфично для Java):
Пустой catch. Вредитель, писавший бизнес-логику верхнего уровня, замолчал исключение и поставил try с пустым catch. В итоге мы думали, что сбой ниже — в протоколе передачи: данные-то на экране показывались совсем левые, а исключение "типа" не выбрасывалось.
Невозможное поведение на сертификационном вокрбенче. Тестовая группа клиента отправляет нам багрепорты, которые уже давно были пофикшены и на тестах не возникали. Две недели компостировали нам мозги: делаем в коде различные "подпорки" для гипотетических (и невозможных) случаев, добавляем больше логов. В итоге требую доступ к сертификационной машине и вижу — о чудо — определена переменная CLASSPATH и в нее добавлены старые .jar-ы из другой директории...
Пустой-не пустой список. Функция фильтровала значения в списке, но на выход выдавала всегда пустой. Причем на все 100% верная и локально все тесты проходит. А на сервере не выдает. После разделывания кода оказался баг в библиотеке ORM, который выдавал "бажной" IndirectList: https://bugs.eclipse.org/bugs/show_bug.cgi?id=433075
В задеплоенном приложении тупо не работали периодические процессы, а ошибки в логах не было. В результате головной боли обнаружилось, что клиент использовал кривой sftp, который почему-то обрезал концовку файла. А возникавший NoClassDefFoundError не перехватывался catch(Exception e) и поэтому в лог не выводился.
Продолжая квантовую тему, предлагаю ввести Эверетт-баг: когда код выполняется в какой-то "параллельной Вселенной" и его результаты абсолютно не соотносятся с исходниками. Обычно происходят по причине неправильного билда, либо ввиду внутренних багов используемых библиотек.
Всё началось с RFHUtil. Мощный, но неудобный и страшный: Ну вы знаете Руса.
Есть такая приблуда как WMQTools. Написан давно каким-то хакером на Java. На порядки более удобоваримое, нежели RFHUtil. А последний, как впрочем и все от IBM — сделано не для людей.
P.S. Как сказал чел на первой картинке: "MQ вы… ет и высушит".
Второе — для запуска приложения, написанного на фреймворке с AOT компиляцией, нужен специальный инструмент. Нельзя просто так взять и запустить приложение, написанное на Quarkus, например. Нужен специальный плагин для maven/gradle, который предварительно обработает ваш код.
Следует отметить, что есть два типа кодогенерации — compile time и execution time. Первый практически всегда использует стандартный механизм Java — annotation processing. Второй метод использует bytecode instrumentation при загрузке классов и библиотеки типа cglib, bytebuddy, etc. Именно второй метод обычно используется всеми фреймворками для ускорения работы.
Мне кажется, что без этого механизма Java не стала бы той Java, которая сейчас занимает большую долю рынка разработки прикладного программного обеспечения.
Reflection — это грязный хак, который изначально встроили только потому, что могли. Он сильно мешает оптимизациям в самой JVM, AOT, обфускации, а в коде используется в основном для интроспекции деклараций и проксирования. Без него везде использовалась бы кодогенерация и экосистема Java была бы более разумной и чистой.
Все доказательства у вас полезут в продакше, когда размер таблиц заметно подрастет.
Вот например баг по поводу дедлока: https://groups.google.com/forum/#!searchin/h2-database/deadlock%7Csort:date/h2-database/wPR5gztLU34/EHMoEEpqBgAJ
Из стектрейса видно, что на больших resultset движок создает на диске временную таблицу, в которую сваливает результаты, а после закрытия resultset ее дропает.
Если интересно, поиграйтесь с солидными (50k+) табличками, джоинами и аналитическими запросами. Много всего интересного повылазит, например неоптимальное использование индексов планировщиком, которое никак не поменять.
Все-равно необходимы доверительные отношения, иначе ваша модель безопасности быстро парализует всю работу. Хорошая политика безопасности — та, которая не заметна. А против направленного вредительства пароли не сильно спасают.
Все-таки H2 больше для тестовых нужд, нужно понимать, что это все-таки не полноценный движок. Он хорош тем, что семантически поддерживает SQLи разных диалектов и может корректно их выполнять.
Мы пробовали использовать H2 1.4.196 в проде в embedded-режиме, и хоть задача и была достаточно простой, но даже на ней стали вылезать проблемы.
сразу же нактнулись на deadlock при выполнении: разобрались, засабмитили баг и вроде бы как в следующей версии пофиксили
Thead.interrupt() внезапно прибивал сразу весь datasource, если тред в этот момент выполнял запрос
странно интегрирован full-text search: старая версия Lucene, один индекс на все таблицы, который полностью перстраивается после каждого alter/create/drop
движок SQL более чем примитивный. По сути он в состоянии выполнять только запросы по одной таблице, либо если все лежит в памяти. Если же ваш запрос содержит JOIN или тупо не умещается в памяти (MAX_MEMORY_ROWS), H2 каждый раз создает временную таблицу с промежуточными результатами (а иногда и не одну), с полным набором данных, даже если тебе нужна только одна запись. А при отсутствии индексов этот же запрос может выполняться часами.
учитывая вышесказанное limit/offset никак не влияют на выполнение запроса и служат тупо для обрезания финального resultset
несмотря на заявленный MVCC, при выполнении "тяжелого" запроса (того, что требует временную таблицу) таблицы жестко блокируются
Мы мигрировали на Postgres за пару часов и с тех пор все тепло и сухо. А вот в тестбенчах и юнитах до сих пор используем H2.
а потому что в офисе может быть обиженный Саша, который собирается уволиться и нагадить или забрать информацию напоследок. Почему бы это не сделать в очередной обед?
Обиженный машинист может пустить поезд под откос, обиженный врач — навредить пациенту, обиженный повар — отравить гостей, обиженный полицейский — застрелить прохожего, обиженный оператор атомной станции — спровоцировать катастрофу. И ведь как-то это все работает без всяких паролей...
Это фейк. Пушки до 19 века никак не могли стрелять ядрами.
качество металла при данном калибре разорвет пушку вклочья при первом же выстреле
либо необратимо деформирует орудие через несколько выстрелов
такое понятие как калибр отсутствовал — каждое орудие имело свой уникальный, к тому же сужающийся к основанию
то же самое с демонстрируемыми ядрами — они тупо все разной величины и о подгонке по калибру и речи быть не может
эффективная длина стрельбы навесом всего 200 метров, и то если повезет
большинство старых пушек изысканно декорировано, что непрактично и дорого
Поэтому наши продвинутые предки до катастрофы 18 века из т.н. "пушек" стреляли чем-то другим, например миниатюрными черными дырами, которые добывали в развалинах, оставленных от цивилизации атлантов, уничтоженной из космоса ядерным оружием в неравной битве с рептилоидами. А теперь они пытаются скрыть правду, выставляя эти загадочные древние орудия как примитивные средства ведения борьбы.
Сколько всего миров? Мы не знаем, может быть как конечное количество, так и бесконечное.
Вопрос в том, счетно оно или несчетно. Нераспавшийся свободный нейтрон в каждый момент времени генерирует новую ветвь, в которой он распался. Как производить интегрирование по всм этим вселенным?
Спасибо. Помимо времени запуска интересно еще было бы посмотреть время компиляции, а также возможность и время "горячей перезагрузки".
Micronaut на самом деле удивил по времени загрузки в 4сек. На сайте уверяют, что оно должно быть вообще моментальным, ибо вся сборка делается на этапе компиляции, а не в рантайме. Возможно это из-за Котлина.
Ну, во-первых, в Helidon Microprofile все-же реализован CDI. А во-вторых, по большей части это скорей плюс, а не минус. Делает только то, что должен делать, не завязывает на конкретную технологию и дает полную свободу выбора.
Это заведомо плохое решение, т.к. сразу позволяет создавать "ненастроенные" объекты как продавец без магазина. Сеттеры еще можно использовать для опциональных полей, но для обязательных — т.е. тех, при которых объект не будет работать — лучше использовать конструктор и final-поля. Именно он, собственно, и задают dependencies.
А это самый быстрый и самый плохой способ. Все ваши объекты становятся въявную завязанными на контейнер и без него уже не способны работать. Ни протестировать нормально ни переиспользовать потом.
Уж поверьте, еще более нетривиальной задачей это становится со спрингом. Особенно когда в проекте несколько разрабов. Когда все внеявную завязано на текущих настройках и умолчаниях, любое изменение либо не тупо работает, либо что-то рушит. Поэтому типичный проект на спринге связывает не более десятка бинов, и используют его совсем не из-за DI, а из-за легкого бутстрапа различных технологий из коробки.
Если нужен DI, возьмите Guice.
В общем случае никакой синхронности/асинхронности не существует. Эти термины возникают, когда появляется понятие "поток выполнения" и связанные с ним термины: контекст выполнения, состояние, стек, etc… Возьмите любой нормальный функциональный язык программирования, и внезапно куда-то исчезнет вся "последовательность выполнения".
Есть два способа реализации асинхронного выполнения:
Очень сильно экономит время разработки. Он вызывается прямо во время компиляции, когда классы уже распарсены, но реально еще не сгенерированы. Решает проблемы:
Недостатки:
Есть куча примеров как написать простой annotation processor.
Есть такая вещь как annotation processor, которая существует уже давно и сделана специально для кодогенерации.
Меня беспокоит затронет ли это уже существующие компоненты JavaEE? Например у Eclipse Foundation была и есть годная имплементация JPA/JAXB под названием EclipseLink/MOXy...
Я конечно могу сильно ошибаться, но по-моему, я нечто подобное уже где-то видел:

Если вы действительно программируете, а я видел среди списка задач только типа "отправить книгу Коле", то должны знать, что программирование любой фичи требует максимальной концентрации на решаемой задаче. Требуется постоянно держать в памяти структуру проекта, модель функционирования, идеи и план реализации, возможные методы тестировния — и все это параллельно с устранением проблем и поском новой информации. И при том, что ресурсы межушного нервного узла сильно ограничены. И вот хуже нет, когда данный процесс прерывают искусственно и бросают на другую задачу. Переключение контекста и для железа стоит дорого — а для головы это вообще непосильный труд, приводящий к нервным расстройствам. И если вы можете параллельно и качественно концентрироваться на разных задачах, то вы сцуко Юлий Цезарь, и место вам в музее.
Зато когда все автопилоты будут координироваться централизованно системой-планировщиком, пробки уберутся и время в пути будет детерминировано.
Там проблема в другом. Сильный нейтронный поток радикально изменяет свойства материалов вплоть до механической деформации. Поэтому конструкция реактора должна быть хоть как-то ремонтопригодной и частично обновляемой. Вот вроде бы упомянутая статья: https://habr.com/ru/post/365991/
Ха! Вот только за последние три месяца (специфично для Java):
Продолжая квантовую тему, предлагаю ввести Эверетт-баг: когда код выполняется в какой-то "параллельной Вселенной" и его результаты абсолютно не соотносятся с исходниками. Обычно происходят по причине неправильного билда, либо ввиду внутренних багов используемых библиотек.
Есть такая приблуда как WMQTools. Написан давно каким-то хакером на Java. На порядки более удобоваримое, нежели RFHUtil. А последний, как впрочем и все от IBM — сделано не для людей.
P.S. Как сказал чел на первой картинке: "MQ вы… ет и высушит".
Следует отметить, что есть два типа кодогенерации — compile time и execution time. Первый практически всегда использует стандартный механизм Java — annotation processing. Второй метод использует bytecode instrumentation при загрузке классов и библиотеки типа cglib, bytebuddy, etc. Именно второй метод обычно используется всеми фреймворками для ускорения работы.
Reflection — это грязный хак, который изначально встроили только потому, что могли. Он сильно мешает оптимизациям в самой JVM, AOT, обфускации, а в коде используется в основном для интроспекции деклараций и проксирования. Без него везде использовалась бы кодогенерация и экосистема Java была бы более разумной и чистой.
Все доказательства у вас полезут в продакше, когда размер таблиц заметно подрастет.
Вот например баг по поводу дедлока:
https://groups.google.com/forum/#!searchin/h2-database/deadlock%7Csort:date/h2-database/wPR5gztLU34/EHMoEEpqBgAJ
Из стектрейса видно, что на больших resultset движок создает на диске временную таблицу, в которую сваливает результаты, а после закрытия resultset ее дропает.
Если интересно, поиграйтесь с солидными (50k+) табличками, джоинами и аналитическими запросами. Много всего интересного повылазит, например неоптимальное использование индексов планировщиком, которое никак не поменять.
Все-равно необходимы доверительные отношения, иначе ваша модель безопасности быстро парализует всю работу. Хорошая политика безопасности — та, которая не заметна. А против направленного вредительства пароли не сильно спасают.
Все-таки H2 больше для тестовых нужд, нужно понимать, что это все-таки не полноценный движок. Он хорош тем, что семантически поддерживает SQLи разных диалектов и может корректно их выполнять.
Мы пробовали использовать H2 1.4.196 в проде в embedded-режиме, и хоть задача и была достаточно простой, но даже на ней стали вылезать проблемы.
Мы мигрировали на Postgres за пару часов и с тех пор все тепло и сухо. А вот в тестбенчах и юнитах до сих пор используем H2.
Обиженный машинист может пустить поезд под откос, обиженный врач — навредить пациенту, обиженный повар — отравить гостей, обиженный полицейский — застрелить прохожего, обиженный оператор атомной станции — спровоцировать катастрофу. И ведь как-то это все работает без всяких паролей...
Это фейк. Пушки до 19 века никак не могли стрелять ядрами.
Поэтому наши продвинутые предки до катастрофы 18 века из т.н. "пушек" стреляли чем-то другим, например миниатюрными черными дырами, которые добывали в развалинах, оставленных от цивилизации атлантов, уничтоженной из космоса ядерным оружием в неравной битве с рептилоидами. А теперь они пытаются скрыть правду, выставляя эти загадочные древние орудия как примитивные средства ведения борьбы.
Вопрос в том, счетно оно или несчетно. Нераспавшийся свободный нейтрон в каждый момент времени генерирует новую ветвь, в которой он распался. Как производить интегрирование по всм этим вселенным?