with(ConfigObject) { "Language $KOTLIN".isSparkingJoy() }
Tags: kotlin
Published: 2019-09-15 16:36:12

I am using [Kotlin](https://kotlinlang.org/docs/reference/) since _traits_ were a thing. Yet it continue to surprise me for the better, usually when I discover how two familiar language constructs combine nicely for the better. 

Today I will share with you such a recent discovery. I am not aware that this pattern has already a name, so I will cal it the `with(ConfigObject)` Pattern. 

```kotlin
with(ConfigObject) { 
     "Language $KOTLIN".isSparkingJoy() 
}
```

But first I will start with a confession:

# That shitty first draft

When I'm starting to work on a project or a feature, my initial code is **messy**. 

It has thing that are hard-coded but shouldn't. It has top-level properties and functions all over the place. Sometimes implemented twice. Things that should be extracted but are not. Things that are extracted in a way that doesn't really make sense. Usually with a bad name. 

That initial messy code serves important purposes. Playing with and learning a new API. Validating that it makes sense to invest time into an idea. More importantly, it's a remedy against perfectionism. On this, I am [with writer Anne Lamott](https://www.brainpickings.org/2013/11/22/bird-by-bird-anne-lamott/)

> Perfectionism is the voice of the oppressor, the enemy of the people. It will keep you cramped and insane your whole life, and it is the main obstacle between you and a shitty first draft.
> Perfectionism is a mean, frozen form of idealism, while messes are the artist’s true friend. What people somehow (inadvertently, I’m sure) forgot to mention when we were children was that we need to make messes in order to find out who we are and why we are here — and, by extension, what we’re supposed to be writing.

# Refactoring time

Yet, when the time has come, it's time to clean things up. 

It's time for [refactoring](https://refactoring.com/).


Imagine we have this initial messy code:

```kotlin
fun doStuff() {
    val feeling = "is sparking joy"
    println("Language $language " + feeling + "!")
}

val language = "Kotlin"
```

The pattern here is to 
- Create a `Config` singleton that contains all the extracted constants so that there are not all over the place in the package
- Use the [scope-function `with`](https://kotlinlang.org/docs/reference/scope-functions.html#with) that imports all the properties and extension function of `Config`

It works. Trust me!

No, actually, trust me but do **verify** by clicking on the **Run ▶️** button of this embedded snippet:

{% kotlin https://pl.kotl.in/ZCSpfZtsF?theme=darcula&from=1&to=8 %}

You will probably have to **scroll down** the Kotlin snippet because of [thepracticaldev/dev.to#4011 Iframe resizing](https://github.com/thepracticaldev/dev.to/issues/4011). But it does work:

![image](https://user-images.githubusercontent.com/459464/64924565-72cd0700-d7e6-11e9-9950-5202ac482c4d.png)

# Conclusion

I am not sure if this pattern has already a name. It use familiar building blocks. You do similar, more complex things when you use Kotlin to build a Domain Specific Language - DSL, see [Kotlin in Action, chapter 11](https://livebook.manning.com/book/kotlin-in-action/chapter-11).

But DSL are a rather advanced topics, while this is an easy solution to a simple problem and merits to be highlighted.

Obviously, this example was contrived to fit on the title of my Post. 

For a real-world example, have a look in my open-source project at [PluginConfig](https://github.com/jmfayard/buildSrcVersions/blob/07fec637833d1a63bb6ed61241ba76ff9d49e3cb/plugin/src/main/kotlin/de/fayard/internal/PluginConfig.kt#L12-L49) and its usage [`with(PluginConfig) { ... }`](https://github.com/jmfayard/buildSrcVersions/blob/07fec637833d1a63bb6ed61241ba76ff9d49e3cb/plugin/src/main/kotlin/de/fayard/BuildSrcVersionsPlugin.kt#L26-L50)

One thing worth pointing out is that it works really well not only for constants, but also for functions and more importantly [extension functions](https://kotlinlang.org/docs/reference/extensions.html#extensions)! I am not a fan of having extensions function for `String`. That would pollute all the Strings out there. But the `ConfigObject` provides a scope for it.

Try it out to discover the life-changing magic of tidying up!

# Hello, Kotlin Weekly

Lots of visitors. What happened? Oh, I was featured in Kotlin Weekly?


Welcome to dev.to!

I shall invite you to create an account here. 
It's a friendly dev community of readers and writers. 
Here is a good summary of what you may want to publish here instead - or in parallel with publishing on Medium.com

{% link https://dev.to/devteam/medium-was-never-meant-to-be-a-part-of-the-developer-ecosystem-25a0 %}

You can follow Kotlin content:

{% tag kotlin %}

and if you wish, you can also follow me

{% user jmfayard %}