Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

Latest commit

 

History

History
402 lines (385 loc) · 7.64 KB

PITCHME.md

File metadata and controls

402 lines (385 loc) · 7.64 KB

---?image=assets/image/background.jpg

From Java to Kotlin

The first year in practice

Agenda

What to expect today?

  • My Background
  • Why Kotlin?
  • Code Code Code
  • Demo Application

My Background

@ul

  • >10 years Java
  • more than 1 year @ Meshcloud
  • solution-oriented developer @ulend

Why Kotlin?

Syntax +++

100% Java interoperability

@ul

  • all Java frameworks can be used without big problems
  • same development paradigm as Java
  • step-by-step conversion of existing Java app
  • it's Java without the flaws + useful candy @ulend +++

Productivity

@ul

  • Practical, not academic
  • Expressive
  • Developed by JetBrains, Open Source -> great IDE support
    • Convert Java to Kotlin Button
    • Great tips how to optimize code within editor
  • Strictly-Typed -> Null-Safety @ulend

Code Code Code

Syntax +++

Context of Code Snippets

@ul

  • Billing of Cloud Platform
  • Resources (VMs, Apps, etc)
  • Projects are container of resources
  • Service to calculate costs per project @ulend

Integration into existing application

Syntax +++

buildscript {
  ext {
    kotlinVersion = '1.2.71'
    kotlinPlugin = 'org.jetbrains.kotlin:kotlin-gradle-plugin'
  }
  dependencies {
    classpath "$kotlinPlugin:$kotlinVersion"
  }
}

+++

apply plugin: "java"
apply plugin: "kotlin"

sourceSets {
  main.kotlin.srcDirs += 'src/main/java'
  main.java.srcDirs += 'src/main/java'
}

dependencies {
  compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
}

Basic Syntax

Syntax +++ Variables

val x = "value" // immutable & type inference
var y: Boolean // mutable

+++ Type Inference

// Java (< Java 10)
Map<ResourceType, List<Resource>> resourceMapByType =
    service.findResourceMapByType();
// Kotlin
val resourceMapByType = service.findResourceMapByType()

+++ Functions

fun sum(a: Int, b: Int): Int {
    return a + b
}

// expression body & type inference
fun sum(a: Int, b: Int) = a + b

+++

Everything is an expression

fun formatText() = if (projects.isEmpty()) "n/a" else projects

Null Safety

Syntax +++ Null checks during compilation

var x = "value"
x = null // compile error

+++ Safe calls

var x: MyClass?
val child = x?.child // if x == null -> null

+++ Intelligent compiler

if (x != null) {
  val child = x.child // knows that x != null
}

+++ Smart casts

if (x is String) {
    print(x.length) // x is automatically cast to String
}

+++ Elvis Operator

// findOne or throw exception if result == null
projectRepository.findOne(id) ?: throw NotFoundException()
tryFindProjectList() ?: emptyList()

Scoping Functions

Syntax +++ Null check in Java

public Date convertToDatabaseColumn(Instant instant) {
    return instant != null ? Date.from(instant) : null;
}

+++ let in Kotlin

// let: return result & use "it" for current object
fun convertToDatabaseColumn(instant: Instant?): Date? {
  return instant?.let { Date.from(it) }
}

+++ run

// run: return result & use "this" for current object
fun convertToEntityAttribute(value: Date?): Instant? {
  return value?.run { toInstant() }
}

+++ apply

// apply: return self & use "this" for current object
val headers = HttpHeaders().apply {
  contentType = MediaType.APPLICATION_JSON
  add("ProjectId", project.id)
}

+++ also

// also: return self & use "it" for current object
fun createAndLogProject() {
  return generateProject().also { log(it) }
}

Mighty little helpers

Syntax +++ String templates

val text = "Project ${project.name}: $details"

+++ Structural equality with ==

project == otherProject // calls null-safe equals
project === otherProject // referential equality

+++ When expressions

when {
  "Bitcoin" in projectNames -> println("Bad guy!")
  projectNames is empty -> println("No Projects")
  else -> println("Just normal projects!")
}

+++ Collection creation

var myList = listOf('a', 'b', 'c')
var mySet = setOf(1, 2)
var myMap = mapOf('a' to 5, 'b' to 10)

+++ Ranges

for (i in 1..100)
for (i in 10 downTo 1)

+++ Destructuring

// Java
for (Map.Entry<String, Object> entry : map.entrySet()) {
    print("Key: " + entry.getKey() + "Value: " + entry.getValue());
}
// Kotlin
for ((key, value) in map) {
    print("Key: $key, Value: $value")
}

Concise Streaming API

Syntax +++ Java

projectRepository
  .findAll()
  .stream()
  .map(p -> new ProjectListDTO(p))
  .collect(Collectors.toList());

+++ Kotlin

projectRepository
  .findAll()
  .map { ProjectListDTO(it) }

Avoid boilerplate

Syntax +++ Implicit Getters/Setters & property access:

class Project {
    var name: String
}
val pName = Project().name

+++ Data classes (with equals, hashcode, toString & copy):

data class Project(
  val name: String,
  val description: String
) {
  val fullText: String
    get() = "$name - $description"
}

Expressive Arguments

Syntax +++ Default Arguments

fun create(
  name: String,
  description: String = "default"
)

+++ Named Arguments

create(
  name = "My Project",
  description = "Some details"
)

Higher Order Functions

Syntax +++ Java (Function, Consumer, Supplier, BiConsumer, …)

public String myFunction(
  BiFunction<String, String, String> fn
) {
    fn.apply("1", "2") // .get() on Supplier, ...
}

+++ Kotlin

fun myFunction(
  fn: (String, String) -> String
) {
  fn("1", "2")
}

Extension Functions

Syntax +++

val customFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")

fun Date.formatted(): String {
  return customFormat.format(this)
}

val dateAsText = Date().formatted()

@[1-5] @[6-7] +++

fun ProjectRepository.findOneOrThrow(id: Long): Project {
  return findOne(id)
    ?: throw NotFoundException("Could not find project $id")
}

Generics

Syntax +++ Reified Generics

inline fun <reified T : Any> createEmptyWrappedResource()
    : PagedResources<EmbeddedWrapper> {
  val wrappers = EmbeddedWrappers(false)
  val emptyWrapper = wrappers.emptyCollectionOf(T::class.java)
  val embedded = listOf(emptyWrapper)
  return PagedResources(embedded)
}

@[1] @[4]

Demo Application

Syntax +++ LoC

Java 460
Kotlin 252
Reduction 46%
https://github.com/Meshcloud/spring-kotlin-example
+++
LoC without data classes
Java 232
Kotlin 185
Reduction 21%
https://github.com/Meshcloud/spring-kotlin-example

Questions?


@faenvelope gp-contact

@fatwitter gp-contact

@fagithub gp-contact

https://github.com/Meshcloud/spring-kotlin-example

Artikel bei IT Aktuell