Особенности перехода на Kotlin для Android-разработчиков

0
992
views
Особенности перехода на Kotlin

Сегодня все большее число программистов, занятых в сфере разработки под Андроид, активно используют Kotlin. Этот современный язык рекомендует Google, да и многочисленные отзывы в сообществах подтверждают удобство и универсальность ЯП.

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

Экскурс в историю

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

Разработка велась с 2010 года. Первая рабочая версия Котлин вышла в 2016 году в середине февраля. В проект было вложено более 15 млн. $. На данный период времени наиболее актуальной версией продукта считается Kotlin 1.2, релиз от ноября 2017 года.

Язык создавался под работу с JVM (Java Virtual Machine), которая является главной исполняющей системой Java. Фактически при работе с Kotlin виртуальная машина компилирует программу в байт-код. Это позволяет запускать приложения, написанные на этом языке, в любой среде, где присутствует виртуальная машина Java, в том числе, в любом браузере.

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

Код, написанный на Kotlin, может без проблем взаимодействовать с разными ОС.  Сегодня язык активно развивается в сторону open source, т.е. разработка его становится массовой, как и у любого популярного продукта с открытым кодом.

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

В 2017 году компания Google включила Котлин в список официальных языков для разработки приложений платформы Android. Инструменты языка поддерживаются в Android Studio, начиная с версии 3.0.

Что полезного содержит Kotlin

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

Самые интересные «фишки», которые оценили в Kotlin разработчики:

  • Null Safety. Одна из самых часто упоминаемых особенностей языка. Позволяет при определении типов, переменных, полей и т.д. самостоятельно определять, может ли в них находиться ссылка на null.
  • Лямбды. Возможность не только объявлять функции в рамках пакета, но и передавать их в качестве параметра для других функций. Возможность, реализованная во многих языках. Но в Java ее сильно не хватает.
  • Extension methods. Возможность определить метод для выбранного типа отдельно от объявления самого типа. Помогает разгрузить интерфейс для утилитарных методов.
  • Делегирование. Возможно двумя методами – делегирование всех методов к определенному инстансу либо delegated properties, при котором делегируется доступ к выбранным свойствам объекта.
  • Generics. Это практически те же самые дженерики, что хорошо известны всем Java-разработчикам. Но в Котлине их доработали и сумели исправить множество недочетов.
  • Data-классы. Возможность генерировать специальные классы, единственное назначение которых состоит в хранении данных. После описания компилятор извлекает члены класса из свойств, которые описаны в коде конструктора. Есть у этой возможности плюсы и минусы, функционал относительно ограничен и нуждается в доработках. Но само наличие

Есть и другие интересные решения в Котлин, все их описывать – придется создавать целое руководство. А это совсем не наша цель. Потому давайте вернемся к тому, с чего мы и начинали. И разберемся в особенностях Kotlin и «подводных камнях» для разработчиков, которые решили «пересесть» с привычного Java на этот язык.

Переход на Kotlin для Android-разработчиков

Начинаем знакомство

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

Если вы пользуетесь средствами annotation processing или основанными на нем библиотеками, придется вносить правки в модули build.gradle. Без подключения дополнительного плагина kapt они просто не будут собираться.

Вот так выглядит код подключения:

apply plugin: 'kotlin-kapt'

Также не забудьте в конфигурации build.gradle заменить все инициированные annotationProcessor на тот же kapt.

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

Null Safety: как это работает

Основное отличие Котлин от Джава – это поддержка null-safety типов. Используются такие описания типов для того, чтобы избежать обращения к null значениям, распространенного бага, который в среде программистов известен под названием «ошибка на миллион» или NPE (NullPointerException).

Причина, по которой может возникнуть ошибка это:

  • throw NullPointerException() – явный вызов, инициированный программистом.
  • Использование NPE в !! операторе.
  • Любое несоответствие данных при инициализации.
  • Интероперабельность платформы Джаба:
    • Попытки доступа к элементу на null референции типа платформы;
    • Обобщенные типы, используемые для Java интероперабельности с некорректной допустимостью;
    • Прочие проблемы с внешним java кодом.

Котлин позволяет при написании кода с самого начала «закрыть» возможность появления этого бага. Это большой плюс, но джава-разработчикам придется привыкать своевременно описывать типы.

Data классы в Котлин

Перед тем компания Google объявило об официальной поддержке Котлин, нередко встречались советы начать знакомство и переход на этот язык с создания на нем юнит-тестов. Многие были с этим согласны, поскольку это было самым неагрессивным способом захвата кодовой базы. Также подобный подход освобождал от риска получения ошибок, вызванных применением двух языков программирования в одном проекте. Напоминаем, что unit-тесты относятся к императивному стилю программирования.

Предположим, что вам нужно указать класс для видеофайла. В этом случае будет достаточно написать:

data class Movie(val id: Long, val title: String, val director: String, val releaseDate: Date)

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

Кроме того, стоит обратить внимание на такие особенности:

  • Переопределенные методы находятся «под коробкой».
  • Immutable неявно наследуется от Any. Его создание в коде выглядит так:
    Movie(42L, «Isle of Dogs», «Wes Anderson», Date())
  • Метод copy () поможет легко «клонировать» фрагмент данного класса, который будет не изменяем, но отличаться одним или несколькими полями если не было применено значение «private». Такое решение станет, по сути, первым шагом к функциональному стилю программирования:
    val clonedMovie = existingMovie.copy(id = 43L)

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

Учтите, что этот метод работает только с data-классами, для обычных он не применим.

Еще один интересный плюс. Вместо обычного Builder-паттерна – значения «по умолчанию:

data class Movie(val id: Long = 0L, val title: String = "", val director: String = "", val releaseDate: Date, val description: String? = null)
...
val movie = Movie(releaseDate = Date(), title = "The Darjeeling Limited")

О чем бы еще хотелось сказать. Дата-классы в рамках средств Котлин не наследуют друг друга. Но можно применить sealed-классы (запечатанные классы), они не могут быть созданы непосредственно и могут иметь абстрактные элементы. Как вы уже поняли, для объявления этого класса применяется идентификатор sealed.

Data-классы и Parcelable: польза или вред

Начиная с версии 1.1.4 в Котлин реализована аннотация с именем «@Parcelize». Она позволяет отказаться от необходимости писать boilerplate-реализации для использования де/сериализации объектов. Выглядит это так:

@Parcelize

data class Movie(val id: Long, val title: String, val director: String, val releaseDate: Date)

Не следует забывать о том, что необходимо применить AEp:

apply plugin: 'kotlin-android-extensions'

Непременно необходимо обозначить experimental-флаг как «истина»:

android {

   androidExtensions {

       experimental = true

   }

}

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

Data-классы и самые востребованные библиотеки

Чтобы пользоваться всеми возможностями популярной библиотеки Room Persistence Library, достаточно подключить kapt. После этого вы с легкостью можете описывать различные объекты, как для исполнения на сервере, так и для работы в браузере.

Пример кода:

@Entity(tableName = "movies")

data class Movie(

        @PrimaryKey @ColumnInfo(name = "id") val id: Long,

        @ColumnInfo(name = "title") val title: String,

        @ColumnInfo(name = "director") val director: String,

        @ColumnInfo(name = "date") val releaseDate: Long

)

С модификатором Nullable также не возникнет никаких проблем. Разочарование вас ждет только при попытке работать с Room, так как здесь не поддерживаются значения по умолчанию. Кроме того, могут возникнуть и другие сложности. (о них стоит почитать в документации).

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

data class Movie(

        @SerializedName("id") val id: Long,

        @SerializedName("title") val title: String,

        @SerializedName("director") val director: String,

        @SerializedName("releaseDate") val releaseDate: Date

)

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

Если вам требуется для работы Jackson, нужно добавить поддержку специального модуля поддержки сериализации. А для комфортной работы с Moshi необходимо прописать зависимость:

implementation 'com.squareup.moshi:moshi-kotlin:1.x.y'
Kotlin и Java

Как свести Kotlin с Java

По идее, постепенно весь ваш проект перейдет с Java на Котлин. Но до этого придется пройти тернистый путь. Некоторые нюансы решаются просто, другие могут заметно «испортить жизнь», как минимум на 2-3 часа.

В принципе, Kotlin создавался как 100% совместимый с Джава. Вы без проблем сможете пользоваться в коде Котлин существующими Java-классами и другими объектами, а также, наоборот, применять в коде Java аннотации и классы из Котлин. Но существуют некоторые ограничения, все они есть в документации. В случае возникновения ошибки рекомендуем с ними ознакомиться подробнее здесь.

Going Static

Обратите внимание, в языке Котлин нет слова static. Но это не повод для паники. Сам механизм, который позволяет объявить объект внутри созданного класса, заимствует все доступные функции описания, никуда не делся. Только теперь это называется «companion object». Но если вы хотите, чтобы компиляция прошла полноценно и для объекта, и для статистических методов классов, не забудьте добавить метку @JvmStatic.

Коллекции

Котлин при работе с коллекциями фактически полностью повторяет протокол, предусмотренный в Джава. Но при этом язык имеет также собственные интересные возможности. Благодаря встроенным модификаторам для объявления, преобразования и модификации коллекций (listOf(), mapOf(), etc)  возможности разработчика расширяются. В работе эти функции показали себя как очень удобные.

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

Несколько слов о unit-тестах

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

Дело в том, что со стороны Mockito из-под-коробки не предусмотрена работа с к final-классами. А в Котлин по умолчанию все классы имеют статус final по умолчанию. Вариант open нужно объявлять явно.

Решить эту проблему можно одним из двух методов — объявить все классы как open или использовать простой хак:

  1. Зайдите в папку …/resources/mockito-extensions
  2. Создайте файл org.mockito.plugins.MockMaker.
  3. Внесите в него строку: mock-maker-inline.

Множество других полезных возможностей и решений вы найдете в библиотеке mockito-kotlin. Она поможет сделать удобнее инициализацию моков, верификацию и т.д.

Kotlin и Data Binding

При использовании в джава-проекте DataBinding в случае перехода на Котлин может появиться множество ошибок компиляции. Чтобы избежать их и восстановить совместимость, добавьте в файл со списком зависимостей строку:

kapt 'com.android.databinding:compiler:x.y.z'

Кроме того, обязательно изучите полезный плагин Kotlin Android Extensions. Он позволит вам отказаться от DataBinding, а реализация многих функций с его помощью становится настолько простой, что в него невозможно не влюбиться.

Резюме

Несмотря на декларируемую 100% совместимость Kotlin с традиционным Java, переход существующего проекта, как видите, может сопровождаться определенными сложностями и багами. В статье мы привели только отдельные, скажем так, базовые примеры подобных проблем и показали их решение. В реальности «подводных камней» окажется намного больше.

Но есть и хорошая новость. Решение возникших сложностей вы практически всегда найдете в документации Котлин или профессиональном сообществе. Чаще всего реализация их оказывается совсем несложной. А переход на Котлин стоит того, так как язык позволит сделать проект быстрее, подарит новые возможности в разработке, да и программировать на Котлин – одно удовольствие. Конечно, после того, как вы его изучите.


ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here