Pull to refresh
31
0.1
Антон Куранов @Throwable

Пользователь

Send message

Поведение @Transactional было скопировано в свое время с JavaEE, в котором многие решения были просто ужасными. В часности, непонятно зачем было выставлять UserTransaction.setRollbackOnly() при выкидывании unchecked exception на каждом прокси (наверное, чтобы как можно раньше откатить и освободить "ценнейший" ресурс), вместо того, чтобы откатывать только на верхнем уровне, если exception не был обработан.

Например, мы можем добавить атрибут noRollbackFor в PersonValidateService.

Это только если экспшн возникает непосредственно в вашем коде, а не ниже по стеку. Стандартная ситуация: работаем с JPA, хотим поставить логику на определенные ошибки, (напр. EntityExistsException). Однако noRollbackFor=PersistenceException.class не сработает, ибо EntityManager уже заботливо выставил setRollbackOnly.

Круто! Года 3 года назад я тоже сделал бота для онлайн игры в шахматы: https://t.me/GameFactoryBot Многие решения реализованы похожим образом (даже Postgres), за исключением того, что бэкенд на джаве. Не понял только как реализована нотификация хода с сервера -- Heroku вроде бы не дает вебсокеты.

Не лучшие впечатления от Telegram Bot Gaming Platform: она не эволюционирует и выглядит заброшенной, функционал заточен под простые казуальные игры и не приспособлен для мультиплеера, в десктопной версии из чата не работают линки на t.me/bot, невозможность нормально "зацепить" игру в чате с партией на сервере, кроме как по inline_mesage_id, ограничение, что игру вызывает только первая кнопка.

Вы, конечно, сравнили хорошо проработанный индустриальный стандарт с поделкой одной компании, склепанной на коленках и созданной с целью продвижения собственного коммерческого решения.
Про SOAP на время забыли, потому что IT отрасль массово заполонили JS-ники, для которых концепция декларации типов и транспорто-независимого протокола была непосильно сложной для их межушного нервного узла. "Зачем нам типы, у нас есть JSON и HTTP!".
Однако когда к новоиспеченному "API" подоспел серьезынй бизнес, потребовалась более строгая форма декларировать контракты взаимодействия между системами. И как результат в данный момент мы видим стихийное переизобретение велосипеда SOAP с нуля подручными и доступными для понимания средствами.

А он собственно на нем и был основан. А поскольку винда везде пиратская была, апдейты не устанавливались годами. Веселье было там, где была сеть — в общагах, в универе, в чатиках, на работе...

А знаменитый WinNuke, при помощи которого можно было удаленно перезагрузить любой компьютер по IP? Средство особенно пользовалось популярностью во всяких чатиках.


1000 и один способ обхода блокировки экрана в Windows 98. Например при нажатии кнопки на подключенном сканере вылезает окно с ошибкой. В нем жмем "Справка" — вылезает Win Help, затем "Файл" — "Открыть" и в окне файла имеем доступ к файловой системе. Из него же можно запустить любую программу. И все это при заблокированном десктопе.

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

Любой менеджер, продающий коммерческую BPM, с пеной у рта будет вам доказывать, что BPM обязательно должна ядром вашего бизнеса и IT-архитектуры, и все сервисы и процессы должны строиться вокруг нее. Иначе это пустая трата денег (что собственно верно). Ну а во-вторых, согласно моей практике, в большинство решений, где требуется "только мотор", в итоге очень неплохо обходятся без него. Как я уже сказал, много людей тащат в проект BPM, только потому что им внезапно понадобились асихнронные вызовы с персистенцией.


Основное преимущество в том, что BPMN – это исполняемая документация.

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

После прочтения этой статьи у вас может сложиться впечатление, будто мы отказались от всех преимуществ BPMS и переложили ответственность на самописный код. Но это не так.

Именно так. Более 10 лет разрабатывал под BPM, а ситуация все та же. Сначала вам задвигают Дорогое Красивое Решение, которое предендует на роль швейцарского ножа на все случаи жизни. Уже в процессе внезапно оказывается, что лезвия нихрена не режут, тупые, маленькие, пользоваться им не удобно или по большей части существуют как декорация. В итоге весь цикл разработки — это горожение велосипедов в борьбе с ограничениями платформы, и постепенная миграция критического функционала из BPM на самописку вплоть до полного отказа от этой самой BPM.


Центр любой BPMS – это BPM-движок, и мы используем его по полной. Это удивительный инструмент, который действительно помогает ускорить разработку и повысить качество поставляемых решений.

Ваш движок — это джарник на 100кб, коих на гитхабе полно, и сам по себе не несет абсолютно никакой ценности. Для того, чтобы его можно было использовать, нужна платформа для интеграции типа Spring и какой-нибудь persistence layer. Коммерческие решения поверх этого обвешиваются различного рода порталами и бизнес тулзами на все случаи жизни, однако как всегда жутко неудобоваримыми и ограниченными. У меня есть твердое убеждение, что весь этот обвесок служит по большей части для маркетинга, нежели для реального использования.


Ну и еще, такое наблюдение: 95% пользователей тащат в проект BPM потому что не знают как осуществить персистенцию долгоиграющего процесса или сделать асинхронный вызов. А большинство т.н. "процессов" — это линейные вызовы в лучшем случае с парой ветвлений.

Часто можно услышать совет «пишие комменте ПОЧЕМУ, а не ЧТО». Хотя это, вероятно, охватывает большинство моих комментариев, это не то, как я думаю о том, когда комментировать. Вместо этого я обычно пишу комментарий, когда есть что-то особенно сложное, либо в домене, либо в том, как выполняется реализация.

С философской точки зрения каждая строчка кода содержит техдолг по дальнейшей поддержке. Ценность представляет только конечный функционал. И если можно его реализовать вообще без единой строчки, то все идеально. В противном случае у вас всегда должен быть мотив "ПОЧЕМУ"/"ДЛЯ ЧЕГО" вы ее добавили. Теоретически этот мотив и следует указывать в комментарии. Вопрос "ЧТО" как правило решается осмысленными идентификаторами классов, методов и переменных. Вопрос "КАК" должен быть понятен из самого кода (тоже теоретически).


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

Если реализация метода сложная, и нет возможности разбить ее на отдельные функции, я использую "лесенку" при помощи блочных операторов: все детали вычислений загоняю под блок, наверху оставляя только переменные-результаты вычислений.


Есть еще такой момент: зачастую коментарии требуются не конкретному куску кода, а всему реализуемому функционалу. Для этого неплохо подходит файл package-info.java. Однако очень редко вижу, чтобы кто-то его использовал, за исключением самой JDK. А вот адепты TDD сказали бы, что в этом случае коментариями должны быть тесты.


Javadoc — самый бесполезный

Он не бесполезен, а неудобен. Неудобны теги, форматирование (звездочки вначале), html. Более адекватным для этих целей был бы Markdown.

Про дедлок слышали? https://ru.wikipedia.org/wiki/%D0%92%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%B0%D1%8F_%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0
Стоит модели и логике стать чуть сложнее — и вот вы уже висите в самый неподходящий момент. Если не нравятся тяжелые транзакции, посмотрите Software Transactional Memory.

Потому что в худшем случае это ворованное, а в лучшем — выловленное с punto limpio, куда народ сам несет выкидывать.

Колесо замкнется, когда кому-то в метабраузере снова понадобится метаканвас...

Рассмотрим ситуацию. Есть два кандидата:
20 лет опыта. java 6,7,8; j2ee; jdbc and so on.

Java 1.1-17, Kotlin/Scala/Clojure, Spring/Guice/Micronaut/любой другой DI, J2EE (CDI, JPA, JMS, SOAP, JTA), ApacheMQ/RabbitMQ/WebsphereMQ, паттерны проектирования, архитектура приложений. Прокачанные скиллы и интуиция. Человек, понимающий как внутри устроены инструменты, которыми он пользуется, и способный при необходимости написать с нуля любой из них.


5 лет опыта. java 11; spring jpa; kubernetes; kafka

Толком не знает как работает ни одно из этих "чудес", а тупо копипейстит из туториалов и SO, строгая шаблонные микросервисы. При вопросе про ACID, transaction isolation levels, delivery semantics той же kafka, и даже же про основу — Spring-овский DI, впадает в ступор. В итоге без надлежащего контроля уже с конвеера выходит абсолютный хлам. Модный, но хлам.


Некоторые решения давно устарели.

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


У всех программистов есть свои идеи и своё видение(

У детей тоже есть свое видение мира. Красочное, интересное, но наивное. Но оно никак не поможет построить ракету.


Склад ума === навязывание образа мыслей.

Так кажется неопытным айтишникам, которые не доросли до уровня, при котором аргументы техлида для них становятся понятны. Кроме того есть такая вещь как интуиция — "мне не нравится это решение, и я предвижу кучу скрытых проблем, которые последуют за ним, перечислять и анализировать которые у меня нет желания и времени".


Человек, готовый принять на себя удар в случае неверного решения. Щит команды. С какой целью?

Хотя бы с целью, чтобы тебя в субботу полупьяного из клуба не достал звонок разгневанного клиента, невнятно орущего, что у него все лежит, и он теряет кучу денег ежеминутно (реальный случай). Человека, способного оперативно разобраться с проблемой и предпринять необходимые действия. А также недопустить, чтобы откровенная халтура проникла на прод. Иначе каждый из команды будет объяснять клиенту как "у вас на компьютере все работало" и "все тесты были зелеными".


Начните набирать/обучать активных джунов/мидлов.

И кто, простите, будет их обучать? Онлайн академия с недельными курсами? Или собственными силами, собирая все грабли в одном проекте?

Это точно мне коментарий? У меня ноутбук 14" с Windows и подключен к внешнему монитору 21". Разрешение у мониторов однинаковые (Full HD), однако, как несложно догадаться, разный DPI. Поэтому в настройках скейлинга для экрана ноута ставим 150%, а для внешнего 125%. В итоге буквы и все элементы приложений одинаковый размер на обоих мониторах. При перетаскивании окна с одного монитора на другой меняется метрика приложения, и оно адаптируется под новый scale. Решено на Windows, Маках, Linux/Wayland, и возможно еще куче девайсов.


Мой коментарий заключается в том, что у девайсов должна быть еще одна метрика — угловой размер, на основании которого графическая подсистема сама выбирает параметры скейлинга. В итоге один и тот же шрифт (и все визуальные элементы) имеет одинаковый визуальный размер и на мобильнике, и на ноуте, и на мониторе, и на плазме 52", стоящей в двух метрах, и на экране проектора в зале заседаний.

Дык были же. Вспомним Java Applets, помянем Flash, Silverlight... Поскольку это были проприетарные решения, компании типа Google и Apple не были заинтересованы поддерживать их на своих платформах. Вместо этого решили использовать веб технологии в качестве тонкого клиента. Хотя сам Html изначально не задумывался для создания интерактивных интерфейсов, а именно для статичных страниц.

код который может вызвать запрос на гигабайт через пол-планеты — выглядят одинаково (как в каком-нить олдовом RPC).

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


А со временем все больше и больше API будут становиться полностью асинхронными (потому как тренд это нынче, не пишут сейчас чисто блокирующих API)

Мне бы ваш оптимизм, но увы. Еще даже нормального асинхронного JDBC стандарта на этот счет нет (и по ходу не будет). Весь низкоуровневый I/O-слой — это блокирующие API.

Действительно надо понимать где код suspendable а где нет.

Вообще-то нет — это совершенно лишнее знание (да простит меня Роман Елизаров), требуемое конкретной реализацией асинхронности. Асинхронность появилась для того, чтобы обойти ограничение posix thread на масштабируемость путем избегания блокировок. Корутины — это лишь хак компилятора, где suspendable подменяет собой asyncrhonous callback. А любой хак, всегда несет с собой кучу побочки и проблемы интеграцией с уже существующей базой. Навскидку, вам под suspendable придется переписать весь стек до самого низкого уровная I/O и JDBC, многие фреймворки используют текущий контекст ThreadLocal в аспектах (напр. @Transactional), кторый не будет работать с suspendable (но и не выдаст ошибки), сложность дебага и стектрейса, etc. С другой стороны упомянутый мной Loom совершенно прозрачно реализует масштабируесомть для блокируемого кода, не требуя абсолютно никаких модификаций. Поэтому для JVM тут спорный выигрыш.


Тем не менее корутины как механизм хорош на других платформах, где нет suspendable threads, либо нет блокировок (native, JS, Android).

Да, но например со стрингом не сработает. Есть неожиданный выход — описать Entity на Java, и все сразу заработает как надо :)

Собственно, ИМХО, сила типизации — это спектр, который как раз и определяется, присутствие насколько сложных желательных (или отсутствие нежелательных) поведений можно гарантировать системой типов языка.

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


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

Проблема в том, что как правило именно требует, благодаря чему делая простые вещи сложными в реализации. В Java вы не можете описать класс с динамическим набором полей, как в JavaScript — для этого приходится использовать Map. Еще более сложно иметь клас одновременно со статическими и динамическими полями. Котлине нет типа "contextual nullable" как в Java. Точнее он есть (Any!!), но это внутренний тип компилятора, введенный для совместимости с Java. TypeScript — да, позволяет использовать типы опционально там, где это нужно, имея fallback в JS.

Преимущество TS в том, что вам дают выбрать между строгой типизацией, нестрогой и динамической (всегда есть фоллбэк в голый JS). В Котлине (да и в Java тоже) такой опции нет — везде требуют строгие декларации, причем в котлине они более жесткие (тип dynamic не берем в рассмотрение — он был внедрен как пятое колесо специально для совместимости с JS). Сделано это с благими намерениями, чтобы обязовать пользователя писать "правильный" (по чьему-то мнению) код, однако как всегда там, где модель немного выходит за рамки, жесткие ограничения начинают жутко мешать.


И не очень понял какое отношение имеет binding к UI формам к обсуждаемому вопросу.

Как раз связано с nullable. Есть Entity, поля которой завязаны на UI-форму, и которая заполняется прогрессивно, например с веба. Вконце делается валидация полей (напр. при помощи JSR305), и все сохраняется в storage. Естественно, в Котлине все поля приходится описывать как nullable, и даже required-поля, которые никогда потом не будут null.


class User {
  @NotNull
  var username : String?
}

А затем уже на этапе использования везде расставлять "!!", либо пустые не-null проверки, что только увеличивает возможность ошибки. Многие скажут, что "правильный" kotlin-way здесь — это на каждую Entity создать еще один объект EntityDTO, в который делать меппинг формы, а затем уже замепить его в сам Entity. Но это сразу тупо в 4 раза увеличивает код практически без увеличения функциональной ценности.

Я реально уже не помню в деталях, раз как-то заставил работать. Общее впечатление — создаешь модель, она валится на сериализации из-за чисто котлиновских фич (конструкторы, nullability, immutable collections, delegates, vals, etc.), и приходится все перелопачивать. Для простых data objects проблем не возникает. Если интересно в деталях, загляните сюда https://github.com/FasterXML/jackson-module-kotlin/issues

Information

Rating
3,151-st
Location
Madrid, Испания
Registered
Activity