PurelyFunctional.tv Newsletter 460: Interface polymorphism

Free Beginner Workshop

From OO to Clojure Workshop!

Watch my free workshop to help you learn Clojure faster and shift your paradigm to functional.

Issue 460 - February 01, 2022 · Archives · Subscribe

Design Idea 💡

Interface polymorphism

This essay continues the series about Domain Modeling.

Java and similar languages have the idea of an interface. An interface is useful because it allows you to add new implementations without modifying the original. Interfaces provide extension points. But when should we insert an extension point? We should insert one when you have to encode a set of alternatives---and you need to add new alternatives at a slower cadence than your release cycle.

If you squint at your domain, you can see alternatives. They're everywhere in the world. For example, a coffee shop may have three alternative sizes for coffee (small, medium, large). A single beverage can't be both small and large. You have to choose one alternative. Likewise, the coffee can be light, medium, or dark roast. That's another alternative.

Interfaces are a way to define an alternative. Let's say I have an Interface called CoffeeSize. In that case, I can extend it in three classes Small, Medium, and Large. Declaring that a function accepts an instance of CoffeeSize implies that it accepts any of the extensions.

There are other ways in Java to encode an alternative. One way is called an enum. You could declare this:

enum CoffeeSize {
  Small(2.50),
  Medium(4.50),
  Large(7.50);
}

This enum encodes the names and volumes of the three sizes. The difference between enums and interfaces is in how we can extend them. To add a new size to the enum, you have to modify the code that declares the enum. You don't modify anything to add a new size to the interface. Instead, you create a new class that implements the CoffeeSize interface. All of the existing code should automatically work with the new size.

Last time we talked about the Open/Closed Principle. The modern incarnation guides us to write interfaces and implement them with classes. But why? Last time, we saw that it was a solution to the tension between leaving existing code alone and needing to change the behavior. It's about maintainability and changeability.

However, maintainability and changeability are meta-level concerns. They're not about how to choose the right abstraction for the problem. They're about cost, not correctness. It's another instance of focusing on coding style and not substance. Maybe that's why I'm not a fan of Open/Closed.

Finding alternatives, however, is very practical. You find the alternatives in your domain, decide how fast they change, and choose the right encoding in your language. If the sizes don't often vary, use an enum. It's easy and convenient. If you add and remove sizes weekly, maybe an interface is the best. You can add and remove classes and redeploy.

But if it changes daily, you may need something more malleable. One solution is to store the sizes in a database. The name and volume are columns on your table. Then you can have a single size like this:

class CoffeeSize {
  public final String name;
  public final double ounces;
}

And you can hydrate these from the rows of the database. Now you can change the table multiple times per day.

So, to conclude, we should be talking more about characterizing domain concepts. In this essay, we talked about alternatives, but there are more conceptual structures to uncover. Once you've identified the domain concept, you can choose how to encode it in your language. We saw three different ways to encode alternatives in Java, each with its strengths and weaknesses.

I've heard people talk about using an interface to make their software maintainable. But I rarely hear someone saying that interfaces encode alternatives you uncover in your domain. Often style (read "design"), rarely substance. We need to talk more about correctly choosing our abstractions to encode a domain model and less about rules of thumb for making code more maintainable. Less talk about code, more talk about coffee.

Awesome podcast episode🎙

What???1?? The JUXT podcast is rocking it. This time it's all about User Empowerment.

Book update 📘

Grokking Simplicity is still selling strong. I love getting messages on Twitter or over email about how it is affecting people's coding. Here's one:

And did you know there's now an audiobook version available? What? I haven't listened to it (I actually had nothing to do with it). You can hear the first chapter on the Manning site.

You can order the book on Amazon. Please leave a rating and/or review. Reviews are a primary signal that Amazon uses to promote the book. And they help others learn whether the book is for them.

You can order the print and/or eBook versions on Manning.com (use TSSIMPLICITY for 50% off).

Pandemic update 😷

I know a lot of people are going through tougher times than I am. If you, for any reason, can't afford my courses, and you think the courses will help you, please hit reply and I will set you up. It's a small gesture I can make, but it might help.

I don't want to shame you or anybody that we should be using this time to work on our skills. The number one priority is your health and safety. I know I haven't been able to work very much, let alone learn some new skill. But if learning Clojure is important to you, and you can't afford it, just hit reply and I'll set you up. Keeping busy can keep us sane.

Stay healthy. Wash your hands. Wear a mask. Get vaccinated if you can. Take care of loved ones.

Clojure Challenge 🤔

Last issue's challenge

Issue 459 -- Paul Cipher -- Submissions

This week's challenge

Rearrange sentence

Here's a neat, yet contrived, text processing problem. The words in your sentence have been mixed up. Luckily, there's a number embedded in each word that says its position in the sentence. Write a function that puts the words in the right order and removes the position digits.

Examples

(rearrange "World2! He1llo,") ;=> "Hello, World!"
(rearrange "fo3r 5more Elegan1t 2weapons age.7 civil6ized a4") ;=> "Elegant
weapons for a more civilized age."
(rearrange "") ;=> ""

Thanks to this site for the problem idea, where it is rated Very Hard in Java. The problem has been modified.

Please submit your solutions as comments on this gist.

Rock on!
Eric Normand