DEV Community

loading...
Cover image for A Tiny Note About Interfaces

A Tiny Note About Interfaces

ovid profile image Ovid ・4 min read

A client wanted to take their current monolithic application and break it up into a series of interconnected services. They wanted to go down the Service Oriented Archicture (SOA) road, but they had made some curious choices regarding what they wanted to expose in their APIs.

That got me to thinking about my daughter, Lilly-Rose. When she was rather young, I had an Android phone and she liked to play with that when we were riding in the car. One day we were driving along when she noticed a new icon on the phone. It had her face. And her name.

“Papa, what’s that?”

“I don’t know. Why don’t you click it?”

So she did. And this is what she saw.

A blank application with a single button reading "CLICK ME"

She smiled, but looked confused and showed me the phone (I was in the back with her). “It just says ‘click me’.”

“So, why not?”

So she clicked it and saw something like this:

The application now reads "What do you call it when a dinosaur crashes his car? Tyrannosaurus Wrecks."

And then she clicked it again and saw something like this:

The application now reads "What did one plate say to the other plate? Dinner is on me!"

She kept getting weird things like “the cats are waiting for us to make a mistake before they take over” or “what do lawyers wear to court? Lawsuits.” (I had to explain that one) and she was laughing and having a blast. Every time she pressed the button she'd get a random joke on a random background color. Chalk that up as a win for papa.

So what does this have to do with APIs? You can think of that application as an API, albeit for my daughter and not another piece of software. I created it so that even my young daughter could figure out how to use it. I even got a bug report from her! (“Papa, it doesn’t work!”) It took me a while to realize that sometimes she would get the same joke twice and the same background color. So I made sure she’d never get the same joke twice in row.

Now you, as a software developer, might wonder ”what programming language did Ovid use?” or “are the jokes stored in a database?” My daughter didn’t care and neither should you. The technology used was the scaffolding to build the application. The application’s interface should hide the scaffolding.

Exposing the scaffolding is making an implicit promise that it can be relied on. People will be unhappy if you break that promise.

To be honest, this is so trivial that it seems ridiculous to write a post about it, but I've seen this violated so many times that I have to write a post about it. What language did I use? Who cares? So long as the app is the same, my daughter would still laugh. Were the jokes hard-coded, stored in a database, fetched from a remote service? Again, it doesn't matter. And it shouldn't be exposed in the interface.

It’s not that those technical decisions are unimportant. It’s that the end consumer shouldn’t have to be aware of them. When you hide them, you can change them, or fix them. When you expose them, whether it be in an application or an API, consumers of what you’re providing learn to rely on those details and then you get stuck providing them. So don’t do that.


For those who must know the technical details, here’s the core of the app, written in Kotlin:

package io.github.ovid.lilly_roserules

import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import kotlin.random.Random
import androidx.constraintlayout.widget.ConstraintLayout

class MainActivity : AppCompatActivity() {
    internal lateinit var layout: ConstraintLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        layout = findViewById(R.id.mainlayout)

        val rollButton    = findViewById<Button>(R.id.rollButton)
        val quoteTextView = findViewById<TextView>(R.id.quoteTextView)

        val messages      = getMessages()
        val colors        = getColors()
        var lastChoice    = 0

        rollButton.setOnClickListener {
            var thisChoice = 0

            // make sure we never get the same message twice in a row
            while (thisChoice == lastChoice) {
                thisChoice = Random.nextInt(messages.size)
            }
            lastChoice = thisChoice

            // picks a random message
            quoteTextView.text = messages[thisChoice]

            // picks a random background color
            val randColor = Random.nextInt(colors.size)
            layout.setBackgroundColor(Color.parseColor(colors[randColor]))
        }
    }

    fun getColors():Array<String> {
        val colors = arrayOf(
            // list of colors
        )
        return colors
    }

    fun getMessages():Array<String> {
        val messages = arrayOf(
            // list of jokes
        )
        return messages
    }
}
Enter fullscreen mode Exit fullscreen mode

It was dead-simple and just thrown together quickly to amuse my daughter. But if I ever needed to make it “production ready,” all the important bits were hidden away. Because this was an application on a smart phone and not an API, this sounds silly, but I’m hard-pressed to find a better analogy to explain this mistake I see made over and over again.

Discussion (1)

Collapse
moopet profile image
Ben Sinclair

Exposing the scaffolding is making an implicit promise that it can be relied on. People will be unhappy if you break that promise.

I think this should be written at the start of every API tutorial or textbook!

Forem Open with the Forem app