Stop Writing Shitty DSLs

Stop Writing Shitty DSLs

This post is prompted by several days of fighting against bad Kotlin libraries which think doing verb {} for every API is cute and fun and not the most annoying thing to ever exist.

What is a shitty DSL?

I am going to pick on ktor:

import io.ktor.server.netty.*  
import io.ktor.routing.*  
import io.ktor.application.*  
import io.ktor.http.*  
import io.ktor.response.*  
import io.ktor.server.engine.*

fun main(args: Array<String>) {  
    embeddedServer(Netty, 8080) {
        routing {
            get("/") {
                call.respondText("Hello, world!", ContentType.Text.Html)
    }.start(wait = true)

This can absolutely fuck off forever. Why is the server a function taking a routing function which is taking other functions that define routes which all take their own functions? It's like somebody learned of the term "functional programming" and thought it meant Node.JS callbacks on steroids.

What's wrong with using a list? Or annotations? Fuck, if we hate ourselves that much we can even go full Java and have to pass classes and even then that would be less of an eyesore than this mess.

A saner API

Here's the API, rewritten into a SANE format:

val server = embeddedServer(Netty, 8080)  
val router = Router()  
router.addRoute(path="/", method="GET") { call.respondText("Hello, world!", ContentType.Text.Html) }  
server.router = router  
server.start(wait = true)  

How much more readable is that? It's not a grotesque mess like the DSL above. It's more imperative, sure, but it's also not ten trillion layers of nesting.


Your library is not a REST API. Passing functions to verbs is horrible, and unreadable.

Written on 09 March 2018