Да, речь про nio, который доступен с Java 1.4, релиз которой был в 2002 году.
Почти 16 лет (!!) уже прошло, как в java нативно поддерживает асинхронный IO, а люди по прежнему несут бред про «в Java 10k клиентов = 10k потоков» (facepalm).
ps: Netty вообще имеет возможность работать с kqueue / epoll напрямую, если нужно.
Красиво пишите, но это больше материал для «впаривания», чем технический обзор :(
Модульность Node позволяет создавать маленькие приложения, не сталкиваясь при этом с необходимостью поддержки огромной инфраструктуры, многие части которой в некоем конкретном случае окажутся незадействованными. При разработке Node-приложений программист выбирает именно то, что ему нужно, и, при необходимости, расширяет решение.
На самом деле, в этом вопросе Node ни в чем не выигрывает и не проигрывает остальным платформам (C#, Java, PHP, RoR...);
Сама же фраза «поддержка огромной инфраструктуры» – попытка показать, что у всех хуже, просто потому, что принято так считать, без каких-либо утверждений (ну вы же знаете, что там у них все сложно, да?).
А на самом деле, для все той же Node нужно разворачивать все те же LB, watchdog, etc. подымать базы данных, редисы, подымать инфраструктуру в докерах… – так чем же это легче, чем у остальных? =)
В противовес более традиционным подходам, жёстко регламентирующим те или иные архитектурные особенности систем, структуру, которая поддерживает серверную часть вашего приложения, создаёте именно вы.
Увы, тут вы лукавите больше всего.
Node очень жестко регламентирует архитектуру: «либо так, либо никак»…
И связано это с EventLoop – писать тяжелые обработчики попросту «запрещено» этой архитектурой.
Кроме того, JS — это язык, популярность которого за последние пять лет растёт быстрее, чем у других языков, при том, что C# и PHP теряют позиции.
Тут отлично подойдет старый пример с SQL. Не важно, какая платформа для бекенда – все они используют SQL, и вот из-за этого SQL становится более популярным, чем сами платформы.
JS популярен потому, что он используется в подавляющем большинстве фронтенд разработки и при этом абсолютно не важно, что на бекенде. Статистика – хорошо, но ее нужно правильно интерпретировать.
ps: Node – действительно крутая технология и за нею будущее в некоторой определенной области, но вот статьи такого плана, которые навешивают лапшу – это плохо. Данная статья – лишь пример как перетягивать одеяло и вызывать холивары. Лучше стоит сконцентрироваться на том, чтобы делать из всего разнообразия фреймворков, языков и технологий – наилучшее решение из всех возможных.
Если начальник – «самодур» и даже готов платить сотруднику деньги за работу, то скорее всего у него все схвачено, а подчиненный не видит всей картины.
Иначе почему начальник он, а не подчиненный? =)
Звучит, как удобная фича с удобством для поддержки – меняешь роут, меняется и реверс урл.
Но для того, чтобы она работала, нужно чтобы фреймворк на себя брал очень много обязанностей, как минимум фреймворку нужно, чтобы он знал все его роуты по именам; а чтобы это все корректно работало, то еще и по параметрам (PathParams, QueryParams, etc), т.е. сам фреймворк уже становится раздутым и сложным.
Часто в этом даже нету необходимости: роуты практически никогда не меняются после релиза. А если меняются, то на старый вешается редирект, чтобы не сломать ничего.
Это без сомнения крутая фича, но в микрофреймворке она избыточна. Если нужно этот функционал можно прикрутить через стороннюю библиотеку.
Но самый большой плюс — поддержка стандартов (Servlet 3.1, JSR-356 для вебсокетов).
Servlet API – это крутой стандарт, но он уже монстроузорный :-(
Servlet API – это не HTTP стандарт, это абстракция над гораздо большим количеством протоколов. С чистым Servlet API крайне неудобно работать. И над ним делают еще парочку абстракций, чтобы добавить удобства. А потом это все выливается в довольно медленный код и раздутый хип.
Servlet API нужно омолаживать; его уже нужно чем-то заменить! Делать какой-то Java HTTP API.
Вы урезали контекст, изначально было: «Долбанная ошибка дизайна».
«Неочевидная вещь» – это проблема дизайна, т.е. – «Долбанная ошибка дизайна».
Тут хорошо подойдет аналогия с UI/UX: все должно быть максимально просто и очевидно. Если это не так, значит есть проблема. Язык программирования – это товар, а Программист – потребитель/пользователь.
Если Вы не согласны с этим утверждением, тогда ответьте на вопрос: почему каждый год выходят десятки новых языков и почему каждый раз, когда крупная компания выпускает свой язык, то подымается хайп?
Kotlin, Scala, Groovy, TypeScript, Elm, CoffeScript, Rust, Go, Swift, etc.
На сколько помню, целью Котлина было облегчение разработки и защита от глупых ошибок. А в результате одни глупые ошибки заменили на другие.
К сожалению, с практической точки зрения, эти «прикольные фичи», на самом деле – «долбанные ошибки дизайна».
Они есть во всех языках, но в некоторых для этого нужно сделать что-то невероятное.
А в Котлине, как показывает автор, на эти грабли можно будет наступить на каждом шагу :-(
Язык очень интересный, но складывается впечатление, что взяли все возможные фичи со всех языков и попытались все их уместить в один язык. В результате имеем такие вот забавные пазлеры.
Я упоминал в статье, что в дальнейшем я думаю использовать DynamoDB в качестве базы данных. При этом ничего не мешает при необходимости иметь еще и in-memory кэш в каждом из запущенных node-процессов.
Это не спасет от Sticky Sessions. Вам придется каждого пользователя направлять всегда на один и тот же сервер.
В противно случае, пользователю придется очень долго ждать, пока данные придут из DynamoDB в локальный кеш, более того, это будет расходом RAM на каждом из серверов (мелочь, но все же), и даже хуже: кеши будут не синхронизированы, а данные – не консистентны.
Сам подход со Sticky Sessions несет за собою проблемы неравномерной загрузки серверов практически без возможности перераспределить нагрузку.
Именно по этой Stateful сервера – это плохо, их тяжело масштабировать.
Интересный подход, но в нем есть и недостатки:
1. Лоадбалансинг: нужно использовать Sticky Sessions, чтобы пользователь всегда ходил на один и тот же сервер.
2. Если этот сервер ляжет – все пользователи потеряют свой стейт или вообще потеряют возможность работать.
3. Под возрастающей нагрузкой ответ от сервера будет дольше, а значит и отклик на действия пользователя будут дольше.
4. Мобильный интернет 3g/4g с плохим покрытием на низкой скорости даст ощутимую просадку в реакции на действия пользователя.
В статье я не увидел списка достоинств/недостатков данного подхода. Не могли бы Вы указать их?
В коде с монадами нам не надо при этом создавать ветки в вызывающем коде, а в коде с ООП — нужно было бы.
Вообще-то нет, не обязательно.
Метод, который выполняет какое-то действие кидает эксепшн (переходит на «красные пути»), который прерывает дальнейшее выполнение кода.
Функция validateRequest явно не занимается формированием ответа на, допустим, http запрос, значит она отдает ответ, который просто переводит исполнение на «красные пути», и где-то тааам, в конце кто-то примет этот ответ и сделает из него ответ на запрос.
в случае с эксепшеном:… и кто-то перехватит эксепшн и сделает из него ответ на запрос.
– суть та же, но способ реализации другой.
Вопрос: почему автор не использовал эксепшены и намеренно изуродовал ООП код? =)
К сожалению в репозитории я не нашел указанного метода.
Под «игнорируются» я имел ввиду, что в данном коде нету явных обработчиков ошибок. Они будут где-то снаружи (или внутри).
После ошибки в первой функции мы «перейдем на красные пути» и выйдем из функции с результатом, который говорит про ошибку – я прав?
И тут вопрос, который я изначально подымал: Кто обрабатывает эти ошибки?
Судя по коду есть 2 варианта:
1. ошибки обрабатываются внутри каждой функции, которую вызывает updateCustomerWithErrorHandling;
2. ошибка обрабатывается снаружи updateCustomerWithErrorHandling.
В обоих случаях – мы получаем несоответствие между двумя примерами кода.
Отлично, я в целом про это и говорил. Автор спекулирует кодом.
В ООП версии но ставил некрасивые обработчики, чтобы показать всю уродливость, хотя так никто не делает.
А в ФП версии кода, он даже не добавил никаких обработчиков, мол «вот смотрите как красиво!».
Если бы автор привел пример, где каждая ветка, которая может пойти не так выдавала бы свое сообщение об ошибке, это выглядело бы уже не так красочно, как он показывал ;-)
Там конкретный код взятый из статьи, который игнорирует ошибки. Никаких «если».
ps: можете привести пример правильного кода, который будет обрабатывать ошибки точно так же, как это делается в ООП варианте? Будет интересно посмотреть, на сколько он будет лучше смотреться.
Почти 16 лет (!!) уже прошло, как в java нативно поддерживает асинхронный IO, а люди по прежнему несут бред про «в Java 10k клиентов = 10k потоков» (facepalm).
ps: Netty вообще имеет возможность работать с kqueue / epoll напрямую, если нужно.
Ваша информация о Java уже лет 5-10 как устарела :(
Не стоит вводить читателей в заблуждение.
На самом деле, в этом вопросе Node ни в чем не выигрывает и не проигрывает остальным платформам (C#, Java, PHP, RoR...);
Сама же фраза «поддержка огромной инфраструктуры» – попытка показать, что у всех хуже, просто потому, что принято так считать, без каких-либо утверждений (ну вы же знаете, что там у них все сложно, да?).
А на самом деле, для все той же Node нужно разворачивать все те же LB, watchdog, etc. подымать базы данных, редисы, подымать инфраструктуру в докерах… – так чем же это легче, чем у остальных? =)
Увы, тут вы лукавите больше всего.
Node очень жестко регламентирует архитектуру: «либо так, либо никак»…
И связано это с EventLoop – писать тяжелые обработчики попросту «запрещено» этой архитектурой.
Тут отлично подойдет старый пример с SQL. Не важно, какая платформа для бекенда – все они используют SQL, и вот из-за этого SQL становится более популярным, чем сами платформы.
JS популярен потому, что он используется в подавляющем большинстве фронтенд разработки и при этом абсолютно не важно, что на бекенде. Статистика – хорошо, но ее нужно правильно интерпретировать.
ps: Node – действительно крутая технология и за нею будущее в некоторой определенной области, но вот статьи такого плана, которые навешивают лапшу – это плохо. Данная статья – лишь пример как перетягивать одеяло и вызывать холивары.
Лучше стоит сконцентрироваться на том, чтобы делать из всего разнообразия фреймворков, языков и технологий – наилучшее решение из всех возможных.
Иначе почему начальник он, а не подчиненный? =)
Где же тут удобство?
Фреймворки и дополнительные уровни абстракций появляются потому, что сервлеты в чистом виде – это боль и унижение.
Но для того, чтобы она работала, нужно чтобы фреймворк на себя брал очень много обязанностей, как минимум фреймворку нужно, чтобы он знал все его роуты по именам; а чтобы это все корректно работало, то еще и по параметрам (PathParams, QueryParams, etc), т.е. сам фреймворк уже становится раздутым и сложным.
Часто в этом даже нету необходимости: роуты практически никогда не меняются после релиза. А если меняются, то на старый вешается редирект, чтобы не сломать ничего.
Это без сомнения крутая фича, но в микрофреймворке она избыточна. Если нужно этот функционал можно прикрутить через стороннюю библиотеку.
ps: за 5+ лет еще не приходилось сталкиваться с этим термином; может эта фича не столь и нужная?
Servlet API – это крутой стандарт, но он уже монстроузорный :-(
Servlet API – это не HTTP стандарт, это абстракция над гораздо большим количеством протоколов. С чистым Servlet API крайне неудобно работать. И над ним делают еще парочку абстракций, чтобы добавить удобства. А потом это все выливается в довольно медленный код и раздутый хип.
Servlet API нужно омолаживать; его уже нужно чем-то заменить! Делать какой-то Java HTTP API.
В этом случае s?.isEmpty() вернет null.
Но null и true сравнивать запрещено.
null нельзя привести в boolean. А если это сделать – это ослабит типизацию, что повлечет ряд других проблем.
null – это не булевый тип, т.е. эта запись недоступна (как в котлине, так и в джаве).
«Неочевидная вещь» – это проблема дизайна, т.е. – «Долбанная ошибка дизайна».
Тут хорошо подойдет аналогия с UI/UX: все должно быть максимально просто и очевидно. Если это не так, значит есть проблема. Язык программирования – это товар, а Программист – потребитель/пользователь.
Если Вы не согласны с этим утверждением, тогда ответьте на вопрос: почему каждый год выходят десятки новых языков и почему каждый раз, когда крупная компания выпускает свой язык, то подымается хайп?
Kotlin, Scala, Groovy, TypeScript, Elm, CoffeScript, Rust, Go, Swift, etc.
На сколько помню, целью Котлина было облегчение разработки и защита от глупых ошибок. А в результате одни глупые ошибки заменили на другие.
Они есть во всех языках, но в некоторых для этого нужно сделать что-то невероятное.
А в Котлине, как показывает автор, на эти грабли можно будет наступить на каждом шагу :-(
Язык очень интересный, но складывается впечатление, что взяли все возможные фичи со всех языков и попытались все их уместить в один язык. В результате имеем такие вот забавные пазлеры.
В противно случае, пользователю придется очень долго ждать, пока данные придут из DynamoDB в локальный кеш, более того, это будет расходом RAM на каждом из серверов (мелочь, но все же), и даже хуже: кеши будут не синхронизированы, а данные – не консистентны.
Сам подход со Sticky Sessions несет за собою проблемы неравномерной загрузки серверов практически без возможности перераспределить нагрузку.
Именно по этой Stateful сервера – это плохо, их тяжело масштабировать.
1. Лоадбалансинг: нужно использовать Sticky Sessions, чтобы пользователь всегда ходил на один и тот же сервер.
2. Если этот сервер ляжет – все пользователи потеряют свой стейт или вообще потеряют возможность работать.
3. Под возрастающей нагрузкой ответ от сервера будет дольше, а значит и отклик на действия пользователя будут дольше.
4. Мобильный интернет 3g/4g с плохим покрытием на низкой скорости даст ощутимую просадку в реакции на действия пользователя.
В статье я не увидел списка достоинств/недостатков данного подхода. Не могли бы Вы указать их?
Метод, который выполняет какое-то действие кидает эксепшн (переходит на «красные пути»), который прерывает дальнейшее выполнение кода.
Функция validateRequest явно не занимается формированием ответа на, допустим, http запрос, значит она отдает ответ, который просто переводит исполнение на «красные пути», и где-то тааам, в конце кто-то примет этот ответ и сделает из него ответ на запрос.
в случае с эксепшеном:… и кто-то перехватит эксепшн и сделает из него ответ на запрос.
– суть та же, но способ реализации другой.
Вопрос: почему автор не использовал эксепшены и намеренно изуродовал ООП код? =)
Под «игнорируются» я имел ввиду, что в данном коде нету явных обработчиков ошибок. Они будут где-то снаружи (или внутри).
После ошибки в первой функции мы «перейдем на красные пути» и выйдем из функции с результатом, который говорит про ошибку – я прав?
И тут вопрос, который я изначально подымал: Кто обрабатывает эти ошибки?
Судя по коду есть 2 варианта:
1. ошибки обрабатываются внутри каждой функции, которую вызывает updateCustomerWithErrorHandling;
2. ошибка обрабатывается снаружи updateCustomerWithErrorHandling.
В обоих случаях – мы получаем несоответствие между двумя примерами кода.
В ООП версии но ставил некрасивые обработчики, чтобы показать всю уродливость, хотя так никто не делает.
А в ФП версии кода, он даже не добавил никаких обработчиков, мол «вот смотрите как красиво!».
Если бы автор привел пример, где каждая ветка, которая может пойти не так выдавала бы свое сообщение об ошибке, это выглядело бы уже не так красочно, как он показывал ;-)
ps: можете привести пример правильного кода, который будет обрабатывать ошибки точно так же, как это делается в ООП варианте? Будет интересно посмотреть, на сколько он будет лучше смотреться.