Pull to refresh
88
51
Subscribers
Send message

Сорри, промахнулся и поставил минус. А хотел плюс.


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

Тогда каким образом объясняется создание таких языков как Ada и Erlang в середине 80-х годов?

Ой, да бросьте. Это не более чем малограмотный вброс. Вы бы еще спросили, зачем в Java класс Thread, с первой версии (а это 1996 где-то). А еще средства координации потоков, разнообразию которых Go может только позавидовать белой завистью.

Знаете, я вот совсем недавно интересовался, для каких языков есть клиентские библиотеки к docker. Среди тех, что мне были интересны, были и Go и Rust.


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


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

Я бы еще хотел заметить, что эти ресурсы либо входят в состав программы (и делают ее толще), либо подкачиваются откуда-то из интернета, что как правило делает программу намного тормознее.


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


Ну и чего стоит название данного поста? Да лучше бы эта программа была еще толще (больше места занимала на диске), но зато простейшие текстовые меню открывала бы сразу, а не через пару минут.

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

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


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


Ну и напоследок — select *, да? А потом getString(1), да? И долго будет удивляться тот, кто это станет поддерживать, почему вдруг оно сломалось, от того, что совсем немного изменился набор (или порядок) колонок в таблице.

Да все в нем не так. Начнем с того, что Connection уже давно (ну лет так 10 наверное уже) рекомендуется получать не из DriverManager, а из DataSource. По разным причинам, например потому, что это обычно пул коннектов, а не один.


Во-вторых, за .close() внутри try — потому что это надо делать внутри finally, и не забывать при этом, что каждый из этих методов сам может кинуть исключение — и эти исключения нужно ловить (хотя обычно можно и не обрабатывать).


В-третьих, начиная с java 7 есть такая штука, как try with resources, и в принципе все ресурсы jdbc относятся к таким, которые могут быть закрыты автоматически.


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

Руки бы сегодня отрывать за такие примеры.

А где такой, простейший в общем-то, случай, когда один или несколько серверов server-1, server-2 и т.д. недоступны? Причем вообще говоря, они могут быть недоступны как полностью, так и частично.

Это перевод. А, сорри, да, просто ссылка немного не там.

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

Вы мои ответы изволите читать, или просто пишете, что в голову пришло? Там где у вас await — там нет никакого whenComplete, не путайтесь в своем же примере.

Блин. При чем тут пост? Я лично давно уже говорю совершенно о другом. await приостанавливает метод до завершения — тоже самое делает .get(). Хотите callback — берите CF, не хотите — get() это ровно тоже самое. Если вы не вызываете .get() — ваш текущий метод и поток (в java это одно и тоже) продолжает выполняться параллельно с тем потоком, в котором работает Future.


То что в C# из кода async метода генерируется де-факто callback — это совершенно другая история.

Оператор await применяется к задаче в асинхронном методе для приостановки выполнения метода до завершения выполнения ожидаемой задачи. Задача представляет выполняющуюся работу.


Это я цитирую MSDN, если что.


По-вашему, приостановка потока — это не равно "блокирование"?

Хм. Вот посмотрите внимательно на свой код с await, и расскажите мне, что делает ваш поток, если асинхронная операция на момент await еще не завершилась? Какой код он выполняет?

Я вам именно про это и толкую. Если у вас такая логика — вам прямая дорога к использованию просто Future, и просто .get(). У Future вообще нет callbacks, если они вам не нужны — зачем вы берете CompletableFuture, чье основное назначение — именно наличие callbacks?

Это вы меня не поняли. Если вам не нужен callback, который будет асинхронно вызван по завершению — то зачем вы берете CompletableFuture? Возмите просто Future, вызовите .get(), и будет у вас ровно тоже число строк — одна.


А если callback нужен — то пример с await неполный, и его надо переписать, и тогда он может будет проще и короче, а может и не будет.


Вообще вся вот эта вот фигня со списками и remove — она ровно для того, чтобы отслеживать, какие процессы завершились. А если у вас асинхронные callbacks — то вы и так знаете, когда и что завершилось, и эти же вещи удобнее делать не так. Изначальный код — он вообще странен, он от обычный Futures, так не пишут.

Эта статься — очень сильное упрощение. Ну вот например:


Всё дело в том, что не нужно писать .then, создавать анонимную функцию для обработки ответа, или включать в код переменную с именем data, которая нам, по сути, не нужна.

Это чепуха. Не полная, но в значительной степени. Что значит нам не нужна переменная data? Во-первых, промисы можно сцеплять в цепочки, и обрабатывать ответ много раз (например, для разных потребителей). При этом каждый обработчик будет получать результат работы предыдущего. Тот сценарий, когда можно без этого — это лишь один частный случай. И пусть он даже часто встречается — но есть и другие.


И потом, это все написано для javascript. А там все сильно иначе, чем в java, как в node, так и в вебе.

Я именно про эти накладные расходы — в виде лишних строчек. Их нет, потому что ваш пример с await — не их той оперы. Напомню:


CF — это A Future that may be explicitly completed (setting its value and status), and may be used as a CompletionStage, supporting dependent functions and actions that trigger upon its completion.


Если вам не нужен обработчик завершения (dependent functions and actions), который и есть вложенный вызов — то зачем вас сдался CompletableFuture? Возьмите обычный, и сделайте get() — и будет вам щастье.

Information

Rating
Does not participate
Registered
Activity