<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Pin-Sho Feng</title>
    <description>The latest articles on Forem by Pin-Sho Feng (@psfeng).</description>
    <link>https://forem.com/psfeng</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F71027%2F305f1287-1fa1-48ab-a0fc-6f545addc7c1.jpg</url>
      <title>Forem: Pin-Sho Feng</title>
      <link>https://forem.com/psfeng</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/psfeng"/>
    <language>en</language>
    <item>
      <title>A story of building a custom Flow operator - bufferTimeout</title>
      <dc:creator>Pin-Sho Feng</dc:creator>
      <pubDate>Sun, 17 May 2020 20:19:45 +0000</pubDate>
      <link>https://forem.com/psfeng/a-story-of-building-a-custom-flow-operator-buffertimeout-4d95</link>
      <guid>https://forem.com/psfeng/a-story-of-building-a-custom-flow-operator-buffertimeout-4d95</guid>
      <description>&lt;p&gt;I have this particular use case where I need to process a live stream of elements to send them to a distributed queue (e.g. Kafka, NATS...). I'd like to consume this stream in batches that can be up to N elements in size and I want to buffer them for at most &lt;code&gt;t&lt;/code&gt; duration. In other words, a batch should be processed when either of the following conditions is met:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of buffered elements reaches a certain size &lt;code&gt;N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Timeout after &lt;code&gt;t&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another use case would be consuming a live stream that we want to process and store to the DB, and in this stream there could be duplicated events or events that could be merged, which we'd like to process before storing.&lt;/p&gt;

&lt;h2&gt;
  
  
  1st attempt: Flow + Reactor
&lt;/h2&gt;

&lt;p&gt;In this particular project I wanted it to be pure Kotlin with as few dependencies as possible so initially I didn't look at either RxJava or Reactor, and Kotlin coroutines (in particular &lt;a href="https://kotlinlang.org/docs/reference/coroutines/flow.html"&gt;Flow&lt;/a&gt;) came to mind. Looking at the &lt;a href="https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/index.html"&gt;available operators&lt;/a&gt; (using version 1.3.6 at the time of writing), I didn't find one for that functionality so I went to coroutine's Github issues to see if anyone had run into a similar problem and found an &lt;a href="https://github.com/Kotlin/kotlinx.coroutines/pull/1558"&gt;open PR&lt;/a&gt; for &lt;code&gt;chunked&lt;/code&gt; and &lt;code&gt;window&lt;/code&gt;. Still, this is missing the timeout functionality.&lt;/p&gt;

&lt;p&gt;The next thing I thought was that either Reactor or RxJava would probably have something like that, and I was lucky to find &lt;a href="https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#bufferTimeout-int-java.time.Duration-"&gt;bufferTimeout&lt;/a&gt;! Now, I wanted to avoid having an extra dependency but building an operator and doing it right must be quite difficult, right? I still want to use coroutines as much as possible, so maybe I could just use the &lt;a href="https://github.com/Kotlin/kotlinx.coroutines/tree/583ec6e862fb70c7fc0232af948a028bab3b20de/reactive/kotlinx-coroutines-reactor"&gt;interop library&lt;/a&gt; and use Reactor to process a &lt;code&gt;Flow&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// some channel where events will be produced&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;disposable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;consumeAsFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asFlux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bufferTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ofMillis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concatMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;  
        &lt;span class="n"&gt;events&lt;/span&gt;  
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;  
                &lt;span class="nf"&gt;mono&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received $event, ts: ${System.currentTimeMillis()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// simultate suspending operation like sending to a queue  &lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Flux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Not bad, right? The problem is that when you start testing you'll find out that &lt;code&gt;bufferTimeout&lt;/code&gt; doesn't implement backpressure (see &lt;a href="https://github.com/reactor/reactor-core/issues/1292"&gt;this&lt;/a&gt; and &lt;a href="https://github.com/reactor/reactor-core/issues/1099"&gt;this&lt;/a&gt;) and if your producer goes faster than you can consume, the flux will crash. The issue was first reported early 2018 and it doesn't seem easy to fix, so now what?&lt;/p&gt;

&lt;p&gt;Maybe we could implement our own operator... Trying to fix &lt;code&gt;bufferTimeout&lt;/code&gt; is out of the question so it has to be for Flow... but where do we start? 🤔 It's my first time using Flow, so I have no clue, let's see.&lt;/p&gt;

&lt;h2&gt;
  
  
  2nd try: imperative approach
&lt;/h2&gt;

&lt;p&gt;If we can produce from a channel and can read from it, we should be able to just whip some naive code with a timeout to create our solution right? So I tried this path first. We'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Something that will provide clock ticks for implementing the timeout&lt;/li&gt;
&lt;li&gt;Accumulate values in a buffer
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// some channel where events will be produced&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;receiverJob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This launches a coroutine that will send ticks to a channel with a given frequency&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tickerChannel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;events&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;  

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;  
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tickerJob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="n"&gt;tickerChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;hasTimedOut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nf"&gt;withTimeoutOrNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  
                    &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;  
                &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received $event, ts: ${System.currentTimeMillis()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
            &lt;span class="n"&gt;tickerJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tickerChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And voilà! Let's break this down a bit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We launch a coroutine that will run the consumer logic&lt;/li&gt;
&lt;li&gt;We have a mutable list that we use as the buffer of elements&lt;/li&gt;
&lt;li&gt;There's an infinite loop to continuously read events from a channel

&lt;ul&gt;
&lt;li&gt;Inside the loop, we launch a coroutine to check if we reached the timeout. This is necessary because a channel's &lt;code&gt;receive&lt;/code&gt; is suspending.&lt;/li&gt;
&lt;li&gt;We read from the events channel while we haven't timed out or reached the desired buffer size. This is done again via &lt;code&gt;receive&lt;/code&gt; and since it's suspending, we need to use &lt;code&gt;withTimeoutOrNull&lt;/code&gt; to ensure it doesn't suspend forever if there are no items in the channel, as we might have elements in the buffer that we have to emit after the timeout.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Finally, since the current implementation of &lt;code&gt;ticker&lt;/code&gt; doesn't respect &lt;a href="https://kotlinlang.org/docs/reference/coroutines/basics.html#structured-concurrency"&gt;structured concurrency&lt;/a&gt; and it's launched in the global scope, we need to make sure to cancel it to avoid a resource leak.&lt;/li&gt;
&lt;li&gt;Note that backpressure is not a problem because by design &lt;code&gt;Channel&lt;/code&gt; will &lt;a href="https://kotlinlang.org/docs/reference/coroutines/channels.html#channel-basics"&gt;suspend the producer&lt;/a&gt; if the consumer is not available to receive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, this is a lot of code with a few undesirable properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mutable variables&lt;/li&gt;
&lt;li&gt;Manual resource management&lt;/li&gt;
&lt;li&gt;Does not easily compose&lt;/li&gt;
&lt;li&gt;Code will probably grow spaghetti over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How can we improve it? There's probably already a bug that I haven't seen and over time that bug might be buried deep in more code. While some of the points can't be helped, can we encapsulate the logic so that it's easy to use? Sounds like it'd be awesome as a Flow operator!&lt;/p&gt;

&lt;h2&gt;
  
  
  Flow operator: bufferTimeout
&lt;/h2&gt;

&lt;p&gt;Wouldn't it be great if we could just use it in the same way as with &lt;code&gt;Flux&lt;/code&gt; so that the code looks like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;consumeAsFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bufferTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ofMillis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received $it"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Taking the previous imperative implementation as a basis, we should be able to encapsulate it as an operator. With a few tweaks, this what I got initially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ExperimentalCoroutinesApi&lt;/span&gt;  
&lt;span class="nd"&gt;@ObsoleteCoroutinesApi&lt;/span&gt;  
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="nf"&gt;bufferTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Window size should be greater than 0"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toMillis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Duration should be greater than 0"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nf"&gt;coroutineScope&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;events&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tickerChannel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toMillis&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;  
                &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;upstreamValues&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;produce&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  

                &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tickerJob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                        &lt;span class="n"&gt;tickerChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="n"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;  
                    &lt;span class="p"&gt;}&lt;/span&gt;  

                    &lt;span class="nf"&gt;withTimeoutOrNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;upstreamValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  
                        &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  
                        &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="n"&gt;tickerJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="n"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tickerChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, the code is pretty much the same as before but there are a few things worth noting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conceptually our operator creates a new &lt;code&gt;Flow&lt;/code&gt; that consumes from the upstream &lt;code&gt;Flow&lt;/code&gt; and &lt;code&gt;emit&lt;/code&gt;s for downstream consumption.&lt;/li&gt;
&lt;li&gt;As we're going to call suspending functions, we need to be in a &lt;code&gt;CoroutineScope&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Instead of receiving from a channel, we need to &lt;code&gt;collect&lt;/code&gt; from the upstream &lt;code&gt;Flow&lt;/code&gt;. As &lt;code&gt;collect&lt;/code&gt; is a terminal operation that will not finish until the upstream is finished, we need to put it in a coroutine, which is what &lt;code&gt;produce { collect { send(it) } }&lt;/code&gt; does while also creating a channel. All the collected values are sent to this channel that we'll drain in the infinite loop.&lt;/li&gt;
&lt;li&gt;The rest is pretty much the same. Instead of &lt;code&gt;while (true)&lt;/code&gt; I'm using &lt;code&gt;while (isActive)&lt;/code&gt; but it doesn't really matter as all the suspending functions that are called support &lt;a href="https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html#cancellation-is-cooperative"&gt;cancellation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Some of the APIs used are either obsolete or experimental, but with no current alternatives AFAIK (coroutines 1.3.6), so this might change in a few months. I suspect &lt;a href="https://kotlinlang.org/docs/reference/coroutines/select-expression.html"&gt;select&lt;/a&gt; could make the code prettier but they're yet another experimental functionality so I thought what we had was enough for now.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That should be it, right? I proceed to write a simple test and run into an issue straight away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ExperimentalCoroutinesApi&lt;/span&gt;  
&lt;span class="nd"&gt;@ObsoleteCoroutinesApi&lt;/span&gt;  
&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OperatorsTest&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StringSpec&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
    &lt;span class="s"&gt;"no emissions with empty flow"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;actualCount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flowOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;bufferTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ofMillis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
        &lt;span class="n"&gt;actualCount&lt;/span&gt; &lt;span class="n"&gt;shouldBe&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// throws ClosedReceiveChannelException: Channel was closed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What the... ? It turns out &lt;code&gt;withTimeoutOrNull(10) { values.receive() }&lt;/code&gt; is not accounting for the case when the channel is closed (upstream is done emitting). There's a &lt;code&gt;receiveOrClosed()&lt;/code&gt; function but it's marked as &lt;code&gt;internal&lt;/code&gt; so we can't use that. I decided to catch the exception and drain any event that might be left in the buffer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// previous loop here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tickerChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now the previous test passes and I continue writing a test to check that the &lt;code&gt;timeout&lt;/code&gt; is respected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="s"&gt;"buffers correctly by timeout"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;firstEmissionTs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;firstItemReceiveTs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;secondItemReceiveTs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;

    &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;firstEmissionTs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bufferTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ofMillis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collectIndexed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;firstItemReceiveTs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;secondItemReceiveTs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Emitted inexistent item"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstItemReceiveTs&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;firstEmissionTs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;shouldBeGreaterThanOrEqual&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondItemReceiveTs&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;firstEmissionTs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;shouldBeGreaterThan&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// test fails randomly for the second assertion:&lt;/span&gt;
&lt;span class="c1"&gt;//   java.lang.AssertionError: 53 should be &amp;gt; 100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Something's off because the second item should be received after the second timeout, which is 50 + 50 = 100. What's going on? It turns out the delay that we specify in &lt;code&gt;withTimeoutOrNull(10)&lt;/code&gt; is important because due to concurrency it could happen we're waiting on &lt;code&gt;withTimeoutOrNull&lt;/code&gt; when the timeout ticker has already passed, meaning that a batch should be emitted. If during this timeout we receive something, a batch is going to be sent with this new item which should actually belong to the next batch. If we add some logs, it may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;withTimeoutOrNull Got 1
withTimeoutOrNull timedout
withTimeoutOrNull timedout
withTimeoutOrNull timedout
withTimeoutOrNull timedout
timeout tick                 -- happens concurrently
withTimeoutOrNull Got 2      -- we were waiting due to delay
start emitting batch         -- batch has 1 and 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Alright, let's take a step back. How do we decide when to emit a batch? When &lt;strong&gt;either&lt;/strong&gt; we got the buffer filled &lt;strong&gt;or&lt;/strong&gt; timeout has passed, whichever condition happens first but &lt;strong&gt;not concurrently&lt;/strong&gt;. Can we somehow select between suspending functions and get the first one that is continued? Yes, we'll finally use the experimental &lt;a href="https://kotlinlang.org/docs/reference/coroutines/select-expression.html"&gt;select expression&lt;/a&gt; we mentioned before! Using that, the code is actually simplified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ExperimentalCoroutinesApi&lt;/span&gt;
&lt;span class="nd"&gt;@ObsoleteCoroutinesApi&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="nf"&gt;bufferTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Window size should be greater than 0"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toMillis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Duration should be greater than 0"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;coroutineScope&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;events&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tickerChannel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toMillis&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;upstreamValues&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;produce&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;

                    &lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;upstreamValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onReceive&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;

                        &lt;span class="n"&gt;tickerChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onReceive&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hasTimedOut&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                        &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ClosedReceiveChannelException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// drain remaining events&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tickerChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And there goes my first attempt at making an operator out of an actual need! To save you from scrolling up again, the final usage is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;someFlow&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bufferTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ofMillis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received batch: $it"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Final remarks
&lt;/h2&gt;

&lt;p&gt;This wasn't exactly easy, concurrency is hard, but it was definitely less scary than attempting to do the same with Rx as suspending channels make the backpressure problem a lot easier. There may be bugs or improvements that I'm not seeing so if you spot anything, I'd really appreciate a comment!&lt;/p&gt;

&lt;p&gt;Thanks for reading and see you next time.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>flow</category>
      <category>coroutines</category>
      <category>reactive</category>
    </item>
    <item>
      <title>Make impossible states impossible - Kotlin edition</title>
      <dc:creator>Pin-Sho Feng</dc:creator>
      <pubDate>Mon, 16 Mar 2020 18:31:36 +0000</pubDate>
      <link>https://forem.com/psfeng/make-impossible-states-impossible-kotlin-edition-189e</link>
      <guid>https://forem.com/psfeng/make-impossible-states-impossible-kotlin-edition-189e</guid>
      <description>&lt;p&gt;Sometimes called "functional domain modelling", there are a bunch of articles and videos titled like that but I haven't found a Kotlin edition, so took the chance and hope it's useful :)&lt;/p&gt;

&lt;p&gt;Let's state our goal clearly again: &lt;strong&gt;make impossible states impossible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What does that mean? In a statically typed language like Kotlin, it means we want to leverage the compiler to ensure that we can only have valid models so that it's impossible to have incorrect cases. In other words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the type system to describe what is possible or not. If something is not possible, it should not compile.&lt;/li&gt;
&lt;li&gt;Another way to look at it is: use types as if they were tests that you won't need to write. Think about &lt;code&gt;nullable&lt;/code&gt; types in Kotlin, for example... if it's not marked with &lt;code&gt;?&lt;/code&gt; you &lt;em&gt;know&lt;/em&gt; it's not &lt;code&gt;null&lt;/code&gt; (unless someone cheated along the way... but you can't control who uses reflection either).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start with an apparently normal example of what could be a user profile in some platform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ACCOUNT_TYPE_BASIC&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ACCOUNT_TYPE_PREMIUM&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ACCOUNT_TYPE_PRIVILEGE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;accountType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;phoneNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What problems can you spot?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: there could be a number within the string. What about the surname? Special characters? What if it's empty?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;age&lt;/code&gt;: can anybody live so long to fill a &lt;code&gt;Long&lt;/code&gt;? Can it be 0? Negative?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;accountType&lt;/code&gt;: what if someone puts a number that's not in our constants list?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;email&lt;/code&gt;: an email needs a specific format, but we could write anything in there and it'd compile.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;phoneNumber&lt;/code&gt;: same...&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;address&lt;/code&gt;: same again...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How could we use the type system to make these cases impossible?&lt;/p&gt;

&lt;p&gt;Let's start with &lt;code&gt;name&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Name
&lt;/h3&gt;

&lt;p&gt;We'd normally have some sort of function that validates the input before putting it into the model, but a &lt;code&gt;String&lt;/code&gt; doesn't reflect any of those validations. What can we do? How about a type that represents a validated name? Let's explore that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// perform some validations on name&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So with a specific type we can represent a validated model. But still, there are problems in the proposed solution...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anyone can just create a &lt;code&gt;UserName&lt;/code&gt;, bypassing &lt;code&gt;createUserName&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It blows in runtime if there's any problem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first case, an attempt could be to make the constructor private:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But then we get a warning telling us that &lt;strong&gt;"private data class constructor is exposed via the generated 'copy' method"&lt;/strong&gt;. Bummer... it's a reported &lt;a href="https://youtrack.jetbrains.com/issue/KT-11914?_ga=2.60279791.356245388.1583944322-2046049152.1549026910"&gt;bug&lt;/a&gt; and it doesn't seem to be a priority for JetBrains. At this point for simplicity I think we could just ignore the warning, rely on convention and call it a day... &lt;/p&gt;

&lt;p&gt;Now, if it still doesn't feel right, we could hack it using some interface magic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IUserName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;

    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;IUserName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// perform some validations on name&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IUserName&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;More verbose than desirable... but it works. Now, there's still the problem of the &lt;code&gt;IllegalArgumentException&lt;/code&gt;. Ideally we want to handle all our cases and make it impossible to blow up. We could use something like &lt;a href="https://arrow-kt.io/docs/apidocs/arrow-core-data/arrow.core/-either/"&gt;Either&lt;/a&gt;, or if we don't want to add Arrow we can just use Java's &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html"&gt;Optional&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IUserName&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform some validations on name&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or since this is Kotlin, you could just make it nullable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;IUserName&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform some validations on name&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For the rest of this post I'll just use the non-interface version for simplicity, but hopefully the point has come across.&lt;/p&gt;

&lt;h3&gt;
  
  
  age
&lt;/h3&gt;

&lt;p&gt;Pretty much the same as for &lt;code&gt;name&lt;/code&gt;, we can create a validated type for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  accountType
&lt;/h3&gt;

&lt;p&gt;For this one we can just use a common construct available in many languages: &lt;code&gt;Enum&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;ACCOUNT_TYPE_BASIC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;ACCOUNT_TYPE_PREMIUM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;ACCOUNT_TYPE_PRIVILEGE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  email, phoneNumber, address
&lt;/h3&gt;

&lt;p&gt;At this point it should be obvious that these fields share the same problem, so we can create validated types for each of them.&lt;/p&gt;

&lt;p&gt;But is that the only problem? Is it possible to have a user that we can't contact in any way? According to the model, this is perfectly valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;profile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;phoneNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We probably want to be able to contact the user right? So maybe we can generalize all of them as a &lt;code&gt;ContactInfo&lt;/code&gt;. Is there any way to express that a &lt;code&gt;ContactInfo&lt;/code&gt; can be "an email, a phone number, or an address"? How would you do that with GraphQL? Hmm... union types? In Kotlin we can represent these with &lt;a href="https://kotlinlang.org/docs/reference/sealed-classes.html"&gt;sealed classes&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// for simplicity, assume that we have factory methods for those data classes and the constructors are private... &lt;/span&gt;
&lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactInfo&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ContactInfo&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;PhoneNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ContactInfo&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ContactInfo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In GraphQL syntax this would be: &lt;code&gt;union ContactInfo = Email | PhoneNumber | Address&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  So everything's validated... is that enough?
&lt;/h3&gt;

&lt;p&gt;Our &lt;code&gt;UserProfile&lt;/code&gt; might look like this now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;accountType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AccountType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;contactInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ContactInfo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Is that OK? Can &lt;code&gt;contactInfo&lt;/code&gt; be empty? We did say 'no' before, didn't we? We could create a special &lt;code&gt;NonEmptyList&lt;/code&gt; type (or use &lt;a href="https://arrow-kt.io/docs/apidocs/arrow-core-data/arrow.core/-non-empty-list/index.html"&gt;Arrow&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;accountType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AccountType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;contactInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NonEmptyList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ContactInfo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now? Hmm... are duplicate &lt;code&gt;ContactInfo&lt;/code&gt;s allowed? 🤔 What's a data structure that can contain only unique elements?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;accountType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AccountType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;contactInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NonEmptySet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ContactInfo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And that's it! (&lt;code&gt;NonEmptySet&lt;/code&gt; is non-standard Java/Kotlin, but should be easy to create)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Making impossible states impossible is about using our data types to represent valid things in our domain, which will ultimately lead to more robust software with less bugs. It's often called "functional domain modelling", probably not because it has anything to do with functional programming per se, but most likely because in the statically-typed functional world we strive for "total functions", which are those that consider all possible inputs and outputs.&lt;/p&gt;

&lt;p&gt;Just asking yourself the question of "does my model allow any illegal state?" will get you a long way!&lt;/p&gt;

&lt;p&gt;Some resources you can check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=1pEffDww4-Q"&gt;Design for errors - An introduction to Domain Modeling with a bit of Arrow by Ivan Morgillo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=PLFl95c-IiU"&gt;Scott Wlaschin - Talk Session: Domain Modeling Made Functional&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=IcgmSRJHu_8"&gt;Making Impossible States Impossible" by Richard Feldman&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;When Kotlin finally gets &lt;a href="https://kotlinlang.org/docs/reference/inline-classes.html"&gt;inline classes&lt;/a&gt;, we'll be able to have zero-cost abstractions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this needs a data class to wrap a String&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// inline classes are basically the underlying primitive,&lt;/span&gt;
&lt;span class="c1"&gt;// verified by the compiler&lt;/span&gt;
&lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>kotlin</category>
      <category>functional</category>
    </item>
    <item>
      <title>Setting up Jenkins on MicroK8s</title>
      <dc:creator>Pin-Sho Feng</dc:creator>
      <pubDate>Tue, 16 Apr 2019 15:59:15 +0000</pubDate>
      <link>https://forem.com/psfeng/setting-up-jenkins-on-microk8s-4b8a</link>
      <guid>https://forem.com/psfeng/setting-up-jenkins-on-microk8s-4b8a</guid>
      <description>&lt;p&gt;I recently bought a mini-pc (MSI Cubi 3 Silent) for home that I use as a server for various purposes and something that I wanted was to set up Jenkins for automatically building and deploying my side projects to my local MicroK8s cluster (Ubuntu Server 18.04).&lt;/p&gt;

&lt;p&gt;It turns out you can install Jenkins on Kubernetes and thanks to &lt;a href="https://github.com/jenkinsci/kubernetes-plugin"&gt;kubernetes-plugin&lt;/a&gt; Jenkins agents will run in ephimeral pods created just for building your task.&lt;/p&gt;

&lt;p&gt;If you know what you have to do, it's actually pretty easy to configure but that's very often the case in hindsight, isn't it? I battled it out for a whole day and here are my findings, should probably take 30 mins to set up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://microk8s.io/"&gt;MicroK8s&lt;/a&gt; cluster (should work with other Kubernetes clusters too), with &lt;strong&gt;storage enabled&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Docker service running on the host (outside Kubernetes)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://helm.sh"&gt;Helm&lt;/a&gt; installed and deployed in Kubernetes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing Jenkins on Kubernetes
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download Jenkins chart values for customization. I'm linking the version I used, but the newest should work.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;wget &lt;span class="nt"&gt;-O&lt;/span&gt; jenkins-chart.yml https://github.com/helm/charts/blob/b22774e2f2019c0e5d8182aab6111a84e95fa8ca/stable/jenkins/values.yaml

&lt;span class="c"&gt;# Edit chart options to use NodePort instead of LoadBalancer, as MicroK8s doesn't&lt;/span&gt;
&lt;span class="c"&gt;# ship with any: https://github.com/ubuntu/microk8s/issues/200#issuecomment-441180273&lt;/span&gt;
&lt;span class="c"&gt;# &lt;/span&gt;
&lt;span class="c"&gt;# ServiceType: NodePort&lt;/span&gt;
&lt;span class="c"&gt;# NodePort: 32000 (optional, if you want to have a fixed one for exposing it externally)&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Alternatively, if you have Ingress enabled on MicroK8s you could &lt;/span&gt;
&lt;span class="c"&gt;# use ServiceType: ClusterIP and add a rule in your Ingress configuration to&lt;/span&gt;
&lt;span class="c"&gt;# direct traffic to Jenkins.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;vim jenkins-chart.yml

&lt;span class="nv"&gt;$ &lt;/span&gt;helm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; jenkins &lt;span class="nt"&gt;-f&lt;/span&gt; jenkins-chart.yaml stable/jenkins

&lt;span class="c"&gt;# Follow the instructions to retrieve the generated password.&lt;/span&gt;
&lt;span class="c"&gt;# If you need to uninstall Jenkins, then&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;helm del &lt;span class="nt"&gt;--purge&lt;/span&gt; jenkins
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point, Jenkins should be accessible at &lt;a href="http://your-server:32000"&gt;http://your-server:32000&lt;/a&gt;. I then installed the Blue Ocean plugin as I find it more aesthetically pleasant plus it's designed for the &lt;a href="https://jenkins.io/doc/book/pipeline/"&gt;Jenkins Pipeline&lt;/a&gt;. Installing it is as easy as going to &lt;strong&gt;Manage Plugins&lt;/strong&gt; and checking the &lt;strong&gt;Blue Ocean&lt;/strong&gt; box. You don't need to check the other ones, they'll be added automatically as dependencies.&lt;/p&gt;

&lt;p&gt;Now we're ready to create our first pipeline!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Github pipeline
&lt;/h2&gt;

&lt;p&gt;Let's assume we want to create a pipeline for a private repository we've got at Github. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Follow the instructions &lt;a href="https://jenkins.io/doc/book/blueocean/creating-pipelines/"&gt;here&lt;/a&gt; but skip the final pipeline creation wizard, as we're going to use a &lt;a href="https://jenkins.io/doc/book/pipeline/jenkinsfile/"&gt;Jenkinsfile&lt;/a&gt; with the &lt;a href="https://jenkins.io/doc/book/pipeline/syntax/#declarative-pipeline"&gt;declarative pipeline&lt;/a&gt; syntax instead.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;webhook&lt;/strong&gt; in your Github repo pointing to &lt;a href="http://your-server:32000/github-webhook/"&gt;http://your-server:32000/github-webhook/&lt;/a&gt; (customize with your domain/port/https, and keep the trailing slash) and verify that it's working (the secret doesn't matter). Theoretically this should be done automatically by Blue Ocean in step 1, but it didn't work for me. Note that if you're using a firewall or you're in a private network, you'll have to open the port and/or forward it to your server appropriately.&lt;/li&gt;
&lt;li&gt;Create a file named &lt;strong&gt;Jenkinsfile&lt;/strong&gt; at the root of the repository. I'm going to assume you've got a dockerized app and you've got the Kubernetes deployment files well configured.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Jenkinsfile&lt;/span&gt;

&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;kubernetes&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// this label will be the prefix of the generated pod's name&lt;/span&gt;
      &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="s1"&gt;'jenkins-agent-my-app'&lt;/span&gt;
      &lt;span class="n"&gt;yaml&lt;/span&gt; &lt;span class="s2"&gt;"""
apiVersion: v1
kind: Pod
metadata:
  labels:
    component: ci
spec:
  containers:
    - name: docker
      image: docker
      command:
        - cat
      tty: true
      volumeMounts:
        - mountPath: /var/run/docker.sock
          name: docker-sock
    - name: kubectl
      image: lachlanevenson/k8s-kubectl:v1.14.0 # use a version that matches your K8s version
      command:
        - cat
      tty: true
  volumes:
    - name: docker-sock
      hostPath:
        path: /var/run/docker.sock
"""&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Build image'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'docker'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"docker build -t your-registry/my-app:latest ."&lt;/span&gt;
          &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"docker push your-registry/my-app:latest"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Deploy'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'kubectl'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"kubectl delete -f ./kubernetes/deployment.yaml"&lt;/span&gt;
          &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"kubectl apply -f ./kubernetes/deployment.yaml"&lt;/span&gt;
          &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"kubectl apply -f ./kubernetes/service.yaml"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Commit and push it to your repository. Jenkins should be notified and a build should be starting!&lt;/p&gt;

&lt;h3&gt;
  
  
  A few things to note from the Jenkinsfile
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;docker&lt;/code&gt; and &lt;code&gt;kubectl&lt;/code&gt; containers declared are so that we can run these commands in the pipeline without having them installed in the host, which is typically what you'd do with Jenkins outside Kubernetes.&lt;/li&gt;
&lt;li&gt;We're using the host's Docker daemon, which is why it was a prerequisite and the reason we defined &lt;code&gt;docker-sock&lt;/code&gt; with &lt;code&gt;path: /var/run/docker.sock&lt;/code&gt;. If you don't want to need to have Docker in your host, you could try &lt;a href="https://medium.com/hootsuite-engineering/building-docker-images-inside-kubernetes-42c6af855f25"&gt;Docker in Docker&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;We're using &lt;a href="https://github.com/lachie83/k8s-kubectl/blob/v1.14.0/Dockerfile"&gt;lachlanevenson/k8s-kubectl&lt;/a&gt;, which is a very simple image with just &lt;code&gt;kubectl&lt;/code&gt;. You could use any other image with &lt;code&gt;kubectl&lt;/code&gt;, but make sure the image doesn't run with another user id or you'll have permission issues with Jenkins. I know it from the experience of trying to use &lt;a href="https://github.com/bitnami/bitnami-docker-kubectl/blob/ee7364cd186dfcf0bbb18dd0ad6b3e16ddadf564/1.14/debian-9/Dockerfile#L16"&gt;bitnami/kubectl&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You might wonder why we've got &lt;code&gt;command: cat&lt;/code&gt; and &lt;code&gt;tty: true&lt;/code&gt;. They &lt;a href="https://github.com/jenkinsci/kubernetes-plugin#constraints"&gt;avoid containers exiting early&lt;/a&gt;. To be honest, I don't know exactly how it works.&lt;/li&gt;
&lt;li&gt;There's no specific step for &lt;code&gt;git&lt;/code&gt;. If you use webhooks, the git step is automagically added when a push event is received.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other things of interest
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If you have submodules, make sure you check &lt;strong&gt;Recursively update submodules&lt;/strong&gt; in your Jenkins repo build configuration, under &lt;strong&gt;Advanced sub-modules behaviours&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You might notice 'zombie' processes (see &lt;code&gt;top&lt;/code&gt; command) as builds are executed. I don't know why this happens but it could be a bug in Jenkins or Docker. It doesn't happen consistently though.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;Configuring Jenkins might seem a very daunting task and it's certainly not obvious. With Kubernetes and Helm I believe it's much simpler but still it's difficult to find easily reproducible instructions.&lt;/p&gt;

&lt;p&gt;If you're setting a Jenkins environment without an existing Kubernetes cluster completely from scratch, you might want to have a look at &lt;a href="https://jenkins-x.io/"&gt;Jenkins X&lt;/a&gt;. Otherwise, I hope this guide works for you. &lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

</description>
      <category>jenkins</category>
      <category>kubernetes</category>
      <category>microk8s</category>
      <category>docker</category>
    </item>
    <item>
      <title>Dependency injection in functional programming</title>
      <dc:creator>Pin-Sho Feng</dc:creator>
      <pubDate>Sun, 13 Jan 2019 19:54:44 +0000</pubDate>
      <link>https://forem.com/psfeng/dependency-injection-in-functional-programming-3gg4</link>
      <guid>https://forem.com/psfeng/dependency-injection-in-functional-programming-3gg4</guid>
      <description>&lt;h1&gt;
  
  
  Dependency injection in functional programming (Kotlin)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;DI in FP can be achieved using partial function application or the Reader monad&lt;/li&gt;
&lt;li&gt;But DI may not make sense in FP&lt;/li&gt;
&lt;li&gt;An OO-FP-OO sandwich where the domain core is purely functional but the outer layers are OO and use a dependency injector could be a good approach for applications which have a lot of side-effects.&lt;/li&gt;
&lt;li&gt;All solutions have pros and cons, final choice depends on the task at hand and personal preference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I started looking into functional programming, I kept wondering how DI works in this paradigm and was surprised to find that there are not many articles written about it, especially for beginners, so I decided I could try to help in filling that void by sharing what I've learnt. Therefore, the target of this article are the developers that have started looking into the functional paradigm and wonder how dependency injection works there, so I'll try to introduce every topic without assuming much prior knowledge. The language I use is Kotlin, though the principles are universal. The article should preferrably be read from top to bottom, as the explanation of the concepts follow a logical order. Let's start!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why functional programming?
&lt;/h2&gt;

&lt;p&gt;Like many developers, the past couple of years I started gaining a lot of interest in functional programming due to all the problems I've seen in practice with mutable state. As an Android developer for the past 5 years, I've experimented these problems with the wide adoption of the MVP architecture. At the time it was all the rage as it allowed us to move away from untestable God-Activities/Fragments and have the presentation logic delegated to testable Presenters. As new features were implemented and requirements changed, our presenters would start to look like the old huge activities/fragments, and making any change would become increasingly dangerous, as presenters modify the view in imperative style (e.g. &lt;code&gt;view.showLoading()&lt;/code&gt;) and multiple view-changing functions were in place. We'd split the presenters further but still, the complexity of not knowing if a change would affect something else was there. There had to be a better way!&lt;/p&gt;

&lt;p&gt;One day I was still in the office (XING Barcelona) while a meetup was held in which the speaker was introducing &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; to the audience. I'm glad I decided to stay as it ultimately inspired me and got me to learn about functional programming. I started digging and discovered that Redux was partly inspired by Elm and then I started checking Elm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt; is an awesome pure functional language that tries very hard to be beginner friendly and while I think it does a great job, the paradigm shift is still enourmous. It's not so much the syntax itself, but the mindset change from an imperative to a functional one (to the Android folks, do you remember when you started with RxJava?). After some practice I began feeling comfortable with Elm, but I still remembered a conversation with a colleague in which he was trying to explain "monads" to me (Elm doesn't have them). No matter how many articles I'd read (including &lt;a href="http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html"&gt;this one with pictures&lt;/a&gt;) I still wouldn't get it. The thing is that most, if not all articles focus on the "what", but not "why" we need monads. That's when I decided to go all-in and teach myself Haskell.&lt;/p&gt;

&lt;p&gt;After reading &lt;a href="http://learnyouahaskell.com/"&gt;LYAH&lt;/a&gt; and chunks of &lt;a href="http://haskellbook.com/"&gt;Haskell Programming&lt;/a&gt; (amazing book btw) I decided to do some practice by building an &lt;a href="https://github.com/ps-feng/arnoldh"&gt;ArnoldC compiler&lt;/a&gt; for fun. The experience was very rewarding, even if I end up never using Haskell professionally. It's forever changed the way I look at code but while I do know what a monad is now, I'm also convinced that type classes (functors, applicatives, monads...) are &lt;a href="https://stackoverflow.com/a/28141248/328616"&gt;not essential&lt;/a&gt; to functional programming, as Elm or Elixir show. &lt;a href="https://package.elm-lang.org/help/design-guidelines#avoid-gratuitous-abstraction"&gt;Abstraction is a tool, not a goal&lt;/a&gt;! I'm aware this is opinionated and others may have a different opinion, which is fine. I think that type classes are especially useful for library writers when they strive to provide generic solutions but end-user application features rarely need such level of abstractions. &lt;/p&gt;

&lt;p&gt;Joe Armstrong said &lt;a href="http://harmful.cat-v.org/software/OO_programming/why_oo_sucks"&gt;"state is the root of all evil"&lt;/a&gt; and I subscribe to it. I've concluded that with these 2 principles you can get very far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immutability&lt;/li&gt;
&lt;li&gt;Referential transparency (for a given input, you get the same output always with no side-effects)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As long as your programming language has first-class/top-level functions, just applying those 2 principles can get you a long way.&lt;/p&gt;

&lt;p&gt;Pure functions excel at transforming data. For any given input, it'll return the same output, without side effects. This makes functional programming suitable for applications that resemble pipelines in which the input data is transformed through various stages. Examples of such applications are parsers, compilers, data analysis, etc. &lt;/p&gt;

&lt;p&gt;But what about UI or CRUD applications? These sort of applications are basically full of side-effects. How can we fit a functional programming paradigm here? Doesn't this go against the 2 principles mentioned before?&lt;/p&gt;

&lt;p&gt;So in the quest for trying to use functional programming to solve the same problems I've been running into the past few years, I've tried to force myself to strictly apply functional programming and see how it goes.&lt;/p&gt;

&lt;p&gt;I built a &lt;a href="https://github.com/ps-feng/sample-fp-di"&gt;sample server application&lt;/a&gt; in Kotlin to test the waters, having the 2 principles above in mind. It's a very simple Spring Boot application that exposes an endpoint that returns some data. Internally, the app will call another endpoint and process the results before returning a response. Fairly standard.&lt;/p&gt;

&lt;p&gt;To be functional I followed these guidelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use only functions, avoiding classes except for the glue initialization code. Having no classes and just functions encourages you to think in terms of data transformation and avoid state.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;val&lt;/code&gt; and immutable data structures (&lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;List&lt;/code&gt;...).&lt;/li&gt;
&lt;li&gt;Avoid side effects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I followed Clean Architecture and separated my code in 3 logical layers: presentation, domain and data. When the server receives a request, the logic will flow like&lt;/p&gt;

&lt;p&gt;&lt;code&gt;request handler -&amp;gt; interactor -&amp;gt; external services&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All good. But then I ran into a problem... How do I achieve DI? My interactors (domain) are no longer classes so I can't inject them the repositories that they should be calling.&lt;/p&gt;

&lt;p&gt;If you look up "functional programming dependency injection" in Google, you'll find that there's (perhaps) surprisingly very little literature written on the topic. I may have an idea why that's the case but bear with me and keep reading! I'll be covering two of the most typical approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Partial function application&lt;/li&gt;
&lt;li&gt;Reader monad&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other styles that can help you achieve similar goals, such as the tagless-final pattern or free monads, but I'm not going to cover them in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency injection goals
&lt;/h2&gt;

&lt;p&gt;Before we look at functional programming's solutions to DI, let's take a step back and reflect on the problem that we're trying to solve. Without going into too much detail, we could summarize the DI goals as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inversion of Control and loose coupling. Implementations don't choose their dependencies. This allows the caller to supply the specific implementations of these dependencies, allowing the behavior of the code to be configured externally. Typically, this is done by making classes depend on interfaces, the implementations of which are passed-in via constructor.&lt;/li&gt;
&lt;li&gt;Unit testing. This derives from the previous goal, as it allows us to inject mock implementations into the class under test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a look at how we might achieve these goals with functional programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Partial function application
&lt;/h2&gt;

&lt;p&gt;Partial function application is a very cool concept in functional programming that consists in passing some of the parameters to a function and getting a function that accepts the rest of the parameters in return. This concept derives from &lt;a href="https://stackoverflow.com/q/218025/328616"&gt;&lt;em&gt;currying&lt;/em&gt;&lt;/a&gt;, which is a technique by which any function of &lt;em&gt;N&lt;/em&gt; arguments can be translated into a sequence of &lt;em&gt;N&lt;/em&gt; functions of 1 argument. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// returns 3&lt;/span&gt;

&lt;span class="c1"&gt;// can be converted into a function that accepts 1 argument (a)&lt;/span&gt;
&lt;span class="c1"&gt;// and returns another function that accepts 1 argument (b)&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;sum1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;sum1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// returns 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;How can this help us? Imagine that we want to be able to inject different loggers into a function. We might want one that simply prints its output to the console or we might want another one that stores the log in a file. We can partially apply the function with the logger and the resulting function won't need the logger parameter anymore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;typealias&lt;/span&gt; &lt;span class="nc"&gt;ItemFetcherFn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchItemsLogged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ItemFetcherFn&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fetching items"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// fetch and return items...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// let's use partial application to "inject" some logger&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;consoleLogger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ItemFetcherFn&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchItemsLogged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consoleLogger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// we can now use fetchItems anywhere, without knowing it has a logger&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ItemFetcherFn&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;onStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This technique was the one I used in the master branch of my &lt;a href="https://github.com/ps-feng/sample-fp-di"&gt;sample project&lt;/a&gt;. As I mentioned before, I separated the code in 3 logical layers (clean architecture style): presentation (or controllers), domain and data. If you remember the &lt;a href="http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"&gt;dependency rule&lt;/a&gt;, the inner layer cannot access the outer layer. Our inner layer is the domain layer, so it shouldn't have references to the presentation and the data layer (note that a Repository is considered an interface to the data layer, and the domain can reference interfaces). With this in mind, let's analyze our example starting with the data layer's &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/d2225432bc79533d50d3dfb3320e3a4918cda702/src/main/kotlin/com/sample/todos/data/Services.kt"&gt;Services.kt&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getUserTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;WebClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uri&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;uriBuilder&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;uriBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users/$userId/todos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bodyToMono&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;ParameterizedTypeReference&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DataTodo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;dataTodos&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dataTodos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDomain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;From the domain layer's perspective, this function has a &lt;code&gt;baseUrl&lt;/code&gt;, which is clearly a data layer detail. From the domain we shouldn't be concerned about where we get the data from. If we were using OO, this function would be encapsulated in a Repository object and &lt;code&gt;baseUrl&lt;/code&gt; could be injected via constructor, so the function signature that the domain layer would end up using is &lt;code&gt;fun getUserTodos(userId: Int)&lt;/code&gt;. How can we achieve this in functional programming style? Using partial function application! We could partially apply &lt;code&gt;baseUrl&lt;/code&gt;. Let's see how this looks in practice for &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/d2225432bc79533d50d3dfb3320e3a4918cda702/src/main/kotlin/com/sample/todos/domain/Interactors.kt"&gt;Interactors.kt&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;typealias&lt;/span&gt; &lt;span class="nc"&gt;TodoFetcherFn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCompletedTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TodoFetcherFn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isCompleted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our domain function depends on a function of type &lt;code&gt;TodoFetcherFn&lt;/code&gt; that takes a &lt;code&gt;userId&lt;/code&gt; and returns a &lt;code&gt;Mono&amp;lt;List&amp;lt;Todo&amp;gt;&amp;gt;&lt;/code&gt;. We're not depending on any specific implementation and as such the function is unit testable, so we achieved our DI goals. As long as we pass in a function that complies with this signature, we're good to go!&lt;/p&gt;

&lt;p&gt;Let's see how this function is partially applied and "injected". This is &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/d2225432bc79533d50d3dfb3320e3a4918cda702/src/main/kotlin/com/sample/todos/Todos.kt"&gt;Todos.kt&lt;/a&gt; from the controller layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ServerRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TodoFetcherFn&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pathVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;todosResponseMono&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="nf"&gt;getCompletedTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onErrorResume&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;internalServerError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todosResponseMono&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GetTodosResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;badRequest&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;syncBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id is not an integer"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And finally this is the injection root (&lt;a href="https://github.com/ps-feng/sample-fp-di/blob/2a78da39b991769c84015096c56b40fd87a3d17f/src/main/kotlin/com/sample/SampleApplication.kt"&gt;SampleApplication.kt&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt; &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TODOS_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;todosBaseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;RouterFunction&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;router&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;nest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/user/{id}/completedtodos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;getTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;getTodosFetcherFn&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getTodosFetcherFn&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;TodoFetcherFn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;getUserTodos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partially1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todosBaseUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The sample is using &lt;a href="https://arrow-kt.io"&gt;Arrow&lt;/a&gt; to partially apply the first argument of &lt;code&gt;getUserTodos&lt;/code&gt; (baseUrl). This function is then passed to the route handler, which then calls the interactor function with it.&lt;/p&gt;

&lt;p&gt;Using partial function application we've successfully achieved FP's version of dependency injection. However, you might have some questions.&lt;/p&gt;

&lt;h5&gt;
  
  
  How do you test the route handler (&lt;code&gt;getTodos&lt;/code&gt;) in isolation?
&lt;/h5&gt;

&lt;p&gt;Fair question. If you want to test &lt;code&gt;getTodos&lt;/code&gt;, you'd inevitably test &lt;code&gt;getCompletedTodos&lt;/code&gt; as well as it makes a direct call to it. My advice is to not test it in isolation, &lt;a href="https://blog.twitter.com/engineering/en_us/topics/insights/2017/the-testing-renaissance.html"&gt;test the whole feature&lt;/a&gt;. Just use a &lt;a href="https://github.com/square/okhttp/tree/master/mockwebserver"&gt;mock web server&lt;/a&gt; and test the whole feature end-to-end. There are many benefits to &lt;a href="https://blog.kentcdodds.com/write-tests-not-too-many-mostly-integration-5e8c7fff591c"&gt;this approach&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Still, this is my opinion and you may not agree. If you really want to test it separately, you could make &lt;code&gt;getTodos&lt;/code&gt; depend on a function that you'd pass in instead of having it call &lt;code&gt;getCompletedTodos&lt;/code&gt; directly. I accidentally did that in a &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/d2225432bc79533d50d3dfb3320e3a4918cda702/src/main/kotlin/com/sample/todos/Todos.kt"&gt;previous commit&lt;/a&gt;, so you could check how it'd work. Note that that implementation is wrong, the &lt;code&gt;fetchTodos&lt;/code&gt; function that's passed in should have a signature separate from &lt;code&gt;TodoFetcherFn&lt;/code&gt; from the domain layer, even if they look the same, so that we keep the functions independent.&lt;/p&gt;

&lt;h5&gt;
  
  
  If you have 5 dependencies, do you pass 5 arguments down?
&lt;/h5&gt;

&lt;p&gt;My example is unrealistic as any real application will likely have more dependencies than that. For simplicity I'm just passing the function that I know I'll use, but you could construct a composition root in which you partially apply the functions that will have to be called as we go through the layers. Then you only have to pass the functions that will have to be called in the immediately next layer. Check how this works &lt;a href="https://fsharpforfunandprofit.com/posts/dependency-injection-1/"&gt;here&lt;/a&gt;. Another approach would be to pass a single argument with all the dependencies, which is what you'd do with the Reader monad.&lt;/p&gt;

&lt;h5&gt;
  
  
  The dependencies appear as arguments in the function signature of all functions in the call chain
&lt;/h5&gt;

&lt;p&gt;Indeed. Whether that's cool or not is subjective, but there's a technique in functional programming that allows us to pass an argument implicitly so that it disappears from the argument list of your functions. Meet the Reader monad in the next section!&lt;/p&gt;

&lt;h5&gt;
  
  
  Code navigation is more difficult as cmd + click doesn't work on partial function signatures
&lt;/h5&gt;

&lt;p&gt;Yes. If you think about it, the key idea of using partial application for DI is loose coupling, so you're not supposed to know which function was originally partially applied. If we organize the code in a way that we don't have deeply nested calls of partially applied functions, it should be simple to find the root.&lt;/p&gt;

&lt;p&gt;I hope I managed to explain the technique in an understandable way, but if it's not enough or if you simply would like to see another take, there's an &lt;a href="https://fsharpforfunandprofit.com/posts/dependency-injection-1/"&gt;awesome article&lt;/a&gt; by Scott Wlaschin explaining it with a more complex example.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reader monad
&lt;/h2&gt;

&lt;p&gt;We've found that passing the same argument down a chain of functions can be (subjectively) annoying. I mentioned that the Reader monad can allow us to pass that argument implicitly... how's that possible? We could put it in some global value and access it directly where needed. We no longer need to pass it to any function! But then this is just hardcoding and beats completely the purpose of dependency injection, in case we lost sight of our initial goals.&lt;/p&gt;

&lt;p&gt;Alright, so what is the Reader monad about? To properly understand it we'd first need to understand &lt;a href="https://stackoverflow.com/q/44965/328616"&gt;what&lt;/a&gt;'s a monad and &lt;a href="https://stackoverflow.com/q/28139259/328616"&gt;why&lt;/a&gt; do we need it. Before that, you'd need to be introduced to functors and applicatives. It personally took me a lot of time to figure it out, even after reading many explanations and seeing them represented as &lt;a href="http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html"&gt;pictures&lt;/a&gt;. I actually never got it until I actually used them in practice, so I'm not going to attempt to explain all the concepts here.&lt;/p&gt;

&lt;p&gt;Instead, let's see if we can build an intuition about it. We can start by stating our goals clearly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pass an argument to all functions in a call chain&lt;/li&gt;
&lt;li&gt;Do so without explicitly having it in the parameters list of these functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we call a function that returns a value, we get that value straight away. However, if we want to &lt;strong&gt;defer&lt;/strong&gt; this computation, we can wrap that value in a function and return it. Then we won't get the value until we call this returned function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;giveMe5&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;deferGiveMe5&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;giveMe5&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// returns 5&lt;/span&gt;
&lt;span class="nf"&gt;deferGiveMe5&lt;/span&gt;&lt;span class="p"&gt;()()&lt;/span&gt; &lt;span class="c1"&gt;// returns 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What if we connected a bunch of functions that return functions that take the same input? The result would be a function chain that wouldn't be evaluated until we actually call it and then we can pass some input down the chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;delegateNum&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;furtherDelegateNum&lt;/span&gt;&lt;span class="p"&gt;()(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;furtherDelegateNum&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;printNum&lt;/span&gt;&lt;span class="p"&gt;()(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;printNum&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;chain&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;delegateNum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;5&lt;/code&gt; in this case would be the "thing" that we want to inject down the chain. It could be the dependency that we need to make available to all the functions in it and it's implicit! So we achieved the goals we set before.&lt;/p&gt;

&lt;p&gt;Now, notice how &lt;code&gt;delegateNum()&lt;/code&gt;, &lt;code&gt;furtherDelegateNum()&lt;/code&gt; and &lt;code&gt;printNum()&lt;/code&gt; have the same structure. It turns out we can abstract this and this is loosely speaking what the Reader monad is about! Create a lazy (as in deferred evaluation) chain of functions that can &lt;em&gt;read&lt;/em&gt; a common value, and then run this chain passing the value that we want.&lt;/p&gt;

&lt;p&gt;Hopefully at this point I managed to give you an idea of the Reader monad, so let's see it with a real example. I didn't create a version of our example but we can use &lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/tree/master/monad-stack"&gt;one&lt;/a&gt; from Jorge Castillo that shares a similar architecture to the one I used previously, although his example is an Android app. In his example he's fetching a list of superheroes from some endpoint. Let's check the &lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/blob/ea4f1702eac15860a468f4cf14fcb39ef408da73/monad-stack/src/main/java/com/github/jorgecastillo/kotlinandroid/data/datasource/remote/MarvelNetworkDataSource.kt"&gt;data source&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// MarvelNetworkDataSource.kt&lt;/span&gt;

&lt;span class="cm"&gt;/*&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="cm"&gt; * This is the network data source. Calls are made using Karumi's MarvelApiClient.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="cm"&gt; * @see "https://github.com/Karumi/MarvelApiClientAndroid"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="cm"&gt; *&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="cm"&gt; * Both requests return a new Reader enclosing an action to resolve when you provide them with the&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="cm"&gt; * required execution context.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchAllHeroes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetHeroesContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nc"&gt;ReaderApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetHeroesContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monadDefer&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;binding&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runInAsyncContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;queryForHeroes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;onError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raiseError&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;onSuccess&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;just&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nc"&gt;AC&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threading&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The value that's passed down through his function chain is &lt;code&gt;ctx&lt;/code&gt;, which is of type &lt;code&gt;GetHeroesContext&lt;/code&gt;, which is a data class with all the dependencies that this chain needs (see &lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/blob/ea4f1702eac15860a468f4cf14fcb39ef408da73/monad-stack/src/main/java/com/github/jorgecastillo/kotlinandroid/di/context/SuperHeroesContext.kt"&gt;SuperHeroesContext.kt&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This function is called from &lt;code&gt;getHeroes&lt;/code&gt;(HeroesRepository), which is called from &lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/blob/ea4f1702eac15860a468f4cf14fcb39ef408da73/monad-stack/src/main/java/com/github/jorgecastillo/kotlinandroid/domain/usecase/HeroesUseCases.kt"&gt;HeroesUseCases.kt&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getHeroesUseCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getHeroes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NetworkOnly&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;discardNonValidHeroes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which is then called from &lt;code&gt;getSuperHeroes&lt;/code&gt;(&lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/blob/ea4f1702eac15860a468f4cf14fcb39ef408da73/monad-stack/src/main/java/com/github/jorgecastillo/kotlinandroid/presentation/SuperHeroesPresentation.kt#L39"&gt;SuperHeroesPresentation.kt&lt;/a&gt;), which is finally called from &lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/blob/ea4f1702eac15860a468f4cf14fcb39ef408da73/monad-stack/src/main/java/com/github/jorgecastillo/kotlinandroid/view/SuperHeroListActivity.kt#L43"&gt;SuperHeroListActivity.kt&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onResume&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onResume&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;getSuperHeroes&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;heroesContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice how &lt;code&gt;heroesContext&lt;/code&gt; is passed down the function chain through the &lt;code&gt;run&lt;/code&gt; function and how there's no trace of it in the parameters of the functions in the chain.&lt;/p&gt;

&lt;p&gt;So this is how you do DI with the Reader monad! If you feel the need for a more technical explanation, check &lt;a href="https://medium.com/@JorgeCastilloPr/kotlin-dependency-injection-with-the-reader-monad-7d52f94a482e"&gt;this post&lt;/a&gt; from the author himself.&lt;/p&gt;

&lt;p&gt;Now, you might again have some questions...&lt;/p&gt;

&lt;h5&gt;
  
  
  How do you decide between the Reader monad and partial application?
&lt;/h5&gt;

&lt;p&gt;This is a &lt;a href="https://stackoverflow.com/q/42780191/328616"&gt;common question&lt;/a&gt;. The main reason people usually use the Reader monad is to avoid passing the same argument over and over again. Still, this may be subjective. &lt;/p&gt;

&lt;p&gt;I said in the introduction that in my opinion these sort of abstractions (typeclasses) are not strictly necessary and we have an alternative to it, but whether you prefer it or not is subjective to a certain point. I personally don't currently feel I need them with the approach that I'll suggest later (I will tell you about it below, keep reading!).&lt;/p&gt;

&lt;h5&gt;
  
  
  Aren't we coupling all the functions in the Reader chain to the value that we're passing?
&lt;/h5&gt;

&lt;p&gt;I think so... any function in the chain will be able to access the value that we're passing. In the example above, any of these functions has access to &lt;code&gt;GetHeroesContext&lt;/code&gt;. I'll go in more detail in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  A critical view
&lt;/h2&gt;

&lt;p&gt;We've seen 2 ways of achieving DI in functional programming, but while we did achieve the goals that we set in the beginning, is this way of doing things better than having a dependency injection framework in OO style?&lt;/p&gt;

&lt;p&gt;Regarding partial function application, a user named Onur left a &lt;a href="https://fsharpforfunandprofit.com/posts/dependency-injection-1/#comment-3058806603"&gt;thought-provoking comment&lt;/a&gt; in the Scott Wlaschin's article that I already mentioned before:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a much needed article unfortunately it misses the point. Normally, objects are not composable. Dependency Injection is a cure for that. Just like functional programming uses functions to build larger programs, dependency injection is used to build larger object programs. In your examples, dependencies are only represented in 1 level but there can be far more deep hierarchies. Secondly, dependency injection registration is a way to achieve inversion of control, such that the components don't create themselves, but registrations are like a recipe that describes the dependencies and hierarchy and &lt;strong&gt;is external to the application&lt;/strong&gt;. Thirdly, dependency injection also incorporates to the &lt;strong&gt;life times of the components&lt;/strong&gt;. Finally, &lt;strong&gt;all of these imply impurity&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is indeed very true. The composition root in our case is arguably &lt;em&gt;not&lt;/em&gt; external to our application. &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/2a78da39b991769c84015096c56b40fd87a3d17f/src/main/kotlin/com/sample/SampleApplication.kt#L40"&gt;We've got it in our router function&lt;/a&gt;. We could tuck it away by putting it into some other file, but we still need to manually define the partial function applications that we want to pass to our specific entry function, whereas with a DI framework we'd simply define the provider functions somewhere and then simply declare what we want to use in the constructors.&lt;/p&gt;

&lt;p&gt;Lifetime is another thing... lifetime as such doesn't make sense in a pure context but things such as a database connection have a lifetime. So DI implies impurity, does it make sense to try to do it in the functional world?&lt;/p&gt;

&lt;p&gt;Let's come back to the last concern of the previous section. Isn't using the Reader monad in our example implying that we're coupling all our functions in the chain to the dependency context that we're passing? Let's check &lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/blob/ea4f1702eac15860a468f4cf14fcb39ef408da73/monad-stack/src/main/java/com/github/jorgecastillo/kotlinandroid/di/context/SuperHeroesContext.kt"&gt;SuperHeroesContext&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroesContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;heroDetailsPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HeroDetailsPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;apiClient&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CharacterApiClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MarvelApiConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;BuildConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MARVEL_PUBLIC_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;BuildConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MARVEL_PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;threading&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;async&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;GetHeroesContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroesListView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroesContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;GetHeroDetailsContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroDetailView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroesContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This context has 5 dependencies. Let's see &lt;a href="https://github.com/JorgeCastilloPrz/ArrowAndroidSamples/blob/ea4f1702eac15860a468f4cf14fcb39ef408da73/monad-stack/src/main/java/com/github/jorgecastillo/kotlinandroid/data/datasource/remote/MarvelNetworkDataSource.kt"&gt;MarvelNetworkDataSource.kt&lt;/a&gt; again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchAllHeroes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetHeroesContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nc"&gt;ReaderApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetHeroesContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monadDefer&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;binding&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runInAsyncContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;queryForHeroes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;onError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raiseError&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;onSuccess&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;just&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nc"&gt;AC&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threading&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can see that we're accessing &lt;code&gt;ctx.threading&lt;/code&gt; and &lt;code&gt;ctx&lt;/code&gt; is passed to &lt;code&gt;queryForHeroes&lt;/code&gt;, which internally accesses &lt;code&gt;apiClient&lt;/code&gt;. But what's impeding us to also access &lt;code&gt;ctx.view&lt;/code&gt; or &lt;code&gt;ctx.heroesDetailPage&lt;/code&gt;? Should those be available to the data layer? I think we're violating the &lt;a href="%5Bdependency%20rule%5D%28http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html%29"&gt;dependency rule&lt;/a&gt;. Besides that, generally speaking it's a good idea to strive for "making impossible states impossible" (see talks by &lt;a href="https://www.youtube.com/watch?v=IcgmSRJHu_8"&gt;Richard Feldman&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=P7dTPoxCg4w"&gt;Patrick Stapfer&lt;/a&gt;, or &lt;a href="https://dev.to/stereobooster/pragmatic-types-making-impossible-states-impossible-inh"&gt;this article&lt;/a&gt;). If we can't access &lt;code&gt;ctx.view&lt;/code&gt;, there's no way we can do anything about it!&lt;/p&gt;

&lt;p&gt;We've showed that we can achieve DI with partial function application or the Reader monad, but the question is, should we?&lt;/p&gt;

&lt;h2&gt;
  
  
  OO-FP-OO, a hybrid approach
&lt;/h2&gt;

&lt;p&gt;Let's remind ourselves of the things we like most about functional programming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immutability. Once a data value is created, we can never modify it.&lt;/li&gt;
&lt;li&gt;Referential transparency. Given a function and an input value, you receive the same output, without side effects, &lt;em&gt;every single time&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These properties make it easier to reason about programs, as you can be sure about the behavior being consistent. If the language is statically typed, &lt;a href="http://www.haskellforall.com/2013/12/equational-reasoning.html"&gt;equational reasoning&lt;/a&gt; becomes possible. This is going to make us have less bugs and less cognitive load, as your thought context should just be the function you have in front.&lt;/p&gt;

&lt;p&gt;Typical Android applications or backend CRUD services are full of side effects. You need to access the network or a database to retrieve some data, and then you need to modify the UI to display this data or return some Json response. On top of that, like most languages Kotlin does not have a way to enforce referential transparency, so you can use any typeclass that &lt;a href="https://arrow-kt.io/"&gt;Arrow&lt;/a&gt; provides but there's nothing preventing you from doing side effectful code that can be something as apparently harmless as a &lt;code&gt;println&lt;/code&gt; or you could just call &lt;code&gt;Thread.sleep(...)&lt;/code&gt; and stop the world. In practice, this means we need to follow some guidelines and make sure everybody in our team is aware of them.&lt;/p&gt;

&lt;p&gt;If we need to access the network or the database and we can't enforce purity anyway, why aren't we even more pragmatic and simply do these in OO style? Our domain logic is what can be isolated from external factors such as UI or the data layer, so we could write it in FP style. If you view our business logic as a deterministic black box, you can just pass some data in (loaded from a DB), get some data out and render it to the UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data layer input -&amp;gt; domain logic -&amp;gt; output UI
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, the domain logic is in the middle. If the rest is OO, we get a OO-FP-OO sandwich (I was inspired by &lt;a href="http://disq.us/p/1fdatya"&gt;Dax Fohl&lt;/a&gt; for the concept, although he's suggesting an FP-OO-FP approach).&lt;/p&gt;

&lt;p&gt;Going back to what this article is about and the open question left at the end of the previous section, we could continue to leverage our DI framework and just keep our business logic core functional. Note that this doesn't mean that we should start having mutable state everywhere in the OO part. My approach would be "prefer FP over OO", which means to generally have an FP mindset but be pragmatic and use OO sparsely when it's much more convenient and it's not dangerous.&lt;/p&gt;

&lt;p&gt;I tried this approach in &lt;a href="https://github.com/ps-feng/sample-fp-di/tree/functional-core"&gt;another branch&lt;/a&gt; of the example. The domain logic stays &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/1302326254702d9a8e46c411e539efdd26231e2e/src/main/kotlin/com/sample/todos/domain/Interactors.kt"&gt;exactly the same&lt;/a&gt; as in the partial application case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interactors.kt&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCompletedTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TodoFetcherFn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isCompleted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;However, now &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/1302326254702d9a8e46c411e539efdd26231e2e/src/main/kotlin/com/sample/todos/data/Repositories.kt"&gt;Repositories.kt&lt;/a&gt; takes advantage of Spring Boot's dependency injection system to inject the base url:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserTodosRepository&lt;/span&gt; &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExternalServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TODOS_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getUserTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;WebClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uri&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;uriBuilder&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;uriBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users/$userId/todos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bodyToMono&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;ParameterizedTypeReference&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DataTodo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;dataTodos&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dataTodos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDomain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And it's injected into the &lt;a href="https://github.com/ps-feng/sample-fp-di/blob/1302326254702d9a8e46c411e539efdd26231e2e/src/main/kotlin/com/sample/todos/Todos.kt"&gt;route handler&lt;/a&gt;, who only passes the &lt;code&gt;UserTodosRepository::getUserTodos&lt;/code&gt; function to the domain function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodosHandler&lt;/span&gt; &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserTodosRepository&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ServerRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pathVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;todosResponseMono&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                &lt;span class="nf"&gt;getCompletedTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;getUserTodos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onErrorResume&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;internalServerError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todosResponseMono&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GetTodosResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;badRequest&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;syncBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id is not an integer"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As we're using the DI framework, we no longer need to have the partial application boilerplate in the outer layers. Also, our data layer could just request the dependencies it requires, instead of having a context injected with the dependencies required across all the layers involved in a feature, like in the Reader monad case.&lt;/p&gt;

&lt;p&gt;A purist could say that the functional core shouldn't know anything about a &lt;code&gt;getUserTodos&lt;/code&gt; function, but should be fed the user todos directly. Our domain function would simply filter by &lt;code&gt;isCompleted&lt;/code&gt; and do nothing else. Essentially, side-effects are pushed to the outer layers. This style is similar to the "Ports and Adapters" architecture and is well described by Mark Seemann &lt;a href="http://blog.ploeh.dk/2016/03/18/functional-architecture-is-ports-and-adapters/"&gt;here&lt;/a&gt; (warning: F# and Haskell ahead!). Fair enough, though you could also argue that we'd do that at the expense of having the business logic pushed to the outer layers just so we can have a pure functional core.&lt;/p&gt;

&lt;p&gt;In any case, you can see that we can successfully mix OO and FP and use them for what they're  best at. DI frameworks are convenient and as long as we keep the side-effects well encapsulated in our OO parts and the pure data processing parts in FP style, we can have the best of both worlds!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;We've seen that using partial function application or the Reader monad we can have similar results to OO-style dependency injection. However, they may not be the best approaches as they seem more like an almost direct translation of the OO pattern into the functional world.&lt;/p&gt;

&lt;p&gt;OO and FP are not mutually exclusive, we can use both of them where they work best. An OO-FP-OO sandwich in which the business core is functional and outer layers use OO may be a pragmatic approach forward.&lt;/p&gt;

&lt;p&gt;In any case, each approach has its pros and cons and which one you choose will depend on your task at hand and your own preferences.&lt;/p&gt;

&lt;h4&gt;
  
  
  Partial function application
&lt;/h4&gt;

&lt;p&gt;+ Functional approach (no classes)&lt;br&gt;
+ Explicit, no magic&lt;br&gt;
+ Simple to implement&lt;br&gt;
- Verbose (in Kotlin + Arrow)&lt;br&gt;
- Lots of manual setup in the composition root.&lt;/p&gt;

&lt;h4&gt;
  
  
  Reader monad
&lt;/h4&gt;

&lt;p&gt;+ Functional approach (no classes)&lt;br&gt;
+ Relatively explicit&lt;br&gt;
- Single parameter passed down through all layers (if used as in the example we used)&lt;br&gt;
- Manual setup in the composition root&lt;br&gt;
- Different layer dependencies may be accessible to all functions in the chain&lt;/p&gt;

&lt;h4&gt;
  
  
  OO-FP-OO, hybrid approach
&lt;/h4&gt;

&lt;p&gt;+ Concise code&lt;br&gt;
+ Easy to specify dependencies&lt;br&gt;
+ DI framework takes care of the composition boilerplate&lt;br&gt;
- DI is magical, especially when you're not familiar with the framework&lt;br&gt;
- Uses classes&lt;br&gt;
- Classes may encourage stateful code&lt;br&gt;
- Developers need to be strict in trying to keep the functions pure and making sure that classes are only used for DI and not to hold state&lt;/p&gt;

&lt;p&gt;I personally find the hybrid approach a good pragmatic one in Kotlin, but be mindful about the cons, especially the last one.&lt;/p&gt;

&lt;p&gt;This was a long post! I hope you enjoyed the read and see you next time!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>android</category>
      <category>springboot</category>
      <category>functional</category>
    </item>
  </channel>
</rss>
