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
Slide 3
Slide 3 text
ARRIVAL Robotics
a web app to connect
mechanical designers
and robofacturing
collecting
real-time feedback
software defined
robofacturing
Kotlin ?:
earlier TRA Robotics
Slide 4
Slide 4 text
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
Slide 5
Slide 5 text
What Δ do you expect?
Slide 6
Slide 6 text
code is shorter
more expressive
have fun doing the migration
less routine coding
faster feature creation
better code reading
language features and stdlib
Slide 7
Slide 7 text
Minuses?
Slide 8
Slide 8 text
Minuses?
yes :(
Slide 9
Slide 9 text
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
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:
official
pom.xml
kotlin.code.style=official
gradle.properties
@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
Slide 30
Slide 30 text
@Log
val slf4j: ReadOnlyProperty
get() = LoggerDelegate()
class LoggerDelegate : ReadOnlyProperty {
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
Slide 31
Slide 31 text
@Log
val slf4j: ReadOnlyProperty
get() = LoggerDelegate()
class LoggerDelegate : ReadOnlyProperty {
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
Slide 32
Slide 32 text
@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”)
}
}
Slide 33
Slide 33 text
@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”)
}
}
Slide 34
Slide 34 text
@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
Slide 35
Slide 35 text
@Log
val slf4j: ReadOnlyProperty
get() = LoggerDelegate()
class LoggerDelegate : ReadOnlyProperty {
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
Slide 36
Slide 36 text
@Log
val slf4j: ReadOnlyProperty
get() = LoggerDelegate()
class LoggerDelegate : ReadOnlyProperty {
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
No tests - No migrations
at least cover your core functionality
Slide 50
Slide 50 text
Keep semantics
Slide 51
Slide 51 text
Let’s do it
Slide 52
Slide 52 text
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"
}
First migrations as small as possible
but not smaller than a class
the 1st avice
Slide 58
Slide 58 text
Constants
let’s do that
Slide 59
Slide 59 text
@JvmField
const val
@file:JvmName(“...”)
object … {
...
}
Slide 60
Slide 60 text
Keep backward compatibility
even inside your team
the 2nd advice
Slide 61
Slide 61 text
Configs & Props
let’s do that
Slide 62
Slide 62 text
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html
#boot-features-kotlin-configuration-properties
@ConfigurationProperties when used in combination with @ConstructorBinding
supports classes with immutable val properties
since 2.2.0
Slide 63
Slide 63 text
First of all check docs
docs of many libs/tools have a chapter called “Kotlin”
the 3rd advice
Slide 64
Slide 64 text
Aspects
let’s do that
Slide 65
Slide 65 text
The Converter Is Software
can have bugs
the 4rd advice
Slide 66
Slide 66 text
Model
let’s do that
Slide 67
Slide 67 text
DTO & mappers
let’s do that
Slide 68
Slide 68 text
Check compatibility of your libs with Kotlin
before migration!
the 5th advice
Slide 69
Slide 69 text
Be strong. Someday it will end
probably not this month
the 6th advice
Slide 70
Slide 70 text
Services
let’s do that
Slide 71
Slide 71 text
Improve your code
if changes are small but profit is great
the 7rd advice
Slide 72
Slide 72 text
Controllers
let’s do that
Slide 73
Slide 73 text
Check auto-generated* stuff manually
if you are too lazy to write tests for it
the 8th advice
* not only, but at least
Slide 74
Slide 74 text
Global Steps
1. What Δ do you expect?
2. Code Style / Checkstyle
3. Migrate
4. Review
Slide 75
Slide 75 text
Global Steps
1. What Δ do you expect?
2. Code Style / Checkstyle
3. Migrate
4. Review
Slide 76
Slide 76 text
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
Slide 77
Slide 77 text
Go in small steps
if you really ready to solve problems
the final avice
Slide 78
Slide 78 text
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