Привет, хабр! Сегодня я хочу рассказать про свой опыт взаимодействия с языком kotlin.

Представлюсь – я java разработчик, работаю крупном банке, создаю (и поддерживаю существующие) микросервисы.

Небольшая ремарка: я не собираюсь становиться Android разработчиком, ни сейчас, ни в будущем, поэтому, когда я заинтересовался новым языком, не принимал в расчет аргументы про различные удобства мобильной разработки на нем, и руководствовался только удобством языка в целом для бэкэнда.

Итак, почему я решил изучить kotlin. Ну, во-первых, прожужали все уши, мол сокращение объема код, лаконичность, читаемость и сахар.

Во-вторых, Kotlin полностью совместим с Java. Для понимания, ниже скриншот того, как выглядит содержание одного из пакетов intellij плагина git4idea:

кусок структуры исходников плагина git4idea
кусок структуры исходников плагина git4idea

(Java и Kotlin классы идут вперемешку, код при этом остается читаемым (местами))

Да, проекты можно мигрировать с Java на Kotlin постепенно, как по мне – киллер-фича.

Так что, я подумал, почему бы и нет.

Вот вещи, к которым я привык за свои полгода пет-проектирования на kotlin, и которыми лично мне удобно пользоваться:

  1. Закрытые для расширения классы и методы. Все по умолчанию final, в отличии от Java, где, наоборот, любой класс открыт для расширения. Kotlin же придерживается принципа, описанного еще в Effective Java Дж.Блоха, который звучит так:

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

    Для того, чтобы сделать класс в kotlin расширяемым, мы должны использовать ключевое слово open, которое не обладает транзитивным свойством – это означает, что когда Class2 наследуется от open class Class1, мы не сможем унаследовать Class3 от Class2, без навешивания на него ключевого слова open.

  2. Null-safe. Возможность на уровне компиляции разрешить/запретить(по умолчанию) присвоение null в переменную – лайк.

    var a: String = "abc"
    a = null                // compile error
    
    var b: String? = "xyz"
    b = null                // no problem

  3. Геттеры и сеттеры по умолчанию. Любое поле не извлекается напрямую, более того под капотом оно является private(по умолчанию) и может быть доступно только геттеру. Когда вы пытаетесь получить поле вашего объекта, вы на самом деле вызываете метод get

    val isEmpty: Boolean

    эквивалентно следующему Java коду:

    private final Boolean isEmpty;
    
    public Boolean isEmpty() {
        return isEmpty;
    }

    Ну, и:

    var someProperty: String = "defaultValue"

    также эквивалентно:

     var someProperty: String = "defaultValue"
        get() = field
        set(value) { field = value }

    При желании, разумеется, можно ограничить доступ к геттерам или сеттерам:

     var isEmpty: Boolean = true
        private set 

    Примеры скоммуниздил

  4. Однострочные методы. Буду краток : при объявлении метода вида:

     fun doSomething(): String{
        return “doing something”
    } 

    Kotlin позволяет убрать явное объявление возвращаемого типа, фигурные скобки и ключевое слово return

    Выглядеть это начинает следующим образом:

     fun doSomething() = “doing something”

    Сначала было непривычно (особенно когда такие объявления идут после блока инициализации полей класса), но потом привык

  5. Упрощена большая вложенность при сравнении строк и любых других сложных типов в If - чуваки зашили equals в  == (начинает работать, если переопределить метод equals явно, либо если пометить класс ключевым словом data.)

    Добавлю, что если уж вам нужно сравнить именно ссылки на объекты, в kotlin есть отдельный оператор для этого: тройное равно ===

    Java:

     if (str1.equals(str2.equals(errString)? "default":str2)){
         //... 
     }

    Kotlin:

     if (str1 == if (str2 == errString) "default" else str2) {
       //... 
     }

    Сравнение объектов на равенство:

    Java:

    @EqualsAndHashCode
    @AllArgsConstructor
    public class MyClass {
       private String name;
       private int value;
     }
    
     
    public static void main(String[] args) {
      MyClass first = new MyClass("name", 5);
      MyClass second = new MyClass("name", 5);
      System.out.println(first.equals(second));//true
      System.out.println(first == second);//false 
    }

    Kotlin:

    data class MyClassK(var name: String?, var value: Int)
    
    fun main() {
      val first = MyClassK("name",10)
      val second = MyClassK("name",10)
      println(first == second)//true
      println(first === second)//false
    }

                  

  6. Именованные аргументы. В сочетании с аргументами по умолчанию именованные аргументы избавляют от необходимости использовать Строителей (паттерн Builder)

    Вместо следующего Java-кода:

    @Builder //lombok annotation
    public class MyClass {
      private String name;
      private int value;
      private double rating;
    }
    
    MyClass myClass = MyClass.builder()
       .name("MyJavaObj")
       .value(10)
       .rating(4.99f)
       .build();

    На kotlin мы можем сделать так:

    class MyClassK(name: String? = null, value: Int = 0, rating:Double = 0.0)
    
    fun main() {
      var myClassK = MyClassK(value = 10, name = "MyKotlinObj", rating = 4.99)
    } 

  7. Перегрузка операторов (Operator Overloading)

    В kotlin заранее определен набор операторов, которые можно перегружать для улучшения читабельности:

    data class Vec(val x: Float, val y: Float) {
        operator fun plus(v: Vec) = Vec(x + v.x, y + v.y)
    }
    
    val v = Vec(2f, 3f) + Vec(4f, 1f)

     пример позаимствован отсюда

  8. Функции-расширения (Extension Functions)

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

    fun String.format() = this.replace(' ', '_')
    
    val str = "hello world"
    val formatted = str.format()

    или, например:

     val result = str.removeSuffix(".txt")

    (В java я бы вынес это в статический метод какого-нибудь класса StringUtils)

    Удобно, не так ли? Тем более что IDE подсказывает нашу функцию среди прочих всплывающих.

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

    Java:

     try{
       Status status = journal.getLog().getRow(0).getStatus();
       if(status == null)
         throw new NullPointerException(“null status detected in log”);
     } catch(NullPointerException e){
       status == Status.ERROR;
       //logger.error(“Journal is not correct”);
     }

    Kotlin:

    var status: Status? = journal?.log?.row?.status
    status  =  status ?: Status.ERROR

    либо

    var status: Status? = journal?.log?.row?.status
    if(status.isNull()){
      status  = Status.ERROR
      logger.error(“Journal is not correct”)
    }

    Как же это прекрасно, что теперь я могу не бояться NPE в цепочке вызовов. В Java, как можно видеть, приходится оборачивать небезопасную цепочку вызовов в громоздкий try-cath, но черт побери, иногда я хочу, чтобы при возврате null где-то в цепочке, в переменную просто присваивался null. Именно этот функционал мне и дает kotlin.

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

Лирическое завершение:

Вообще нахожусь в больших раздумьях насчет языка: я очень долго программирую на Java и она мне, как то роднее, что ли.
(Когда вижу в проекте файлы с функциями, отдельно от классов, периодически дергаюсь.)

Много нюансов и изменений, как ни крути, хотя и совместимость.
Слушал недавно несколько подкастов с гостями – разработчиками и продактами JetBrains, ребята так увлеченно рассказывали про язык, его перспективы и горизонты, мол как Java, только лучше, Kotlin Multiplatform и тд.

Но все-таки остается фактом, что массово kotlin в бэкэнд не пошел, а занял нишу мобилок, хотя может это я чего-то не знаю. Может за моей спиной в проде все тайно уже переписали свои жаба проекты на kotlin, а мне не сказали.

Да и вообще есть ли такое понятие, как основной язык? Может не надо так к этому относиться, а придерживаться принципа «под каждую задачу свой инструмент». Но тогда под какие задачи бэкэнда kotlin, а под какие java? Или все-таки “прокачанная java”?

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

Был ли опыт миграции больших проектов с одного языка на другой? Если да, то какой? Если нет, то почему?

Может вы поменяли лично свой основной язык? Почему? Сахар и отсутствие точек с запятой? Или более глобальные причины?
(Пришла в голову мысль, что мне синтаксический сахар не кажется киллер-фичей какого-либо языка, ведь когда ты привык писать так, а другие привыкли так читать, это перестает быть проблемой)

Источники:

https://habr.com/ru/companies/otus/articles/532270/ - Проверка на равенство в Kotlin

https://youtu.be/rB5Q3y73FTo?si=piObKnscuv1S9vtg – Роман Елизаров. Корутины в kotlin

https://habr.com/ru/companies/vk/articles/329294/ - обзор фич kotlin от ВК

https://stackoverflow.com/questions/37906607/getters-and-setters-in-kotlin - геттеры и сеттеры. Тред на Stack Overflow

https://www.baeldung.com/kotlin/open-keyword - ключевое слово open

https://github.com/amitshekhariitbhu/from-java-to-kotlin - прикольный репо-обучалка в формате Java vs Kotlin

https://radioprog.ru/category/183 - паттерны проектирования, без воды и шелухи

 

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


  1. TerraV
    06.09.2024 21:15
    +20

    Но все-таки остается фактом, что массово kotlin в бэкэнд не пошел, а занял нишу мобилок, хотя может это я чего-то не знаю. Может за моей спиной в проде все тайно уже переписали свои жаба проекты на kotlin, а мне не сказали.

    Kotlin используется во множестве энтерпрайз компаний в качестве бэкенд языка. Знаю множество компаний в банковской сфере в Европе которые плавно переходят на Kotlin (плавно это значит начали лет 3-5 назад). В плане что java остается в Book of Standards как разрешенный инструмент, но рекомендуется к использованию Kotlin (whitelist).

    Как разработчик, который использует Kotlin 7+ лет, я могу сказать что на данный момент Kotlin не имеет принципиальных преимуществ перед Java. Да, где-то больше сахара. Да, функции расширения местами очень удобны. Да, писать свой dsl гораздо легче на Kotlin. Но каждый из этих аргументов довольно узкий.

    В целом Котлин дал мощный пинок под зад Джаве и заставил развиваться. Та же nullability на аннотация которая сейчас приходит в Java к единому стандарту это последствие влияния Kotlin.


    1. ermadmi78
      06.09.2024 21:15

      Для меня в своё время основным аргументом перехода на Kotlin стали корутины. И до сих пор я корутины считаю стратегическим преимуществом Kotlin'а. И даже Project Loom здесь ситуацию не меняет. Project Loom это про многопоточность. А корутины это про императивную асинхронность. Как говорится - не путайте тёплое с мягким.


      1. TerraV
        06.09.2024 21:15
        +2

        Корутины очень мало кто умеет правильно готовить. Как правило я вижу просто обертку runBlocking, на чем собственно преимущества и заканчиваются. Я ни в коем случае не применительно к вам, я скорее в "среднем по больнице".


        1. ermadmi78
          06.09.2024 21:15

          Да, согласен - есть такая болезнь :( Нужно нести культуру в массы...

          Но, справедливости ради хочу сказать, что когда вышла революционная Java 5.0, и вместе с ней Java Memory Model, то её тоже долгое время не умели готовить. Ни один год прошёл, прежде чем JMM стала повседневной обыденностью.


        1. september669
          06.09.2024 21:15
          +1

          Сходите в гости к мобильным разрабам, там за runBlocking часто бьют по рукам :)


      1. youngmyn Автор
        06.09.2024 21:15

        Я что-то не понимаю, или lombok - это не многопоточность? На моей памяти был библиотекой для сокращения количества бойлер-плейт кода)


        1. ermadmi78
          06.09.2024 21:15
          +1

          :))) Sorry, засыпаю и ересь пишу :) Речь конечно же шла про Project Loom. Поправил комментарий. Спасибо!


      1. Lewigh
        06.09.2024 21:15
        +2

        Project Loom это про многопоточность.

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


        1. ermadmi78
          06.09.2024 21:15

          Ох, не буду спорить. Это как спор между тупоконечниками и остроконечниками :) Можно до хрипоты ругаться, при этом обе стороны будут правы и одновременно не правы:)


      1. pin2t
        06.09.2024 21:15

        Тут есть важный момент. Многопоточную программу гораздо проще написать корректно, чем императивно асинхронную. Именно поэтому Project Loom меняет ситуацию очень сильно. Там где раньше программисты были вынуждены использовать императивную асинхронность для повышения эффективности, теперь достаточно запустить на JVM последней версии. И существующий многопоточный код становится более эффективным.
        Project Loom слишком долго делали, его надо было запускать еще 10 лет назад.


      1. breninsul
        06.09.2024 21:15
        +1

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

        С виртуальными потоками же мы шпарим новый вирт. поток на каждый чих, вешаем локи куда надо и ни про что не паримся


        1. aleksandy
          06.09.2024 21:15
          +4

          и ни про что не паримся

          Действительно, зачем заморачиваться?


          1. breninsul
            06.09.2024 21:15

            1) Я писал про локи, а не блоки синхронизации (не просто так). Я всегда предпочитал семафоры/локи блокам синхронизации, по этому проблем не испытываю.

            2) Это , вероятно, скоро полечат

            3) В корутинах ситуация с блоками синхронизации не лучше, а точнее хуже. Точнее нужно использовать другие примитивы синхронизации, что гораздо больше ломает совместимость со сторонним кодом.

            По этому да, фигачим вирт. потоки и локи на каждый чих и ни про что не паримся.


            1. ermadmi78
              06.09.2024 21:15
              +2

              Святая наивность :)


              1. xhumanoid
                06.09.2024 21:15

                не наивность, а реальность

                https://openjdk.org/jeps/8337395

                в тестовых билдах самого loom уже с февраля как есть, с высокой вероятностью войдёт в мартовский релиз


    1. ris58h
      06.09.2024 21:15
      +3

      Kotlin не имеет принципиальных преимуществ перед Java

      Nullability - это всё ещё принципиальное преимущество перед Java. Было бы оно в Java, я б на Kotlin даже не смотрел бы. Аннотации - костыль, который приходится использовать.


      1. xhumanoid
        06.09.2024 21:15
        +1

        как следующий этап развития валхалы и это тоже присутствует

        https://openjdk.org/jeps/8303099

        пока рано говорить про то когда появится в проде, но если сама valhalla в бранче lworld в основном фиксят оставшиеся вопросы с поддержками JIT C2 и юниттесты. то в бранче lw5 идёт активная работа над nullability

        https://github.com/openjdk/valhalla/commits/lw5

        In Java syntax, a nullness marker is used to indicate this property.
        The type Foo! is null-restricted: the value set excludes null.
        The type Foo? is nullable: the value set deliberately includes null.
        By default, the nullness of the type Foo is unspecified: a null may occur, but we don't know whether its presence is deliberate.

        In this JEP, nullness markers are explicit: to express a null-restricted or nullable type, the ! or ? symbol must appear in source. In the future, it may be useful, for example, for a programmer to somehow express that every type in a class or compilation unit is to be interpreted as null-restricted, unless a ? symbol is present. The details of any such a feature will be explored separately.

        конкретно от этого jep зависит работа ещё нескольких, поэтому работа идёт


  1. ermadmi78
    06.09.2024 21:15
    +7

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

    (Когда вижу в проекте файлы с функциями, отдельно от классов, периодически дергаюсь.)

    Я 18 лет программировал на Java. Последние 5 лет пишу на Kotlin. И возвращаться обратно не собираюсь. Java люблю и уважаю, но для меня она как раритетный автомобиль. Изредка выгнать из гаража, покрасоваться, потусить с такими же ценителями старины. Но в повседневной жизни предпочитаю Kotlin.

    Но все-таки остается фактом, что массово kotlin в бэкэнд не пошел, а занял нишу мобилок, хотя может это я чего-то не знаю. Может за моей спиной в проде все тайно уже переписали свои жаба проекты на kotlin, а мне не сказали.

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


  1. LedIndicator
    06.09.2024 21:15
    +6

    К Котлину равнодушен, в качестве «прокачанной Жавы» (и вообще любимый язык) предпочитаю Скалу, но если вы пишете кровавые бэкенды для JVM, то желательно знать и то и другое и пятое десятое. Плюс кафка, кубер, докер и т.д и т.п.

    Для общего развития, во-первых, а во-вторых можно внезапно попасть на проект где есть и Жаба и Котлин и Скала и градл скрипты на Груви.

    Да и вообще есть ли такое понятие, как основной язык? Может не надо так к этому относиться, а придерживаться принципа «под каждую задачу свой инструмент».

    Я с годами как-то перестал думать в категориях «основного языка». На чём надо на том и пишу. JVM-бэкенд можно наколбасить на чём угодно, в общем. Вопрос вкуса.

    Мой банк работодатель (UBS) больше ориентируется на Скалу (и правильно делает, имхо). На прошлом проекте был фанат Котлина, писавший всякие компоненты, утилиты и пр, но уволился, и Котлин в проекте зачах.

    Пришла в голову мысль, что мне синтаксический сахар не кажется киллер-фичей какого-либо языка, ведь когда ты привык писать так, а другие привыкли так читать, это перестает быть проблемой

    В общем, да. Точки с запятой и прочий синтаксис это ерунда. Мне не лень и ресурса клавиатуры не жалко лишние пару символов дописать, тем более всё равно за меня большую часть автодополнение пишет. Главное в языке это какие-то функциональные преимущества, безопасность, ограниченность стрельбы по своей ноге и всякое такое.


    1. Anarchist
      06.09.2024 21:15
      +1

      Неистово плюсую. Котлин по ощущениям занимает промежуточное положение между Java и Scala.


    1. KarlKremen
      06.09.2024 21:15

      (удалено)


  1. andrey_27
    06.09.2024 21:15
    +3

    А про минусы чего не сказали?)

    Я так не люблю Котлин. Да, есть пара нереально удобных свистоперделок, но зачем-то разработчики в одном месте уменьшают код/усилия, а в другом наоборот увеличивают, что просто бесит нереально. Многие решения довольно спорные, кому-то удобны - кому-то наоборот вредительны. Вроде и хочется использовать те крутые нововведения, но отрицательная сторона как по мне побольше будет, только затормозит и выбесит меня(


    1. a_beacon
      06.09.2024 21:15
      +5

      Какие конкретно минусы у Котлин с вашей точки зрения?


      1. andrey_27
        06.09.2024 21:15
        +1

        • Множество кода превращается в кашу, выдавая слишком много информации на одну строку. Становится сложно ориентироваться с потоке всех сокращений, а ведь Джава славится своей понятной и удобной структурой, расставляя все по полочкам.

        • Null-safety нужно не всем. Тем более её пытаются засунуть в язык, где уже исторически используется null повсеместно, это только усложняет работу с ним.

        • Закрытые для расширения классы тормозят процесс. Расширяемость в Java - преимущество, а не проблема.

        • Лично для меня - неудобное определение переменных. Кто вообще додумался до двоеточия между названием и типом переменной??? Так оно ещё и требует больше действий, т.к. двоеточие ставится через шифт

        • Каша со сравнением классов: в Джаве четкое и понятное разделение на == и equals, что очень удобно. В Котлтне же появляется ещё и третье равно. Рабочая и логичная система просто заменена на отсебятину.

        • Неудобства с классами: хоть сам язык и совместим с Java, но kotlin-класс это не java-класс, .javaClass и .kotlin приходится обрабатывать раздельно.

        • Есть ещё разные штуки по мелочи, уже не вспомню


        1. KarlKremen
          06.09.2024 21:15
          +5

          Вот хоть убейте меня, я даже близко представить не могу, где null-safety может помешать (по крайней мере null-safety в том виде, в котором оно сделано в kotlin). Null ведь оттуда никто не выкидывал, напротив, благодаря null-safety его стало удобнее и безопаснее использовать.


          1. aleksandy
            06.09.2024 21:15

            Скорее всего, речь идёт о работе на стыке Котлина с Явой.


          1. andrey_27
            06.09.2024 21:15

            Лично мне не нравится разделение на null-able переменные. В Джаве ты делаешь ТОЛЬКО проверку на null, в котлине ты и переменную делаешь особенную, и проверку. Но синтаксис проверки и правда очень удобен в Котлине.

            Опять же, речь про мой опыт, но меня жутко выбесили постоянные проблемы при работе с кодом в духе "укажи ? чтобы туда можно было совать null" и "делай проверку на null". А всё из-за того, что язык действительно ругает тебя за использование null, потому что вся позиция JetBrains в том, чтобы избавиться от них. Но это буквально невозможно (и не всем нужно, ведь null это тоже определенный статус объекта).


            1. ris58h
              06.09.2024 21:15
              +1

              Но это буквально невозможно (и не всем нужно, ведь null это тоже определенный статус объекта).

              Возможно. Это вам не хочется этого делать, по каким-то причинам.


              1. andrey_27
                06.09.2024 21:15
                +1

                Невозможно, потому что даже если писать на Котлине, будешь использовать популярные библиотеки Джавы. Будешь использовать нативные классы Джавы. Экосистема совершенно не предусматривает отсутствие null вот и всё. Да и не то чтобы это было необходимо, как по мне.


                1. ris58h
                  06.09.2024 21:15

                  Невозможно, потому что даже если писать на Котлине, будешь использовать популярные библиотеки Джавы. 

                  Как вы, используя библиотеки Java из Java, определяете, где может быть null, а где нет?


                  1. andrey_27
                    06.09.2024 21:15

                    Суть то в том, что это не обязательно делать. Можно повесить `@NonNull` или `@Nullable` - если хочешь, но код будет работать и без этого. Никаких обязательств. Допустим, я пишу свою программу и знаю, что и как. Почему я должен париться насчет этого, когда могу просто напросто забить на null-чеки? В Котлине же меняется переменная и вдобавок к этому необходимо явно указать, что переменная не null, если она была nullable. Изобилие обязательств в виде вопросительных и восклицательных знаков как раз и напрягает.


                    1. ris58h
                      06.09.2024 21:15
                      +6

                      Изобилие обязательств в виде вопросительных и восклицательных знаков как раз и напрягает.

                      Посмеялся. Типизация-то не напрягает?


        1. Sipaha
          06.09.2024 21:15
          +8

          Множество кода превращается в кашу, выдавая слишком много информации на одну строку.

          Наговнокодить можно и в java. В чем здесь вина kotlin?

          Null-safety нужно не всем.

          Null References очень часто называют The Billion Dollar Mistake. Kotlin помогает свести шанс этих ошибок к минимуму. Почему это плохо? Да, это заставляет разрабочика каждый раз задумываться "а может ли тут быть null? И если да, то что это значит?" и это может быть неприятно на первых порах (мозг по своей природе думать вообще не любит), но по итогу что лучше - чуть меньшее время разработчика (что спорно т.к. куда больше время тратится потом на отлов и фикс багов) или безошибочная работа программы?

          Закрытые для расширения классы тормозят процесс. Расширяемость в Java - преимущество, а не проблема.

          Откройте для себя композицию и мир заиграет новыми красками.

          Лично для меня - неудобное определение переменных.

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

          Каша со сравнением классов: в Джаве четкое и понятное разделение на == и equals, что очень удобно.

          Потому что вы так привыкли. В том же C# '==' вызывает equals под капотом как и в Kotlin. В 95% сравнение ссылок никому не нужно и заставлять всех каждый раз писать equals, вызов которого может еще и привести к NullPointerException - это тот еще цирк с конями. Есть конечно Objects.equals, но это уже какие-то костыли для решения проблемы, которой изначально быть не должно.

          Неудобства с классами

          А в каких сценариях это неудобство проявляется?

          Я не считаю kotlin идеальным языком, но все его недостатки обычно достаточно мелкие, а плюсы ооочень весомые. Используем его для enterprise без всяких мобилок и живем отлично.


          1. youngmyn Автор
            06.09.2024 21:15
            +2

            Про null references и equals - подписываюсь под каждым словом.


          1. andrey_27
            06.09.2024 21:15

            Наговнокодить можно и в java. В чем здесь вина kotlin?

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

            что лучше - чуть меньшее время разработчика (что спорно т.к. куда больше время тратится потом на отлов и фикс багов) или безошибочная работа программы

            Лучше или нет - совсем другой вопрос. Я говорил об удобстве для себя, потому что я программирую не ради идеальной программы, а ради удовольствия. Эта возня вызывает лишь негативные эмоции.

            Откройте для себя композицию

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

            Да, на первых порах ооочень непривычно, но спустя некоторое время это воспринимается так же естественно как и в java.

            Привыкнуть и не замечать можно и запах канализации в подъезде, привычка не доказывает ничего.

            Почему нажатие шифт в этом кейсе проблема

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

            В том же C# '==' вызывает equals под капотом как и в Kotlin

            Это всё создает огромную путаницу, особенно в контексте нескольких языков. Теперь в Котлине есть и ==, и === и equals и Objects.equals. Причем Java и Kotlin довольно близкие языки, но по-глупому разнятся иногда. Просто взять и поменять местами смысл одного из самых частых операторов - немыслимо, особенно учитывая то, что часто можно видеть комбинированные проекты либо в процессе перехода на Котлин.

            А в каких сценариях это неудобство проявляется?

            MyClass::class.java

            Сразу видно, язык делает проще и удобнее, правда? Нет...


            1. youngmyn Автор
              06.09.2024 21:15
              +8

              Откройте для себя композицию.

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

              На этом моменте я заплакал


            1. Sipaha
              06.09.2024 21:15
              +4

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

              Без примера все же сложно понять о чем речь.

              Лучше или нет - совсем другой вопрос. Я говорил об удобстве для себя, потому что я программирую не ради идеальной программы, а ради удовольствия.

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

              Откройте для себя композицию

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

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

              Лично для меня - неудобное определение переменных.

              Привыкнуть и не замечать можно и запах канализации в подъезде, привычка не доказывает ничего.

              Вы исходите из позиции "это точно плохо и не нужно привыкать к плохому", но у вас нет аргументов в пользу утверждения того что это плохо.

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

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

              Это всё создает огромную путаницу, особенно в контексте нескольких языков. 

              Путаницу как раз ввела java в свое время сделав оператор == практически бесполезным в большинстве случаев. В kotlin исправили эту проблему и большое им спасибо за это. Если сравнение ссылок кому-то действительно нужно, то это обычно продвинутые разработчики, которые в состоянии выбрать подходящий оператор в нужном месте.

              MyClass::class.java

              Если здесь проблема в количестве символов, то странно слышать такие аргументы при сравнении с java, которая не славится краткостью. Если вы копнете глубже в рефлексию и возможности, которые предоставляют Kotlin типы и классы, то поймете почему они решили сделать свои варианты классов.


              1. andrey_27
                06.09.2024 21:15

                Если вы копнете глубже в рефлексию и возможности, которые предоставляют Kotlin типы и классы, то поймете почему они решили сделать свои варианты классов

                Мне без разницы почему так вышло, есть финальный результат этого решения - моё неудобство. И я лишь говорю об этом. Я не говорю, что это неправильно или так делать нельзя, просто говорю, что для меня это минус.

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

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

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

                Наследование то костыль?) Сходите в дурку, пожалуйста, на обследование

                Вы исходите из позиции "это точно плохо и не нужно привыкать к плохому", но у вас нет аргументов в пользу утверждения того что это плохо.

                Я сказал, что это неудобно, а не плохо

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

                Программист - кто постоянно жмет кнопки клавиатуры, и без этого миллион нажатий надо делать. Для чего еще больше? А вот просто так... Суть то не в том, что это мелочь, так и есть, но ради непонятно чего сделали СЛОЖНЕЕ, хотя язык стремится сделать проще. Парадокс. Потому я не люблю котлин, язык контрастов.

                Путаницу как раз ввела java в свое время сделав оператор == практически бесполезным в большинстве случаев. В kotlin исправили эту проблему и большое им спасибо за это. Если сравнение ссылок кому-то действительно нужно, то это обычно продвинутые разработчики, которые в состоянии выбрать подходящий оператор в нужном месте.

                Путаницы в Джаве нет, потому что Джава для Котлина как основа, не наоборот. А в Котлине поменяли смысл целого оператора на противоположный, что само по себе глупо. Так еще и третий добавили, при всем при том, что оригинальные методы от Джавы тоже работают. В результате имеем несколько вариантов сравнения, которые повторяют смысл друг друга, один из них имеет противоположный смысл с "материнским" языком, а третий имеет другой смысл в сравнении с другими языками в целом (=== всегда проверял не ссылку, а идентичность типов + equals).

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

                Так вы сами и подтверждаете по сути еще один парадокс, когда в языке ждя краткости сделано не кратко.


                1. youngmyn Автор
                  06.09.2024 21:15

                  Наследование то костыль?) Сходите в дурку, пожалуйста, на обследование

                  Подозреваю, что эта фраза была лишь саркастической калькой на вашу цитату про композицию.

                  А в общем и целом, кому то удобно, кому то нет, но вы сами говорите:

                  Я сказал, что это неудобно, а не плохо

                  А я скажу, что мне удобно, например.

                  /discuss


                1. gBear
                  06.09.2024 21:15

                  Путаницы в Джаве нет, потому что Джава для Котлина как основа, не наоборот.

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

                  Несравнимо большее влияние на синтаксис Kotlin - по словам самого Бреслава - оказал "ML (через Scala)" - все вот эти "постфиксы", val'ы и прочие fun'ы - это как раз оттуда. Один из первых "лозунгов" Kotlin, емнип, как раз и было: "Лучше чем Java. Проще чем Scala".

                  По факту, единственное, что сейчас связывает Kotlin и Java - это интероперабельность и, собственно, JVM.

                  Ну а Kotlin - уже далеко не только (да и не столько) JVM.

                  P.S. По личным наблюдениям, раздражение от "не так, как в Java" возникает только у тех, у кого в background'е, собственно, только Java и есть. Для тех, для кого Kotlin не второй ЯП - с этим проблем вообще нет никаких.


            1. panzerfaust
              06.09.2024 21:15
              +4

              Был такой советский мультик "Баба Яга против". Эта фраза там повторялась рефреном. Вот читая эту ветку, я его и вспомнил. Аргументы детские и натянутые. Кого в здравом уме они могут в чем-то убедить, я даже представить не могу. Это как ругать машины BMW за то, что у них на логотипе есть синий цвет, а вы как раз не любите синий.

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


              1. andrey_27
                06.09.2024 21:15
                +1

                Это как ругать машины BMW за то, что у них на логотипе есть синий цвет, а вы как раз не любите синий.

                Так для меня это будет минусом при выборе машины, очевидно.

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


                1. panzerfaust
                  06.09.2024 21:15
                  +1

                  Я же не навязываю вам свое мнение, я лишь рассказал о том, какие моменты меня выбесили при работе с языком

                  Вы непоследовательны. Вы влезли в спор о дизайне языка, имея из аргументов только вкусовщину. Вам на это указывают и вы теперь "ой, да я просто высказал мнение". Классика.


        1. JustSokol
          06.09.2024 21:15

          Это не минусы Котлин. Это вы просто не привыкли.


          1. andrey_27
            06.09.2024 21:15

            Привыкнуть ко всему можно, вопрос не в привычке, а УДОБНО ЛИ. Ответ нет.


  1. panzerfaust
    06.09.2024 21:15
    +5

    Функции-расширения (Extension Functions)

    На 8 месте? Это на первом должно быть вместе с элвис-оператором. 2 эти штуки как раз и дают возможность писать короче. Без расширений не было бы

    • функции let, run, also, appy

    • полезных функторов на стандартных коллекциях

    • красивых DSL с labmds with receiver

    • возможности почти любой код написать в виде цепочки fluent api

    Был ли опыт миграции больших проектов с одного языка на другой? Если да, то какой? Если нет, то почему?

    Вытаскивал из джавового монолита микросервис на 50к строк с переводом на котлин. Мигратор Intellij IDEA делает 90% работы. Лишь чуть подправлять типы за ним надо.

    Про котлин в бэкенде уже сказали выше. Уже в третьей организации подряд пишу на котлине. Проблем с поиском не было.


  1. VaVM
    06.09.2024 21:15

    Автору: в тексте должно быть не "Сравнение классов:", а "Сравнение объектов на равенство (по содержанию и по адресу ссылки):"


    1. youngmyn Автор
      06.09.2024 21:15

      Благодарю, поправил.


  1. navrotski
    06.09.2024 21:15
    +2

    kotlin на бекэнде вполне себе ок, проверено лично в разных проектах. особенно если иметь в виду, что intellij насчёт java нигде в документации не использует слово совместимость (compatibility), они пишут interoperability.


  1. Anarchist
    06.09.2024 21:15
    +4

    Я так понимаю, уже отдельные части Spring пишутся на Котлине. Так что в бекенде он может быть шире, чем кажется.


    1. TerraV
      06.09.2024 21:15
      +1

      Был комментарий от лид мейнтенера Spring, что они очень довольны тем что интегрировали Kotlin в Spring (это было еще во времена Spring Boot 2.x). Он говорил что это в том числе улучшило дизайн Spring Boot 3 и повысило качество кода. К сожалению не храню ссылки на такие материалы, придется искать если интересно.


  1. xoraxax
    06.09.2024 21:15

    Был на одном проекте. Сложная кривая система, написанная на скале. Т.к. в компании скалу никто не знал, проект отдали котлинистам. Эти люди переписали зачем-то репозитории на Котлин, оставив при этом все остальное на скале. Т.е. второй набор моделек для котлина, набор кривых мапперов из скалы в Котлин. Вызовы репозиториев были завернуты в try с пустым catch. Не придумали как передавать в Котлин скаловские монады, поэтому вместо опшн, например, передавались разные варианты строк - иногда "", иногда "null", в итоге - штук 10 различных вариантов null-значений в бд.

    Таким образом очевидно, что если "простой и гибкий язык" дать людям, которые не имеют хорошего фундамента в программировании (что не редкость), в любом случае получится катастрофа. На java-проектах я такой порнографии не встречал ни разу - бывают ляпы, но не такого масштаба.

    В целом не видел ещё ни одного положительного примера использования Котлин для бэкенда. Очевидных плюсов на мой взгляд нет. Сахарок, без которого вполне можно обойтись. И корутины, полезность которых весьма спорная.


  1. olku
    06.09.2024 21:15

    Котлин это побочный результат многолетнего суда между Гуглом и Ораклом о Java API. JetBrains подсуетились и обрели партнёра в виде Android Studio. Котлин не меняет парадигму разработки как Скала, например.


  1. milinsky
    06.09.2024 21:15
    +3

    Несколько лет назад стоял выбор, пойти в сторону Kotlin или Scala, тогда я выбрал Kotlin. Первое время, после Java, это казалось как глоток свежего воздуха. Но потом особую разницу ощущать перестал. Спустя время, я таки решил попробовать Scala. И вот тогда-то для меня и открылся новый мир. С тех пор Kotlin ушёл на второй план, и я по-прежнему кайфую от работы со Scala. Да, понимаю что многие считают Scala чем то оверинжиниринговым, и я наверное с этим даже соглашусь. Но кайф в том, что Scala не заставляет тебя писать такой код, но она позволяет это делать, и делать это приятно.

    Котлин оставил приятные воспоминания. Не вижу причин отказываться от Java, как и не вижу причин не использовать Scala или Kotlin. Спасибо за статью.


  1. rutexd
    06.09.2024 21:15

    Принцип закрытого всего (как например пункт 1 в статье) - единственное что отталкивает от изучения и работы с котлином.

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


    1. panzerfaust
      06.09.2024 21:15
      +2

      Что полезного в том, что все классы закрыты по умолчанию?

      А чтобы вы дважды подумали, зачем это вам. Наследование чего угодно от чего угодно в некоторых кругах считается антипаттерном и зачатком спагетти-кода - и Jetbrains с этим согласны, очевидно. Если вы пишете самописное АОП, то есть плагин allOpen. А если просто любите шарить логику или данные между классами путем наследования, то есть композиция, интерфейсы, абстрактные классы, функции высшего порядка. В реальности нет никаких проблем.


  1. Cryvage
    06.09.2024 21:15

    Ну если нужен именно бэкенд, то можно ещё в сторону C# посмотреть. Почти все из перечисленных в статье фишек там есть (кроме закрытых по умолчанию классов). Но есть и гораздо больше. Одни только структуры чего стоят. А в последних версиях появились ещё и ref структуры, которые исключают случайный боксинг. К сожалению, Котлин не может реализовать структуры, т.к. зависит от JVM, у которой "лапки" в этом направлении.


  1. Homyakin
    06.09.2024 21:15
    +1

    На работе у нас основной язык Kotlin, но для пет-проектов предпочитаю Java свежих версий.

    • Java проще читать. В Kotlin довольно много можно сделать разными способами. Те же функции с = и без возвращаемого типа. В Java скорее всего будет написано больше кода, но потом это намного проще понять.

    • С каждой версией Java отставание от Kotlin сокращается, появляется всё больше синтаксического сахара и фичей. Project Loom, Pattern Matching, Record и т.д. Тут большее спасибо Kotlin за толчок.

    • Kotlin нормально поддерживается только в IDEA. В других IDE всё печально, банально даже навигация бывает сломана. Своеобразный вендерлок.

    • Kotlin не всегда будет эффективно использовать фичи свежих Java, те же value классы скорее всего надо будет писать именно на Java для лучшей эффективности.

    • Основные фреймворки и библиотеки всё ещё пишутся на Java, и использовать их из неё просто удобнее.

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


  1. foatto
    06.09.2024 21:15
    +2

    7 лет назад Котлин привлёк меня своей фуллстековостью - можно было на одном языке (и часто в одно лицо) писать и бэк и фронт (на kotlin/js). Сейчас стало ещё лучше - в проекте, помимо бэка, живут фронт на kotlin/wasm и мобильная версия на андроиде. Очень сокращает время разработки.