Comments 35
философия Kotlin заключается в доверии большего количества инструментов программисту (по крайней мере, нам так показалось)
Вам показалось. Kotlin создавался как удобный, прагматичный язык, и описанные вами возможности авторы языка посчитали ненужными и отвлекающими от разработки.
Собственно, почему вам не хватает internal
? Да, это область видимости чуть больше, чем package-private
, но и проблем с ним меньше.
А о исключениях можно спорить вечно… Кто-то считает, что обязательно должны быть проверяемые исключения и компилятор должен насиловать мозг на каждый чих, кто-то считает, что исключения — это зло (как минимум, в том виде, какие они в Java). Правда как всегда где-то посередине.
Как мне показалось из статьи, у Вас мозг "отформатирован" под Java и ещё не до конца осознал Kotlin, это всё-таки не просто Java-с-плюшками, это другой язык, хоть у него и хороший интероп с экосистемой Java.
Kotlin создавался как удобный, прагматичный языкА есть серьёзные языки, которые создаются как неудобные, что ли? Проблема в том, что принцип доверия-недоверия разработчику объективен, а удобство — это уже понятие субъективное. Можно либо руководствоваться какими-то принципами при принятие решений при разработке языка, либо нет. Удобство — это не принцип.
область видимости чуть большеЕсли в каждом модуле пара пакетов, тогда «чуть». А если пакетов больше, то тогда уже не «чуть».
это другой языкВ этом другом языке есть проблема, которую я чётко обозначил: язык не позволяет мне понять, где нештатные ситуации могут возникнуть, а где нет. Если авторы придумают, как решить этот вопрос, например, через алгебраические типы данных, тем более что в Kotlin они есть, я ничего против не имею. Например, в Rust это очень хорошо сделано. В Haskell чуть менее в силу того, что язык чисто функциональный.
А вообще скатываться на личные аргументы некрасиво.
А есть серьёзные языки, которые создаются как неудобные, что ли?
Rust и C++ считаются? :)
Дело не в том, что создаются как "неудобные", а в том, что "удобство" это одна из первоочерёдных задач.
А если пакетов больше, то тогда уже не «чуть».
По сравнению с public частью — всё-таки "чуть".
язык не позволяет мне понять, где нештатные ситуации могут возникнуть, а где нет.
Да OOM может вылететь от каждого оператора new, SOE может вылететь от каждого вызова функции — теперь что, оборачивать всю программу в try-catch? Kotlin не отбирает возможность определения throws, как и отлова исключений.
А вообще скатываться на личные аргументы некрасиво.
Вы меня не поняли. Я не скатывался в стиле "ниасилил", я сам через это проходил. После нескольких лет Java Kotlin (особенно до версии 1.0 и в некоторых моментах до 1.1) выглядел… мягко говоря непривычно. Я плевался чуть ли не от каждой фичи, которая была сделана не так, как в Java просто потому, что всё не Java, кроме Java. Я не понимал, почему авторы сделали то-то и то-то, от того отказались, заменили на то-то. Мне понадобилось некоторое время для изучения stdlib и других библиотек чтобы осознать, как стоит писать на Kotlin и почему не надо бездумно копировать практики с Java просто потому, что это тоже JVM язык.
Я же уже объяснил, почему удобство не может быть принципом. Для меня лично, например, Rust — намного более удобный язык для тех задач, для которых он предназначен, чем его альтернативы. В том-то и проблема, лаконичность может быть принципом, явность может быть принципом. Удобство — нет.
По сравнению с public частью — всё-таки "чуть".
А если у меня всего один модуль в проекте в силу каких-то причин? Тогда public
и internal
вообще никак отличаться не будут.
Да OOM может вылететь от каждого оператора new
Это всё ситуации, которые программа не должна обрабатывать. Я же говорю не про них.
я сам через это проходил
Если бы мне было просто непривычно, я бы ругался на гораздо большее, чем эти две особенности. Мне-то как раз Kotlin понравился сразу тем, что можно всё очень лаконично записать, и с функциональными возможностями мне очень комфортно, в частности, благодаря опыту с Rust и Haskell. И пишу я на нём уже давно. Но вот эти две вещи мешали всегда.
«инструмент должен быть удобным в основных целевых сценариях использования» — это полноценный принцип разработки чего угодно, в том числе языка
Это утверждение верно, но оно примерно как теория, которая может описать что угодно. То есть формально теория верна, но предсказательная сила у неё в итоге нулевая. Так и тут: поскольку это верно в отношении всего, то и знание об этом ничего не даёт относительно какого-то конкретного языка.
Мы же говорим не об инструментах вообще, а о языках программирования. Говорили бы мы о таких инструментах, как молоток — я бы всецело согласился.
Минимизация бойлерплейта пойдет как критерий удобства?
Для кого-то да. А кому-то удобнее видеть всё прописанным явно.
В яве эксепшены надо обкладывать бойлерплэйтом
В Java тоже есть выбор: либо обрабатывать, либо объявлять, что твой метод тоже бросает определённые исключения. Другое дело, что бывают кривые API, которые проверяемыми исключениями делают ошибки программиста.
Котлин этого не запрещает делать, и вот ни разу не вынуждает
Верно. Проблема в другом. Я её уже и в статье, и в других комментариях подробно описал.
Я бы ни за один JVM-язык не стал браться без знания Java, а за Kotlin тем более, потому что стандартная библиотека там призвана дополнять стандартную Java, а не заменять её. Но пересесть на Kotlin со знанием Java, мне кажется, нет никакого труда. Правда, если предыдущий опыт был основан на Java 7 и раньше, к функциональным конструкциям придётся какое-то время привыкать.
На самом деле можно учить и Kotlin как первый язык. Но тут встает вопрос как сильно вы готовы абстрагироваться от выполнения самой программы. Скажем когда мы начинаем учить язык программирования нам начинают постепенно вводить понятия: переменные, циклы, классы. И даже если вы их используете как заклинание, без глубокого понимания, программа все-равно работает. Здесь ситуация будет примерно такая-же. Вы будете знать «как», но не будете знать «почему». Если вас это устраивает, то почему-бы и нет.
Но тут есть еще один подводный камень. Язык молодой и призван облегчить жизнь Java-программистов. Поэтому большая часть авторов будет предполагать, что вы пишите на Java и переходите на Kotlin. Если предполагается, что этот так, то большую часть понятий будут не объяснять и обсасывать, а декларировать. Вы знаете как работает try-catch в Java. В Kotlin это работает вот так. Но вы-то не знаете. Готовы через это продираться с учетом того, что в результате все-равно не будете понимать половину кода или таки пойдете коротким путем по изучению сначала Java? Решать вам.
PS: А еще хорошо перед изучением Kotlin почитать Haskell. Хотя это сейчас к большей части языков применимо ;)
Ещё рассказы о Java-инфраструктуре пугают. Вроде достаточно загрузить JDK для разработки и JRE для запуска, но что на глаза не попадётся, то всякие Ant, Maven, Gradle упоминаются вскользь но как «маст хэв», причём по ощущениям даже не в проекте, а где-то сбоку, глобально. В Kotlin с этим как?
Про инфраструктуру. Так-как я пишу на котлине под адроид, то из инфраструктуры мне кроме gradle ничего больше не нужно. Gradle хватает за глаза. Ставим jdk и android studio она подтянет sdk, а gradle у нее в комплекте, и все можно писать. Манипуляций с инфраструктурой не сильно больше чем в любом другом языке.
А о исключениях можно спорить вечно… Кто-то считает, что обязательно должны быть проверяемые исключения и компилятор должен насиловать мозг на каждый чих, кто-то считает, что исключения — это зло (как минимум, в том виде, какие они в Java). Правда как всегда где-то посередине.
Вот моё мнение однозначно, что непроверяемые исключения — это плохо. Я, к слову, лучше всего знаю C# и считаю непроверяемые исключения заодно с их *censored* иерархией наследования главным недостатком C#. В Java по мне главный недостаток в отсутствии возможности объявления структур, хотя в C# есть проблема с их изменением. Последний вопрос по-человечески сделали в Swift, исключения тоже проверяемые, даже есть возможность запрета пустых указателей, но в то же время ест свои, мягко говоря, «особенности». Разве что в 5-м Swift что-то исправят, хотя б абстрактные классы добавят. К слову в Swift и варианта protected нет, вот это по мне по-настоящему неудобно.
Используя протоколы, можно со спокойной совестью забыть об использовании protected
И как они помогут сделать override, не делая метод открытым для всех? Хорошо, конечно, что в них можно объявлять и конструкторы в отличие от интерфейсов в C#, но по мне что уж они точно не заменяют — так это абстрактные классы. Точнее заменить можно, но иногда это настолько громоздко, что я предпочитаю писать такую фигню:
var price: Int? {
return nil;//pseudo-abstract
}
надеясь, что в 5-м Swift или позже абстрактные классы всё ж будут. Ибо иногда получается, что едва ли не на каждое абстрактное свойство пришлось б создавать протокол.
Тем, что класс обладает функциями не благодаря наследованию(где и используют protected), а тем, что наследует протоколы.
Жаль, сейчас уже не могу найти ту страницу о возможном появлении абстрактных классов в Swift, с тех пор об этом написано слишком много белиберды, а Google ещё не научился отличать дельную информацию от белиберды.
github.com/JetBrains/kotlin-native/issues/733
А просвета на самом деле нет, как и в jruby, грузится несколько тысяч классов, похоже, поэтому так медленно. Упреждаю комментарии про IDE и инкрементальную сборку — речь идет о TDD. Запускается 1 тест c нуля. Прелоадеры — тоже, со времен ruby/jruby считаю, что проблем от них больше, чем пользы.
- Пакетов нет в во второй платформе, в которую компилируется Kotlin — это JavaScript
- Там же нет и проверяемых исключений
- В самой JVM исключения тоже не делятся на проверяемые и непроверяемые, это фича только языка.
- Более того, есть "хаки", позволяющие выкинуть проверяемое исключение из метода, в котором оно не объявлено.
- И вообще, работая с JVM надо быть готовым к тому, что исключение может выкинуться из абсолютно любой точки выполнения. Это прописано в спецификации. Поэтому try-catch-finally надо писать не "для галочки", а там где реально надо сделить за потоком выполнения.
- Не знаю, сколько времени вы потратили на написание статьи, но разработчки Kotlin потратили на исследования и обсуждения не один год. Всем фичам языка там есть своя веская причина, правда, это далеко не всегда документировано.
Пакетов нет в во второй платформе
А чем их отсутствие в JS мешает проверять область видимости при компиляции Kotlin?
Там же нет и проверяемых исключений
Но если "это фича только языка", опять же, почему тогда они должны поддерживаться в JS?
Поэтому try-catch-finally надо писать не "для галочки", а там где реально надо сделить за потоком выполнения.
Верно, но вот как мне понять, где именно такие места находятся? И какого рода проблемы могут возникнуть, чтобы правильно написать обрабатывающий код? Иногда это очевидно, иногда нет.
Не знаю, сколько времени вы потратили на написание статьи
При чём тут написание статьи? Я использую инструмент, которым трудно решить определённые проблемы, и я их описал. А "годы исследований и обсуждений" — это, по сути, апелляция к авторитету.
Естественно, я не знаю так, как авторы языка, какие последствия повлёк бы тот или иной выбор. Но объяснение всё-таки хочется увидеть грамотное, а не основанное на избирательном цитировании известного автора и притянутом за уши примере. И хочется иметь какую-то альтернативное решение проблемы, раз авторы считают, что старое не годится.
можно сделать так, чтобы метод был виден наследникам, как в своём пакете, так и вне пакета (protected)Не совсем так. Protected это видимость для всех внутри пакета и для наследников в других пакетах.
Мне тоже не хватает package private.
Всё-таки мне кажется, что удобно разделять подсистемы по пакетам и скрывать детали их реализации, выставив для других частей приложения чёткий интерфейс и спрятав то, что напрямую использовать не следует.
Создавать 10-20 модулей в приложении только ради этого — не решение.
И аргумент создателей о том, что пакеты не защищены от добавления левых классов в другом модуле, не очень убедителен — это бросается в глаза и нельзя сделать случайно (и вряд ли так кто-то будет делать без веской причины). Чего не скажешь об использовании классов из соседнего пакета, которые для этого не предназначены.
Видимость внутри модуля — очень полезная вещь для библиотек. Но и видимость внутри пакета тоже нужна.
аргумент создателей о том, что пакеты не защищены от добавления левых классов в другом модуле, не очень убедителен
Да и не актуален начиная с Java 9. Один модуль не может подложить классы в те же пакеты другому модулю. Поэтому, кстати, JetBrains и заменили kotlin-stdlib-jre7 и kotlin-stdlib-jre8 на kotlin-stdlib-jdk7 и kotlin-stdlib-jdk8: в первых двух один и тот же пакет был в обеих библиотеках.
Kotlin: две ложки дегтя в бочке меда