Неделю назад в Питере прошла встреча JUG.ru с разработчиками языка Kotlin Андреем Бреславом и Дмитрием Жемеровым. Как вы все наверняка знаете, Kotlin зарелизился пару недель назад, и теперь, спустя почти шесть лет разработки, пришла пора поговорить о том, что в итоге получилось.

В пятничный вечер 26 февраля народу в питерский офис Oracle набилось дофига, что очень обрадовало и нас и спикеров.



Встреча состояла из четырех частей:
  • Введение. Что такое Kotlin?
  • Kotlin: к релизу и далее
  • Kotlin: самое сложное — совместимость
  • Сессия вопросов и ответов про Kotlin



Андрей Бреслав — Введение. Что такое Kotlin?




Рассказ, что такое Kotlin, какие идеи в него заложены и как эти идеи эволюционировали в течение последних пяти лет.





Дмитрий Жемеров — Kotlin: к релизу и далее




Начиная с версии 1.0, Kotlin предоставляет гарантии обратной совместимости с существующим кодом. Дмитрий рассказал о том, что разработчики Kotlin обещают нам с вами на будущее, о том, как эти обещания повлияли на дизайн языка, и о том, под какие направления будущего развития уже есть заготовки в версии 1.0.





Андрей Бреслав — Kotlin: самое сложное — совместимость


Андрей рассказал о том, как они с коллегами боролись за прозрачную совместимость с Java — чтобы Kotlin и Java могли дружно обитать в одном проекте. Для этого пришлось придумать немало оригинальных решений и пойти на многие компромиссы на всех уровнях: от системы типов до плагинов к билд-системам.




Сессия вопросов и ответов про Kotlin







Получилось бодро, получилось весело, народу в целом понравилось. А вам?

Оставляйте ваши мнения и вопросы в комментариях и подписывайтесь на JUG.ru в соцсетях (Twitter, VK, FB, OK) и YouTube.

Команда JUG.ru желает вам приятного просмотра.

Комментарии (9)


  1. vsb
    06.03.2016 23:37

    Спасибо за видео, очень интересно. К сожалению многие вопросы из зала почти не слышно.


    1. 23derevo
      06.03.2016 23:39

      спикеры почти всегда повторяли вопросы :)


  1. bigfatbrowncat
    07.03.2016 00:32

    Не знаю, где задать вопрос по этой теме, попробую обсудить здесь.

    Я уже давно заинтересовался языком Kotlin, мне очень нравится как сама идея "обновить" Java, так и выбранное разработчиками направление. Почти все принятые решения очень радуют. Помимо одного — отсутствия "контроллируемых" исключений.

    Я специально внимательно прочитал всё, что авторы языка писали по этому поводу. В разделе "Checked Exceptions" на официальном сайте написано совершенно невнятное объяснение, которое бы я хотел оспорить.

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

    Привожу пример с сайта:

    try {
      log.append(message)
    }
    catch (IOException e) {
      // Must be safe
    }

    Привожу то, как поступаю в подобной ситуации я сам (и рекомендую любому Java-разработчику):

    try {
      log.append(message)
    }
    catch (IOException e) {
      throw new RuntimeException(e); // Maybe we should use some RuntimeException subclass here
    }

    Пример, приведенный в статье, несомненно, плох. Но проблема не в наличии "контроллируемых" исключений в языке — на один случай, когда они вредны, приходится 10 случаев, когда они спасают разработчика от проблем из-за невнимательности или плохого знания чужих API. Проблема в том, что многие, очевидно, не любят (не хотят, не знают, что можно или нужно) преобразовывать при необходимости контроллируемые исключения в неконтроллируемые.

    Я сам в Java пришел из C# и C++. В первом нет проверяемых исключений вовсе, во втором они как бы есть, но обычно не используются. И через некоторое время я начал недоумевать, почему такой прекрасный способ самопроверки присутствует только в Java. Ведь именно с практической точки зрения, например, парсер JSON должен выкидывать JSONException, который внешний код должен обязательно обработать — и в это разработчику полезно "ткнуться носом", чтобы не забыть. Даже если обработка похожа на то, что я написал выше и упирается в конвертацию контроллируемого исключения в неконтроллируемое. Типа такого:

    try {
      parseSomeConfig(...);
    } catch (JSONException e) {
      throw ConfigParsingException("The config is incorrect", e); // ConfigParsingException extends RuntimeException
    }

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

    В аргументах на сайте написано "в больших проектах выгода стремится к нулю". Логика, на мой взгляд, странная. Потому что в маленьком проекте, как раз, можно помнить, какой именно код выкидывает какое исключение — ПОМНИТЬ. И поймать его. А вот в большом… Я не знаю, что такое "большой проект" в понимании авторов. По моему собственному опыту, чем больше кода (особенно, чужого, требующего адаптироваться), тем сложнее в этом коде корректно обработать нештатные ситуации. И при правильном использовании checked-exception очень помогает.


    1. 23derevo
      07.03.2016 00:39
      +1

      Если вам не хватает объяснений на сайте котлина — просто погуглите. Интернет завален холиварами на тему «нужны ли checked exceptions?»


      1. bigfatbrowncat
        07.03.2016 00:47

        Разумеется, я их читал. И в некоторых даже участвовал.

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

        1. Приведенный у разрабов Kotlin-а типа "люди не умеют их готовить, поэтому травятся сырыми"
        2. Они ограничивают меня в движениях! Мне всё время приходится писать "throws"
        3. Серьезные чуваки утверждают, что checked exceptions — зло.

        По пункту 1 я уже высказался (не впервые — обычно спорящие люди, например, обнаруживают незнание того, что исключения можно "нанизывать матрешкой" друг на друга. Разумеется, здесь люди грамотные, но тогда мне тем более не ясна проблема)

        По пункту 2: Из любого высокоуровневого языка можно выкинуть любую ограничительную конструкцию с аргументом "мешает". Давайте, например, вернем goto. И будем на Java писать как на ассемблере. Чистый код получится… Да и всё равно почти за всех throws пишет IDE.

        А п.3 — это вообще не аргумент. Надо собственное мнение иметь. Я и в защиту checked exceptions могу привести статьи. И что с того?


        1. Throwable
          07.03.2016 13:26

          Один из аргументов: вы видели десятиэкранные стектрейсы каких-нибудь больших приложений, где эксепшн по десять раз оборачивается и повторяется в Caused by"? При всем при том, что информативные строчки только последняя парочка, какой-нибудь NullPointerException at XXX. Все остальное по большому счету мусор.

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

          С точки зрения логики кода в 99% случаев обработчик не классифицирует эксепшны. Ему вобщем-то пофиг, будет это ConfigParsingException caused by IOException или же сам IOException. Более того, в случаях, где это действительно необходимо, насильное заврапливание эксепшнов делает более трудоемким разбор причины: приходится проходится по всему getCause() и смотреть нет ли причины среди них.

          И, да. Первый пункт. 9 из 10 людей, называющих себя программистави Java не понимают и умеют правильно готовить checked exceptions.


    1. vsb
      07.03.2016 04:06
      +1

      Некоторые факты из практики:

      1. Checked exceptions из распространённых языков присутствуют только в Java. Несмотря на то, что с тех пор вышло много других языков с похожей на Java моделью исключений.
      2. В Java 8 Checked Exceptions де-факто объявлены устаревшими. Из чего я делаю этот вывод? Во-первых лямбды не пробрасывают их, т.е. любой код с Checked Exceptions нужно оборачивать в Unchecked Exception (хотели бы — сделали бы механизм проброса). Во-вторых в JDK введён класс java.io.UncheckedIOException, это уже такой намёк, как бы.
      3. В подавляющем большинстве популярных Java-библиотек нет Checked Exceptions. Включая последние версии Java EE (обратите внимание, как от Checked Exceptions в J2EE перешли к Unchecked Exceptions в JavaEE 5+).

      Поэтому можно утверждать, что Checked Exceptions были только в Java и на практике в современной Java они не используются.

      Я согласен с тем, что место для Checked Exceptions в коде можно найти, при желании. Но не в том виде, в котором они реализованы в Java. Нужен другой синтаксис, больше возможностей для работы с ними (потому что в текущем виде они провоцируют лапшекод). Но тут, я думаю, дело в том, что Kotlin это не экспериментальный язык для обкатки новых идей. Они просто взяли все проверенные временем решения и завернули их в приятную оболочку. Переносить Checked Exceptions в том виде, в котором они есть в Java — ну это просто добровольно наступать на грабли. Пробовать изобретать новые возможности обработки ошибок? Наверное это лучше делать в более исследовательских языках, но никак не в прагматичном языке.


    1. anjensan
      07.03.2016 17:47

      Ну вот Вы сами же и написали, мол рекомендуете просто конвертировать исключения. Проблема в том, что в подовляющем количестве случаев проброс контролируемого исключения в обертке — самое адекватное решение.
      А вспомните про java.util.concurrent.Callable (обратите внимание на throws). Красотень, правда? И таких примеров приличное количество...

      На самом деле с таким же успехом можно убрать автобоксинг. Да, неудобно. Но ведь отсутствие автобоксинга может спасти от невнимательности или плохого знания API. А еще можно усилить типизацию, никаких там преобразований из int в double. Хочешь сложить два числа — преобразуй явно к одному типу! И оператор "+" для строк уберем. А то иногда в цикле используют, а компилятор не в силах к StringBuilder свести...

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


    1. anjensan
      07.03.2016 17:55
      +1

      И в качестве бонуса предлагаю вам такой код:

      class Util {
          @SuppressWarnings("unchecked")
          private static <T extends Throwable> void throwException(Throwable exception, Object dummy) throws T {
              throw (T) exception;
          }
      
          public static void throwException(Throwable exception) {
              Util.<RuntimeException>throwException(exception, null);
          }
      }
      
      public class Test {
          public static void main(String[] args) {
              Util.throwException(new Exception("This is an exception!"));
          }
      }

      Таким образом, любое исключение может к вам прилететь из любого метода. Никаких гарантий JVM по этому поводу вам все равно не дает.