🇬🇧 Some reasons why I build my server stack with Vert-x, Kotlin, and Arrow.kt

This year, I created my own (small) company for various reasons. One of them is to make alive (in real life) some side projects (2 in fact). And, when you decide to create something professional, you need professional tools. This blog post is about what language and frameworks I'm using for my backend stack:

  • Vert-x https://vertx.io/: "a tool-kit for building reactive applications on the JVM" (I'm lucky (and honored) to know a part of the team well, and it's another reason to choose it)
  • Kotlin: https://kotlinlang.org/, I'm a JavaScript person, and I feel confident "like at home" when developing with Kotlin (with the safety of the types as a plus 😉)
  • Arrow.kt: https://arrow-kt.io/ Three years ago, I had a kind of illumination ✨ about Scala and its way of error management, and now I can do the same with Arrow.

So, here are some (right?) reasons why I build my server stack with Vert-x, Kotlin, and Arrow.kt.

It's like ExpressJS

As I said, I'm a JavaScript Person, and I have a deep love ❤️ for the Express framework. Even with Java, Vert-x code looks like JavaScript + Express code. But with Kotlin, it's even better:

router.get("/hello/:who").handler { context ->

  val who = context.request().getParam("who")

  context.response()
    .putHeader("content-type", "application/json;charset=UTF-8")
    .end(json {obj(
      "message" to "👋 Hello $who 😍",
      "author" to "@k33g_org"
    )}.encodePrettily())
}

Kotlin string templates and multiline strings are awesome

You can find it in a lot of languages, but not in Java 🤔 (right now)

Ref: https://kotlinlang.org/docs/reference/basic-types.html#string-templates

router.get("/about").handler { context ->
  
  val title = "Kitchen Sink"
  val message = "Kitchen Sink 🍲 With Vert-x & Kotlin with 💕"
  
  val aboutHtmlPage = """
  <!doctype html>
  <html>
    <head>
      <meta charset="utf-8">
      <title>$title</title>
      <style>
        .title
        {
          font-family: "Source Sans Pro";
          display: block;
          font-weight: 300;
          font-size: 100px;
          color: #35495e;
        }
      </style>
    </head>
    <body>
      <h1 class="title">
        $message
      </h1>
    </body>
  </html>
  """.trimIndent()

  context.response()
    .putHeader("content-type", "text/html; charset=utf-8")
    .end(aboutHtmlPage)
}

Extension functions, the perfect gift ğŸŽ ğŸŽ… ğŸŽ„

Ref: https://kotlinlang.org/docs/reference/extensions.html

Thanks to the extension functions, you can add some methods easily to existing classes and even "decorate" the existing methods.

In the following example, I created three "augmentations" (extensions) of Vert-x components to simplify and beautify my source code:

fun Router.get(uri: String, handler: (RoutingContext) -> Unit ) {
  this.get(uri).handler(handler)
}

fun RoutingContext.json(jsonObject: JsonObject) {
  this.response().putHeader("content-type", "application/json;charset=UTF-8").end(jsonObject.encodePrettily())
}

fun RoutingContext.param(paramName: String): Any {
  return this.request().params().get(paramName)
}

Now, thanks to these extensions, I can write something more concisely without losing the readability:

router.get("/yo/:who") { context ->
  context.json(json {obj(
    "message" to "👋 Yo ${context.param("who")} 😍",
    "author" to "@k33g_org"
  )})
}

I'm the Green Arrow (sorry) 🏹

👋 I could not help it, and it's foolish. 🤪

I'm not a "functionalist/academic" person, but I love the functional way of Error handling in Scala (and some other languages of course). I know that Kotlin is already null safety, but it's enjoyable (for me) to write things like that:

val envHttpPort = Option.fromNullable(System.getenv("PORT"))

val httpPort: Int = when(envHttpPort) {
  is None -> 8080
  is Some -> {
    Integer.parseInt(envHttpPort.t)
  }
}

And using the Try type inside my functions obliges me to manage and think of all my possible use cases of error:

// 🙀 a very bad function 😡
fun giveMeSomething(): Try<Any> {
  return Try {
    when((0..2).shuffled().first()) {
      0 -> throw Exception("🤭 Oups! I did it again")
      1 -> 42
      else -> 666
    }
  }
}
router.get("/oups") { context ->
  giveMeSomething().let {
    when(it) {
      is Failure -> context.json(json { obj("message" to it.exception.message) })
      is Success -> context.json(json { obj("number" to it.value) })
    }
  }
}

Last but not least: named parameters for code lisibility

Ref: http://kotlinlang.org/docs/reference/functions.html#named-arguments

class DarthVader {
  private var quotes: MutableList<String> = listOf(
    "The Emperor will show you the true nature of the Force. He is your Master now.",
    "He will join us or die, Master."
  ).toMutableList()

  // I can use named parameter ğŸŽ‰ !!!
  fun addQuote(quote: String) { quotes.add(quote) }

  fun getQuote(): String { return quotes.shuffled().first() }
}

These last weeks, I wrote some source code that became difficult to read even for me, so I decided to do some refactoring, and the most natural first task is to use the named arguments when calling methods:

val vader = DarthVader()
vader.addQuote(quote="Perhaps I can find new ways to motivate them.")

And it runs too with the classes constructors (sometimes, you cannot avoid classes with a lot of properties):

data class Trooper(
  val id: String, 
  val name: String, 
  val nickName: String, 
  val age: Int
) 
val bob = Trooper(
  id= "121268",
  name= "Boba Fett",
  nickName= "Bob",
  age= 42
)

They are some other good reasons to choose Vert-x (HealthCheck, Circuit Breaker, Discovery, Timers, ...) and Kotlin (e.g. Coroutines)

But that's all for today (next time, I think I will write something about my front stack).

Last Articles

Last Updated: 12/30/2018, 8:15:05 AM