Че-то как-то не зашел — просмотрел полсезона, засыпаю на середине серии. Сюжеты не интригуют, не хватает экшна, юмор ситуативный на любителя, кроме главного героя остальный персонажи очень серые и незапоминающиеся, отношения мутные и невыраженные.
Любителям космических комедий могу порекоммендовать "Орвилл" — это современный кавер на "Звездный путь". Вот тут все очень живо и колоритно с первых секунд. Ну а в качестве серьезного сериала про космос конечно же смотреть "Пространство" (The Expanse) — imho лучшая космосага со времен BSG.
Тот же самый трюк с SerializedLambda использовал в своей библиотеке BeanRef, чтобы получить доступ к пропертям объекта через ссылку на геттер. Статья на хабре.
В долгосрочной перспективе решение не оправдало ожиданий: высокая трудоемкость создания бизнес-процессов через визуальные инструменты не позволила достичь приемлемых показателей продуктивности, а сам инструмент стал одним из самых нелюбимых среди разработчиков.
Это касается всех средств разработки для любой BPM. Строчить мышкой код — дело нудное и непродуктивное. Кроме того, у большинства производителей средства разработки мало что кривые, еще и глючные. После этого хочется кричать "дайте мне обычный текстовый редактор!".
Следует понимать, что движок — это еще не BPMS, если нужен только движок — их десятки разных, каждый из них не более 100кб. Кроме того, можно использовать корутины или файберы для написания бизнес процесса в более удобоваримой и натуральной форме.
Главным положительным моментом применения jBPM стало осознание пользы и вреда от наличия собственного персистентного состояния у экземпляра бизнес-процесса.
Сам движок — это еще не BPMS, и их существуют десятки похожих. Преимущество jBPM перед другими — это то, что он умеет версионировать не только сам процесс, но и весь артефакт, включая классы.
Недостатки синхронных вызовов как интеграционного паттерна
Описанные недостатки типа Quality-of-Service не относятся как таковые к способу вызова. Архитектурное отличие синхронных вызовов в том, что клиент обязан обрабатывать нештатные ситуации, и включать их в логику процесса посредством retries-with-delay или human task. Это сильно усложняет и замусоривает сам процесс. Кроме того, не стоит путать асинхронные вызовы с message-oriented communication. Асинхронные вызовы можно сделать при помощи того же синхронного вебсервиса, используя паттерны InvokeAsync и InvokeWithCallback. Во втором случае нужен сторонний брокер, который берет на себя задачи reliable delivery и доступен приложению в режиме 24/7.
Инкапсуляция бизнес-логики в микросервисах
Заведомо плохая идея выносить что-то, что зависит от состояния вне транзакции. После чтения данных из микросервиса сразу же теряется их актуальность. Контролировать целостность в таких случаях приходится вручную с лишними приседаниями: дополнительные операции компенсации, distributed locking (тот еще геморрой). Здесь не стоит гнаться за модой и на ровном месте создавать себе проблемы — микросервисы придуманы поколением девопсеров, которые по большей части произошли из мира JS, и большинство из которых плохо понимают концепции race conditions и acid. Оркестрация нужна там, где ваш процесс выходит за рамки одной системы (и собственно одного хранилища). В этом случае их нельзя объединить одной транзакцией.
Все сообщения – в одной очереди
С одним допущением: если ваша система использует исключительно асинхронный тип взаимодействия, а очередь потенциально безлимитна. Иначе есть вероятность нарваться на дедлок.
Обеспечение потокобезопасности бизнес-логики
Одному и тому же экземпляру бизнес-процесса может поступить сразу несколько сообщений и событий, обработка которых запустится параллельно.
Нет. Как вы могли заметить, ни одна из BPM не использует параллельное выполнение процесса. То есть всегда только одна транзакция модифицирует состояние. Даже если в процессе есть несколько веток, помеченных как параллельные, движок выполняет их последовательно каждую до первой блокирующей операции. Точно также и с сообщениями для процесса — движок обрабатывает их последовательно.
Проблемы начинаются, когда нужно внести изменения в бизнес-логику и/или модель бизнес-процесса. Не любое такое изменение оказывается совместимым со старым состоянием бизнес-процессов.
Это отдельная тема для лютого геморроя, где не существует стандартного хорошего решения. Большинство коммерческих BPMS имеют проприетарный формат хранения данных, поэтому вариант 2 отпадает. Некоторые BPMS продают на презентациях умение версионировать, но это касается только самого flow: естественно ни состояние ни интерфейсы, ни логику ни сервисы никто не версионирует. Кроме того, многие BPMS позволяют деплоить версии ранзных процессов, но не дают версионировать java-бандлы, которые идут вместе с ними, и где есть львиная доля всей логики. Есть еще 3 вариант: откатить запущенные процессы и рестартнуть их в новой версии. Актуально для коротких процессов, где определена компенсация каждого из них.
По Испании зарплаты в IT одни из самых низких по Европе, причем в Мадриде самые высокие по стране.
Верхний порог зарплаты никак не зависит от квалификации — только увеличивается объем и сложность работы. БОльшая зарплата — бОльший риск увольнения, и что на ваше место возьмут двух джунов за те же деньги.
Подавляющее большинство проектов — это сопровождение говносистем клиента и поддержка сторонних продуктов. Своего практически ничего не пилится и не внедряется — слишком большой риск и надо вкалывать.
Страна естественных монополий. Весь рынок предложений и услуг сожрали большие корпорации. Мелким игрокам клевать почти нечего.
Низкий профессиональный уровень и заинтересованность работников. За кофе двести раз обсудят новости, еду, футбол и отпуск, и ни разу к примеру фишки и полезности новой версии фреймворка X. Команды проекта чрезмерно раздуты бесполезными людьми, которым тимлиду необходимо придумывать посильную работу.
Развито кумовство — на хорошее место обязательно нужен "enchufe" (связи). Все стремятся руководить. Хлебное место — Gestión de proyecto (менеджмент проекта), где требуются минимальные навыки ввиде подвешенного языка и PowerPoint-а. В итоге организационная структура проекта уже выстроена, но не хватает работника, кто бы все сделал.
Ориентированность на прибыль, а не качество. Качество вообще никого нигде не волнует. В итоге 100% публичных е-сервисов — ё#### стыд, включая органы правительства, банки, сайты и системы крупных компаний.
Инфраструктура. До последнего времени мало компаний практиковало телеворкинг. Учитывая, что офисы большинства компаний находятся в пригородах (Alcobendas, Las Rozas...), добираться до них на общественном транспорте долго и неудобно, а иногда вообще не вариант. Личный авто — плохая альтернатива: ибо везде проблемы с парковкой (а в центре ее вообще как бы нет), пробки каждый день по часу-полтора туда и обратно, и постоянно ужесточающиеся меры против автомобилей.
Ну и собственно плюсы.
Какой-никакой соцпакет, предпенсионные программы, страховки, бонусы (зависит от компании), пособие по увольнению за выслугу лет. В convenio IT как правило хорошие отпуска.
Квалифицированному сотруднику в легко проявить себя и достичь уровня "стабильности".
Работа не сковывается жесткими дедлайнами. Поэтому всегда есть свободное время для креатива, и возможность к самообучению и саморазвитию.
Компании как правило свято чтут трудовой кодекс и все, что касается прав, оплаты, отпусков и персонального времени.
В целом, отсутствие токсичности и стресса на рабочем месте. Зависит конечно от места, но по моему опыту, все общение происходит очень корректно, неслыханно, чтобы кто-то на кого-то орал или неуважительно относился.
Возможность работать удаленно на зарубежные компании.
Несмотря на общий низкий уровень зарплат по Европе, хорошему специалисту на правильном месте на жизнь хватает.
А при чем тут собственно Spring и Boot? Что, все то же самое не будет работать для простой Java? Если так, то почему в таком случае статью не назвать "Удаленная отладка Java приложений"? Или вам платят за каждое упоминание Spring Boot по поводу и без повода?
Если уж завели речь про SB, то хотя бы упомяните Spring DevTools и возможность удаленной отладки, которая позволяет патчить изменения онлайн и перезагружать контекст. Иначе все ваши приседания с развертыванием придется повторять после каждого изменения.
Забудьте вообще про нее. Она вам нужна только, если вы планируете использовать ahead-of-time компиляцию и шипить ваше приложение в одном бандле с jvm. Модули — это внутренняя вещь jvm, которая была придумана только, чтобы реальный размер бандла был не 250М, а 20-30М. Все остальные кейсы неплохо решаются при помощи старых добрых build tools.
Котлин, и в какой-то мере Скала являлись своего рода ответом на более чем семилетний застой, который образовался в Java во второй половине нулевых. Но, благо дело сдвинулось с мертвой точки и Java стала обрастать модными фичами из других языков, делая все менее оправданным использование альтернатив.
linq, var, пропертей, null propagation, функциональщины
То есть все как бы есть, пусть не в самом языке, зато расширяемо библиотеками.
Программируя на Котлине, что я заметил:
Нет единого выработанного стиля. Да, более экспрессивный, но позволяет использовать разные конструкции для написания одного функционального фрагмента. Нет четких правил по структурированию кода (пакеты, классы, файлы, etc) и устаканившихся паттернов проектирования. Помножьте все на то, что в тот же проект коммитят еще несколько гениев, у каждого из которых свое понимание как правильно.
Пишется легче, но читается сложнее. Лаконичность приводит к бОльшей семантической нагрузке на строчку. Многие сложные многошаговые конструкции пытаются свернутся в однострочник. На порядок больше неявностей и контекстно-зависимой семантики. Естественно все от того кто и как пишет, но код, написанный на Котлине в стиле джавы проще и понятнее, нежели труЪ Kotlin-way.
Интегрируется с Java далеко не бесшовно. Если использовать чисто котлиновскую либу, то все ОК. Но с Java нужно всегда держать ухо в остро.
Сильно больше букав. Никакая IDE вас не спасёт от чтения килотонн boilerplate и не завезёт в язык перегрузку операторов и прочие полезные вещи.
Я не заметил особого boilerplate, кроме пропертей. Но это легко решает Lombok. Также как и для большинства вещей из Kotlin stdlib в джаве решается сторонними библиотеками. А лишнюю скобку поставить или указать тип — это не проблема с хорошей IDE. По моим наблюдениям на котлине код компактнее лишь на 20%, за исключением некоторых специфичных кейсов, где требуется DSL или перегрузка. Тут котлин рулит.
Есть экосистема JVM — это разные сборщики проектов (Ant/Maven/Gradle), это система распространения артефактов и пр.
Экосистема — это во-первых, сторонние библиотеки и фреймворки. Многие из них сильно заточены под джаву, а не котлин. Поэтому интеграция всегда идет с дополнительными приседаниями.
Ну во-первых — приведите пример, пожалуйста, вынужденного извращения на Kotlin.
Вот только то, что следует помнить, просто микшируя код на котлине с джавой: https://kotlinlang.org/docs/reference/java-interop.html
А вообще повсюду: интроспекция (reflection), annotation processing, проблема allopen, SAM & lambda conversions, проблема перекрытия ключевых слов (is/as, привет Mockito), static-и, не совпадает бинарно структура класса (здравствуй ASM/Javassist/ByteBuddy), не котлиновские коллекции в джаве — множество их. Не говорю, что они не решаемые, но это лишние накладки, которых можно избежать.
А потому фраза "то же самое можно сделать на Java"
Смысл моей фразы был в том, что реальный выигрыш от использования котлина не столь значителен перед джавой, и на джаве не сильно больше букав писать приходится, особенно с поддеркой IDE.
Например, если Вам надо ограничить наследование (я знаю, что в Java есть visitor, но ведь не всегда хочется писать много кода для такой простой вещи?).
Обычно подобные специфичные задачи всегда очень пунктуальны: надо еще 100 раз оценить, стоит ли ради нее в проект привлекать еще одну сильную зависимость, либо же обойтись тем, что предоставляет Джава. К тому же джава не стоит на месте, и скоро там появятся файберы, которые по-моему мнению, более органичны, чем корутины.
Вот сравнение скорости сборки.
Блин, не стоит тупо вестись на рекламу! Maven в отличие от Gradle по умолчанию не использует parallel builds, но их можно включить либо в самом pom.xml, либо опцией -T. Собственно и все, что нужно знать об этом "тесте", опубликованном на странице градла. К тому же на гифке не видно надписи "Starting gradle daemon...", что говорит о том, что билд уже не первый, и демон уже загружен и прогрет.
Гы, я ждал этого коментария :)
Ничего не имею против самого языка Котлина, но давайте будем объективными. Котлин разрабатывается уже лет 8, но основной всплеск интереса получил именно, когда Google анонсировал его как основным для андорида. До этого он еле входил в 50-ку. А открыв простую статистику github можно увидеть на чем разрабатывают люди. Плюс вычтите отсюда львиный процент разработки под андроид, и оцените на чем все-таки реально пишут под JVM. Даже Scala тут обходит.
В громадном числе Enterprise библиотек Kotlin используется или как второй официально поддерживаемый, наряду с Java (пример — Spring и компания)2
В каком громадном? Spring вообще технологическая помойка, которая стремиться всосать в себя всю экосистему. Поэтому было бы странно, если бы он не поддерживал Kotlin, но поддерживал какой-то Groovy. С другой стороны, идея разработчиков языка заключалась именно в переиспользовании экосистемы Java без всякой специальной поддержки. Но здесь не обошлось без костылей типа allopen.
Своя же чисто котлинская экосистема еще меньше, чем у скалки, львиную долю которой занимает то, что пилят в самом JetBrains.
В самой шустрой и быстроразвивающейся системе сборки
Это самая отстойная и тормозная система сборки с ядром на Groovy (но тем не менее полезная за отсутствием чего-то лучшего). Опять же популяризировалась засчет андроида. В 80% случаев все-равно Maven.
Чисто мое субъективное ощущение, когда я писал на котлине: нафига извращаться, если то же самое можно сделать на Java, не многим сильно приседая. Была нужда в fullstack проекте налабать фронт и бэк на котлине, но по ходу эта технология еще очень далека от массового использования. Проще взать какой-нибудь Vaadin или (прости хоспади, GWT).
Я не знаю что вы такое пишите, но вангую, что микросервисы, задача которых — это сделать rest-frontend для базы данных. С этой точки зрения абсолютно пофигу что использовать — сегодня все умеют Rest и SQL, и сравнивать на чем лучше мепить просто бессмысленно.
Там, где задача реально посложнее стоит, вам будут необходимы не столько возможности самого языка сколько то, что предоставляет экосистема. С этой точки зрения Java не переплюнуть. Основная проблема Scala и Kotlin в том, что они переиспользуют экосистему Java но интеграция далеко не бесшовная. В Scala попытались создать свою экосистему с блэкджеком, которая, однако, не имела особенного успеха. Лишь некоторые проекты заняли свои ниши, сделав тем самым скалу нишевым языком. Kotlin, несмотря на хайп и более гладкой интеграции с Java, также по большей части является нишевым для андроида.
На удалёнке люди работают не столько эффективнее, сколько тупо больше, со всеми вытекающими. В офисе люди работают от звонка до звонка — необходимость возвращаться домой так или иначе нормирует рабочий день. А на удалёнке эти грани постепенно смываются — внезапно ты обнаруживаешь себя в 12 ночи, пытающимся закончить задачу, которую не хочется откладывать на завтра.
Люди разные. Для экстравертов необходима постоянная подзарядка, живое общение и обмен идеями. Для интровертов же все это ненужный и отвлекающий шум.
Есть небезосновательное мнение, что checked exceptions в Java — это зло. От неправильного try-catch гораздо больше вреда, чем если бы его вообще не ставить — в последнем случае все-равно где-нибудь выше сработает обработчик, поставленный умными и компетентными людьми. Сколько встречал дерьма наподобие:
которые дают исчерпывающую информацию в логах о причине ошибки и заставляют медитировать над хрустальным шаром, пытаясь реконструировать сценарий по всевозможным сайд эффектам.
Поэтому один из способов снизить тревожность: заняться тем, что требует серьёзной умственной активности.
Сомнительно. Думаю, 99% пользователей хабра ежедневно занимаются серьезной умственной деятельностью, и тем не менее, почему-то наиболее подвержены тревожности, нежели люди, тяготеющие к физическому труду. Я сам после работы чувствую себя овощем, способным только поглотить ужин и тупо попялиться в надоевший сериал. И вот, как только приходит время спать, как головные тараканы выходят на охоту. Есть разные способы разогнать их — выпить снотворное, листать ленту или ютуб пока не отъедешь в мир снов. Но это не есть решение проблемы.
А вот то, что по-моему помогает для снижения тревожности:
Резко поменять обстановку: выбраться на природу, пойти в поход, съездить в другой город. Мозг будет занят обработкой новых ощущений.
Поменять вид деятельности: попробовать новое хобби, заняться спортом, заняться делами, которые долго откладывал.
Больше живого общения с людьми. Это создает ощущение себя частью общества, а соответственно защиты и ценности.
Как это ни странно, ограничить себя в получении новой информации. Мозг, перегруженный бесконечными несвязными фактами, совершенно не обрабатывает эту информацию, а получает лишь сиюминутные впечатления, которые через минуту забываются.
Суть Active Record проста: мы храним бизнес-логику с логикой хранения сущности.
Ну уж нифига. Active Record — это и есть хранилище, только не такое плоское, как Repository. Предоставляет для бизнес слоя доступ к данным в более удобной форме, нежели паттерн "хранилище", и инкапсулирует всю логику доступа, хранения изменения данных, экспортируя только консистентные операции.
Просто современные ORM недостаточно гибкие, чтобы раскрыть всю мощь удобства Active Record, ибо не позволяют напрямую управлять хранением из самой entity, а только управляют простыми отношения между сущностями. Объект-сущность в ORM мимикрирует под POJO, хотя таковым не является. Поэтому для более сложных операций вещей потребовался посредний — некий слой, куда можно было бы инъектировать ненавистный EntityManager, и который носит гордой название паттерн "хранилище".
Но это легко исправить: EntityManager доступен в текущем UnitOfWork (а вне ее он вообще не имеет смысла) как правило привязанном к ThreadLocal. Или как альтернатива — ковырнуть generated-поля самого класса Entity (он там тоже есть). И вперед! А все паттерны пусть идут лесом.
Но такое разделение ответственностей не дается бесплатно.
Еще бы! Через некоторое время проект превращается в помойку из копипейщеных слоев, дао, хранилищ и прочей лабуды. А любое изменение как ножом пронизывает насквозь сразу всю эту хваленую луковицу.
добавлять @Transactional на контроллер, что является грубейшим нарушением принципа разделения слоёв приложения
Принципы у всех разные, и не стоит абсолютизировать никакой из них. Для меня принципиальна бизнес логика приложения. Если она тонет в куче сопроводительного бойлерплейта, то стоит пересмотреть модель использования. Я всегда стараюсь, весь бойлерплейт замести под ковер и автоматизировать по мере возможности.
В данном случае не вижу ничего зазорного, чтобы контроллер был @Transactional. Даже если некоторые properties грузятся как lazy, при сериализации они корректно догрузятся.
либо явно загружать ленивую сущность (нужно приседать с графами или явно прописывать fetch)
Суперинтерфейсы (BasicInfo, ExtendedInfo, SecurityInfo, etc...) как раз по сути определяют наборы свойств, которые необходимо вытащить в каждом конкретном случае, поэтому ничто не мешает модифицировать репозиторий и сделать автоматическую генерацию графа для каждого из суперинтерфейсов.
// dao-метод возвращает список User entity с загруженными свойствами только для суперинтерфейса T
<T super User> List<T> findAll(Class<T> superClass);
...
List<BasicInfo> userInfos = findAll(BasicInfo.class);
Мы получаем весьма элегантное построение не сложного объекта:
Как раз для построения несложного объекта здесь нет элегантности, ибо сильно пестрят в глазу builder().build(). Кроме того билдеры в отличие от конструкторов не контролируют required-поля. Они хороши, когда есть настраиваемый объект с множеством опциональных пропертей.
Я предпочитаю factory method, в который добавляю required поля, без которых объект не имеет смысла, а все опциональные поля устанавливаются при помощи wither-ов. Есть минимальные накладные расходы на копирование immutable-объекта, но я предпочитаю элегантность и читабельность.
Не совсем. Сериализатор настроен так, чтобы отдавать только сет свойств, указанных в возвращаемом интерфейсе.
@GET
@Path("/users/{userId}")
public BasicInfo getUserBasicInfo(@PathParam("userId") String userId) {
User user = userDao.findById(userId);
return user;
}
Окей, это интересно (нет, серьёзно), но что делать с зависимостями, которые линкуются статически?
Я не разрабатываю на Си, но насколько я могу судить (да поправят меня знающие люди), нет большой разницы слинкована библиотека динамически или статически. Любое приложение можно слинковать обоими способами (чем пользуются всякие flatpack и snappy). В первом случае резольвинг идет в рантайме на этапе загрузки бандла, тогда как во втором — сразу на этапе линковки бандла. Правила резольвинга не должны отличаться.
Или просто в новой версии транзитивной зависимости добавили новую функцию, которая имеет то же имя, что и в библиотеке.
Когда говорят о транзитивных зависимостях, почему-то нигде не указывают тип транзитивности. Вне зависимости от языка программирования любая библиотека всегда состоит из двух частей: интерфейса (структуры, типы, сигнатуры функций) и имплементации (непосредственно код). Интерфейс библиотека экспортирует наружу, тогда как имплепентация — это внутреннее поведение библиотеки. Если транзитивная зависимость используется полностью в имплементативной части библиотеки, то нет никаких проблем иметь разные версии в разных зависимостях: различные платформы предоставляют свои средства "изоляции" (namespaces, dynamic linkers, classloaders, etc...).
Если же библиотека экспортирует в своем интерфейсе элементы из транзитивной зависимости, то тут нет простого решения, т.к. описания из транзитивных интерфейсов разных версий могут конфликтовать в одном бандле. Выделяют частный случай, когда описания обратно совместимы, например, когда в интерфейс добавили новые элементы, не модифицируя старые. Для этого при компиляции берут интерфейс более свежей библиотеки, а на этапе линковки можно слинковать те транзитивные версии, которые требуются каждой из библиотек (если платформа позволяет их корректно изолировать).
Если же транзитивные интерфейсы несовместимы, то все плохо: одну из веток зависимостей придется полностью изолировать или даже виртуализировать и писать к ней адаптер (ну или как вариант оставить все как есть и посмотреть что будет).
Классику даже не упоминаем :)
Че-то как-то не зашел — просмотрел полсезона, засыпаю на середине серии. Сюжеты не интригуют, не хватает экшна, юмор ситуативный на любителя, кроме главного героя остальный персонажи очень серые и незапоминающиеся, отношения мутные и невыраженные.
Любителям космических комедий могу порекоммендовать "Орвилл" — это современный кавер на "Звездный путь". Вот тут все очень живо и колоритно с первых секунд. Ну а в качестве серьезного сериала про космос конечно же смотреть "Пространство" (The Expanse) — imho лучшая космосага со времен BSG.
Тот же самый трюк с SerializedLambda использовал в своей библиотеке BeanRef, чтобы получить доступ к пропертям объекта через ссылку на геттер. Статья на хабре.
Это касается всех средств разработки для любой BPM. Строчить мышкой код — дело нудное и непродуктивное. Кроме того, у большинства производителей средства разработки мало что кривые, еще и глючные. После этого хочется кричать "дайте мне обычный текстовый редактор!".
Следует понимать, что движок — это еще не BPMS, если нужен только движок — их десятки разных, каждый из них не более 100кб. Кроме того, можно использовать корутины или файберы для написания бизнес процесса в более удобоваримой и натуральной форме.
Сам движок — это еще не BPMS, и их существуют десятки похожих. Преимущество jBPM перед другими — это то, что он умеет версионировать не только сам процесс, но и весь артефакт, включая классы.
Описанные недостатки типа Quality-of-Service не относятся как таковые к способу вызова. Архитектурное отличие синхронных вызовов в том, что клиент обязан обрабатывать нештатные ситуации, и включать их в логику процесса посредством retries-with-delay или human task. Это сильно усложняет и замусоривает сам процесс. Кроме того, не стоит путать асинхронные вызовы с message-oriented communication. Асинхронные вызовы можно сделать при помощи того же синхронного вебсервиса, используя паттерны InvokeAsync и InvokeWithCallback. Во втором случае нужен сторонний брокер, который берет на себя задачи reliable delivery и доступен приложению в режиме 24/7.
Заведомо плохая идея выносить что-то, что зависит от состояния вне транзакции. После чтения данных из микросервиса сразу же теряется их актуальность. Контролировать целостность в таких случаях приходится вручную с лишними приседаниями: дополнительные операции компенсации, distributed locking (тот еще геморрой). Здесь не стоит гнаться за модой и на ровном месте создавать себе проблемы — микросервисы придуманы поколением девопсеров, которые по большей части произошли из мира JS, и большинство из которых плохо понимают концепции race conditions и acid. Оркестрация нужна там, где ваш процесс выходит за рамки одной системы (и собственно одного хранилища). В этом случае их нельзя объединить одной транзакцией.
С одним допущением: если ваша система использует исключительно асинхронный тип взаимодействия, а очередь потенциально безлимитна. Иначе есть вероятность нарваться на дедлок.
Нет. Как вы могли заметить, ни одна из BPM не использует параллельное выполнение процесса. То есть всегда только одна транзакция модифицирует состояние. Даже если в процессе есть несколько веток, помеченных как параллельные, движок выполняет их последовательно каждую до первой блокирующей операции. Точно также и с сообщениями для процесса — движок обрабатывает их последовательно.
Это отдельная тема для лютого геморроя, где не существует стандартного хорошего решения. Большинство коммерческих BPMS имеют проприетарный формат хранения данных, поэтому вариант 2 отпадает. Некоторые BPMS продают на презентациях умение версионировать, но это касается только самого flow: естественно ни состояние ни интерфейсы, ни логику ни сервисы никто не версионирует. Кроме того, многие BPMS позволяют деплоить версии ранзных процессов, но не дают версионировать java-бандлы, которые идут вместе с ними, и где есть львиная доля всей логики. Есть еще 3 вариант: откатить запущенные процессы и рестартнуть их в новой версии. Актуально для коротких процессов, где определена компенсация каждого из них.
Почему Мадрид не лучший выбор для IT?
Ну и собственно плюсы.
А при чем тут собственно Spring и Boot? Что, все то же самое не будет работать для простой Java? Если так, то почему в таком случае статью не назвать "Удаленная отладка Java приложений"? Или вам платят за каждое упоминание Spring Boot по поводу и без повода?
Если уж завели речь про SB, то хотя бы упомяните Spring DevTools и возможность удаленной отладки, которая позволяет патчить изменения онлайн и перезагружать контекст. Иначе все ваши приседания с развертыванием придется повторять после каждого изменения.
Забудьте вообще про нее. Она вам нужна только, если вы планируете использовать ahead-of-time компиляцию и шипить ваше приложение в одном бандле с jvm. Модули — это внутренняя вещь jvm, которая была придумана только, чтобы реальный размер бандла был не 250М, а 20-30М. Все остальные кейсы неплохо решаются при помощи старых добрых build tools.
Котлин, и в какой-то мере Скала являлись своего рода ответом на более чем семилетний застой, который образовался в Java во второй половине нулевых. Но, благо дело сдвинулось с мертвой точки и Java стала обрастать модными фичами из других языков, делая все менее оправданным использование альтернатив.
То есть все как бы есть, пусть не в самом языке, зато расширяемо библиотеками.
Программируя на Котлине, что я заметил:
Я не заметил особого boilerplate, кроме пропертей. Но это легко решает Lombok. Также как и для большинства вещей из Kotlin stdlib в джаве решается сторонними библиотеками. А лишнюю скобку поставить или указать тип — это не проблема с хорошей IDE. По моим наблюдениям на котлине код компактнее лишь на 20%, за исключением некоторых специфичных кейсов, где требуется DSL или перегрузка. Тут котлин рулит.
Экосистема — это во-первых, сторонние библиотеки и фреймворки. Многие из них сильно заточены под джаву, а не котлин. Поэтому интеграция всегда идет с дополнительными приседаниями.
Вот только то, что следует помнить, просто микшируя код на котлине с джавой:
https://kotlinlang.org/docs/reference/java-interop.html
А вообще повсюду: интроспекция (reflection), annotation processing, проблема allopen, SAM & lambda conversions, проблема перекрытия ключевых слов (is/as, привет Mockito), static-и, не совпадает бинарно структура класса (здравствуй ASM/Javassist/ByteBuddy), не котлиновские коллекции в джаве — множество их. Не говорю, что они не решаемые, но это лишние накладки, которых можно избежать.
Смысл моей фразы был в том, что реальный выигрыш от использования котлина не столь значителен перед джавой, и на джаве не сильно больше букав писать приходится, особенно с поддеркой IDE.
Обычно подобные специфичные задачи всегда очень пунктуальны: надо еще 100 раз оценить, стоит ли ради нее в проект привлекать еще одну сильную зависимость, либо же обойтись тем, что предоставляет Джава. К тому же джава не стоит на месте, и скоро там появятся файберы, которые по-моему мнению, более органичны, чем корутины.
Блин, не стоит тупо вестись на рекламу! Maven в отличие от Gradle по умолчанию не использует parallel builds, но их можно включить либо в самом pom.xml, либо опцией -T. Собственно и все, что нужно знать об этом "тесте", опубликованном на странице градла. К тому же на гифке не видно надписи "Starting gradle daemon...", что говорит о том, что билд уже не первый, и демон уже загружен и прогрет.
Гы, я ждал этого коментария :)
Ничего не имею против самого языка Котлина, но давайте будем объективными. Котлин разрабатывается уже лет 8, но основной всплеск интереса получил именно, когда Google анонсировал его как основным для андорида. До этого он еле входил в 50-ку. А открыв простую статистику github можно увидеть на чем разрабатывают люди. Плюс вычтите отсюда львиный процент разработки под андроид, и оцените на чем все-таки реально пишут под JVM. Даже Scala тут обходит.
В каком громадном? Spring вообще технологическая помойка, которая стремиться всосать в себя всю экосистему. Поэтому было бы странно, если бы он не поддерживал Kotlin, но поддерживал какой-то Groovy. С другой стороны, идея разработчиков языка заключалась именно в переиспользовании экосистемы Java без всякой специальной поддержки. Но здесь не обошлось без костылей типа allopen.
Своя же чисто котлинская экосистема еще меньше, чем у скалки, львиную долю которой занимает то, что пилят в самом JetBrains.
Это самая отстойная и тормозная система сборки с ядром на Groovy (но тем не менее полезная за отсутствием чего-то лучшего). Опять же популяризировалась засчет андроида. В 80% случаев все-равно Maven.
Чисто мое субъективное ощущение, когда я писал на котлине: нафига извращаться, если то же самое можно сделать на Java, не многим сильно приседая. Была нужда в fullstack проекте налабать фронт и бэк на котлине, но по ходу эта технология еще очень далека от массового использования. Проще взать какой-нибудь Vaadin или (прости хоспади, GWT).
Я не знаю что вы такое пишите, но вангую, что микросервисы, задача которых — это сделать rest-frontend для базы данных. С этой точки зрения абсолютно пофигу что использовать — сегодня все умеют Rest и SQL, и сравнивать на чем лучше мепить просто бессмысленно.
Там, где задача реально посложнее стоит, вам будут необходимы не столько возможности самого языка сколько то, что предоставляет экосистема. С этой точки зрения Java не переплюнуть. Основная проблема Scala и Kotlin в том, что они переиспользуют экосистему Java но интеграция далеко не бесшовная. В Scala попытались создать свою экосистему с блэкджеком, которая, однако, не имела особенного успеха. Лишь некоторые проекты заняли свои ниши, сделав тем самым скалу нишевым языком. Kotlin, несмотря на хайп и более гладкой интеграции с Java, также по большей части является нишевым для андроида.
P.S. А еще Scala страшный и тяжелый
На удалёнке люди работают не столько эффективнее, сколько тупо больше, со всеми вытекающими. В офисе люди работают от звонка до звонка — необходимость возвращаться домой так или иначе нормирует рабочий день. А на удалёнке эти грани постепенно смываются — внезапно ты обнаруживаешь себя в 12 ночи, пытающимся закончить задачу, которую не хочется откладывать на завтра.
Люди разные. Для экстравертов необходима постоянная подзарядка, живое общение и обмен идеями. Для интровертов же все это ненужный и отвлекающий шум.
Есть небезосновательное мнение, что checked exceptions в Java — это зло. От неправильного try-catch гораздо больше вреда, чем если бы его вообще не ставить — в последнем случае все-равно где-нибудь выше сработает обработчик, поставленный умными и компетентными людьми. Сколько встречал дерьма наподобие:
или даже
которые дают исчерпывающую информацию в логах о причине ошибки и заставляют медитировать над хрустальным шаром, пытаясь реконструировать сценарий по всевозможным сайд эффектам.
Сомнительно. Думаю, 99% пользователей хабра ежедневно занимаются серьезной умственной деятельностью, и тем не менее, почему-то наиболее подвержены тревожности, нежели люди, тяготеющие к физическому труду. Я сам после работы чувствую себя овощем, способным только поглотить ужин и тупо попялиться в надоевший сериал. И вот, как только приходит время спать, как головные тараканы выходят на охоту. Есть разные способы разогнать их — выпить снотворное, листать ленту или ютуб пока не отъедешь в мир снов. Но это не есть решение проблемы.
А вот то, что по-моему помогает для снижения тревожности:
Ну уж нифига. Active Record — это и есть хранилище, только не такое плоское, как Repository. Предоставляет для бизнес слоя доступ к данным в более удобной форме, нежели паттерн "хранилище", и инкапсулирует всю логику доступа, хранения изменения данных, экспортируя только консистентные операции.
Просто современные ORM недостаточно гибкие, чтобы раскрыть всю мощь удобства Active Record, ибо не позволяют напрямую управлять хранением из самой entity, а только управляют простыми отношения между сущностями. Объект-сущность в ORM мимикрирует под POJO, хотя таковым не является. Поэтому для более сложных операций вещей потребовался посредний — некий слой, куда можно было бы инъектировать ненавистный EntityManager, и который носит гордой название паттерн "хранилище".
Но это легко исправить: EntityManager доступен в текущем UnitOfWork (а вне ее он вообще не имеет смысла) как правило привязанном к ThreadLocal. Или как альтернатива — ковырнуть generated-поля самого класса Entity (он там тоже есть). И вперед! А все паттерны пусть идут лесом.
Еще бы! Через некоторое время проект превращается в помойку из копипейщеных слоев, дао, хранилищ и прочей лабуды. А любое изменение как ножом пронизывает насквозь сразу всю эту хваленую луковицу.
Принципы у всех разные, и не стоит абсолютизировать никакой из них. Для меня принципиальна бизнес логика приложения. Если она тонет в куче сопроводительного бойлерплейта, то стоит пересмотреть модель использования. Я всегда стараюсь, весь бойлерплейт замести под ковер и автоматизировать по мере возможности.
В данном случае не вижу ничего зазорного, чтобы контроллер был @Transactional. Даже если некоторые properties грузятся как lazy, при сериализации они корректно догрузятся.
Суперинтерфейсы (BasicInfo, ExtendedInfo, SecurityInfo, etc...) как раз по сути определяют наборы свойств, которые необходимо вытащить в каждом конкретном случае, поэтому ничто не мешает модифицировать репозиторий и сделать автоматическую генерацию графа для каждого из суперинтерфейсов.
Вот вам и автоматизация DTO.
Как раз для построения несложного объекта здесь нет элегантности, ибо сильно пестрят в глазу builder().build(). Кроме того билдеры в отличие от конструкторов не контролируют required-поля. Они хороши, когда есть настраиваемый объект с множеством опциональных пропертей.
Я предпочитаю factory method, в который добавляю required поля, без которых объект не имеет смысла, а все опциональные поля устанавливаются при помощи wither-ов. Есть минимальные накладные расходы на копирование immutable-объекта, но я предпочитаю элегантность и читабельность.
Не совсем. Сериализатор настроен так, чтобы отдавать только сет свойств, указанных в возвращаемом интерфейсе.
В этом случае контроллер отдаст JSON:
Я не разрабатываю на Си, но насколько я могу судить (да поправят меня знающие люди), нет большой разницы слинкована библиотека динамически или статически. Любое приложение можно слинковать обоими способами (чем пользуются всякие flatpack и snappy). В первом случае резольвинг идет в рантайме на этапе загрузки бандла, тогда как во втором — сразу на этапе линковки бандла. Правила резольвинга не должны отличаться.
Когда говорят о транзитивных зависимостях, почему-то нигде не указывают тип транзитивности. Вне зависимости от языка программирования любая библиотека всегда состоит из двух частей: интерфейса (структуры, типы, сигнатуры функций) и имплементации (непосредственно код). Интерфейс библиотека экспортирует наружу, тогда как имплепентация — это внутреннее поведение библиотеки. Если транзитивная зависимость используется полностью в имплементативной части библиотеки, то нет никаких проблем иметь разные версии в разных зависимостях: различные платформы предоставляют свои средства "изоляции" (namespaces, dynamic linkers, classloaders, etc...).
Если же библиотека экспортирует в своем интерфейсе элементы из транзитивной зависимости, то тут нет простого решения, т.к. описания из транзитивных интерфейсов разных версий могут конфликтовать в одном бандле. Выделяют частный случай, когда описания обратно совместимы, например, когда в интерфейс добавили новые элементы, не модифицируя старые. Для этого при компиляции берут интерфейс более свежей библиотеки, а на этапе линковки можно слинковать те транзитивные версии, которые требуются каждой из библиотек (если платформа позволяет их корректно изолировать).
Если же транзитивные интерфейсы несовместимы, то все плохо: одну из веток зависимостей придется полностью изолировать или даже виртуализировать и писать к ней адаптер (ну или как вариант оставить все как есть и посмотреть что будет).