Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Иван Осипов — Из Java на Kotlin, сидя на корме веб-приложения

Moscow JUG
November 14, 2019

Иван Осипов — Из Java на Kotlin, сидя на корме веб-приложения

Kotlin имеет место не только на поприще android разработки, но и в backend мире. Много кода уже написано на Java и Spring Boot, что же со всем этим делать?

Мигрировать! В ходе доклада мы проделаем путь с прекрасного "острова Java" со своими дикими зверьми вроде lombok в направлении "острова Kotlin", где постараемся адаптироваться и оглянуться назад.

Шаг за шагом мы мигрируем веб приложение с одного языка на другой, а по пути взглянем на местами неочевидные проблемы.

Moscow JUG

November 14, 2019
Tweet

More Decks by Moscow JUG

Other Decks in Programming

Transcript

  1. github.com/ivan-osipov/repository telegram ivan_osipov twitter _osipov_ name Ivan Osipov viber >

    sudo rm -rf whatsapp > dev/null deprecated i-osipov.ru t.me/from_junior_to_senior from-java-to-kotlin
  2. ARRIVAL Robotics a web app to connect mechanical designers and

    robofacturing collecting real-time feedback software defined robofacturing Kotlin ?: earlier TRA Robotics
  3. Agenda 1. Motivation 2. Preparation (checkstyle, autoformatting, test coverage) 3.

    Java + Lombok vs. Kotlin 4. Java to Kotlin Converter 5. Bugs, rakes and steps to migrate
  4. code is shorter more expressive have fun doing the migration

    less routine coding faster feature creation better code reading language features and stdlib
  5. lost ternary operator lost a number of ide features structural

    search, AspectJ highlights nullability noize!! lost implicit widening conversions companion object { noise } third party idiomaticity
  6. https://kotlinlang.org/docs/reference/code-style-migration-guide.html 1 Oct. 2018 Kotlin Coding Conventions • Since Kotlin

    1.3 by default for new projects • For old projects: <properties> <kotlin.code.style>official</kotlin.code.style> </properties> pom.xml kotlin.code.style=official gradle.properties
  7. Equivalents @Getters @Setters properties @NonNull nullability @SneakyThrows only unchecked exceptions

    @Cleanup .use { … } val/var val/var @*ArgsConstructor primary constructor
  8. Equivalents @Getters @Setters properties @NonNull nullability @SneakyThrows only unchecked exceptions

    @Cleanup .use { … } val/var val/var @*ArgsConstructor primary constructor
  9. Equivalents @Getters @Setters properties @NonNull nullability @SneakyThrows only unchecked exceptions

    @Cleanup .use { … } val/var val/var @*ArgsConstructor primary constructor
  10. Equivalents @Getters @Setters properties @NonNull nullability @SneakyThrows only unchecked exceptions

    @Cleanup .use { … } val/var val/var @*ArgsConstructor primary constructor
  11. Equivalents @Getters @Setters properties @NonNull nullability @SneakyThrows only unchecked exceptions

    @Cleanup .use { … } val/var val/var @*ArgsConstructor primary constructor
  12. Equivalents @Getters @Setters properties @NonNull nullability @SneakyThrows only unchecked exceptions

    @Cleanup .use { … } val/var val/var @*ArgsConstructor primary constructor
  13. @Log @Slf4j public class MyService { public void doSmth() {

    log.info(“my log entry”) } } class MyService { val log by slf4j fun doSmth() { log.info(“my log entry”) } } https://discuss.kotlinlang.org/t/best-practices-for-loggers/226/26
  14. @Log val slf4j: ReadOnlyProperty<Any, Logger> get() = LoggerDelegate() class LoggerDelegate

    : ReadOnlyProperty<Any, Logger> { lateinit var logger: Logger override fun getValue(thisRef: Any, property: KProperty<*>): Logger { if (!::logger.isInitialized) logger = LoggerFactory.getLogger(thisRef.javaClass) return logger } } https://discuss.kotlinlang.org/t/best-practices-for-loggers/226/26
  15. @Log val slf4j: ReadOnlyProperty<Any, Logger> get() = LoggerDelegate() class LoggerDelegate

    : ReadOnlyProperty<Any, Logger> { lateinit var logger: Logger override fun getValue(thisRef: Any, property: KProperty<*>): Logger { if (!::logger.isInitialized) logger = LoggerFactory.getLogger(thisRef.javaClass) return logger } } https://discuss.kotlinlang.org/t/best-practices-for-loggers/226/26
  16. @Log @Slf4j public class MyService { public void doSmth() {

    log.info(“my log entry”) } } class MyService { val log by slf4j fun doSmth() { log.info(“my log entry”) } }
  17. @Log @Slf4j public class MyService { public void doSmth() {

    log.info(“my log entry”) } } class MyService { companion object { val log by slf4j } fun doSmth() { log.info(“my log entry”) } }
  18. @Log @Slf4j public class MyService { public void doSmth() {

    log.info(“my log entry”) } } class MyService { companion object { val log by slf4j } fun doSmth() { log.info(“my log entry”) } } https://www.reddit.com/r/Kotlin/comments/8gbiul/slf4j_loggers_in_3_ways INFO my.package.MyService$Companion - my log entry
  19. @Log val slf4j: ReadOnlyProperty<Any, Logger> get() = LoggerDelegate() class LoggerDelegate

    : ReadOnlyProperty<Any, Logger> { lateinit var logger: Logger override fun getValue(thisRef: Any, property: KProperty<*>): Logger { if (!::logger.isInitialized) { val javaClass = thisRef.javaClass logger = LoggerFactory.getLogger( javaClass ) } return logger } } https://discuss.kotlinlang.org/t/best-practices-for-loggers/226/26
  20. @Log val slf4j: ReadOnlyProperty<Any, Logger> get() = LoggerDelegate() class LoggerDelegate

    : ReadOnlyProperty<Any, Logger> { lateinit var logger: Logger override fun getValue(thisRef: Any, property: KProperty<*>): Logger { if (!::logger.isInitialized) { val javaClass = thisRef.javaClass logger = LoggerFactory.getLogger( if (javaClass.kotlin.isCompanion) javaClass.enclosingClass else javaClass ) } return logger } } https://discuss.kotlinlang.org/t/best-practices-for-loggers/226/26
  21. FF000000 0 Compile error println( Integer.toHexString( 0xFF000000 ) ) Rewritten

    Long https://discuss.kotlinlang.org/t/when-does-bit-fiddling-come-to-kotlin/2249
  22. FF000000 0 Compile error println( Integer.toHexString( 0xFF000000u ) ) Rewritten

    a future solution? https://discuss.kotlinlang.org/t/when-does-bit-fiddling-come-to-kotlin/2249
  23. Gradle Plugins plugins { ... id 'org.jetbrains.kotlin.jvm' version "1.3.50" id

    "org.jetbrains.kotlin.plugin.spring" version "1.3.50" id "org.jetbrains.kotlin.plugin.allopen" version "1.3.50" }
  24. compileKotlin { kotlinOptions { freeCompilerArgs = ["-Xjvm-default=compatibility"] jvmTarget = "1.8"

    } } https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-default/index.html
  25. First of all check docs docs of many libs/tools have

    a chapter called “Kotlin” the 3rd advice
  26. Check auto-generated* stuff manually if you are too lazy to

    write tests for it the 8th advice * not only, but at least
  27. Global Steps 1. What Δ do you expect? 2. Code

    Style / Checkstyle 3. Migrate 4. Review
  28. Global Steps 1. What Δ do you expect? 2. Code

    Style / Checkstyle 3. Migrate 4. Review
  29. Migration Steps 1. Repositories 2. Constants 3. Config & Props

    4. Delombok everything (at least one sub domain) 5. From the most abstract entity classes downwardly 6. Subdomains: Model + DTO + Mappers 7. Services & Another Domain Logic 8. Controllers
  30. github.com/ivan-osipov/repository telegram ivan_osipov twitter _osipov_ name Ivan Osipov viber >

    sudo rm -rf whatsapp > dev/null deprecated i-osipov.ru t.me/from_junior_to_senior from-java-to-kotlin