chapter five

5 Expressiveness

 

This chapter covers

  • Understanding expressiveness
  • Comparing equivalent solutions across languages
  • Evaluating expressiveness through practical signals
  • Recognizing the limits of expressiveness

We’ve tackled complexity and explored why striving for simplicity and clarity of intent is essential to writing beautiful, maintainable code. Now, let’s turn to another crucial dimension of the rosette: expressiveness.

Expressiveness is about transforming logic into code effortlessly. When a programming language is expressive, it feels like a natural extension of your thoughts, a powerful tool that allows you to tell your story clearly and fluently. Expressive code clearly reveals its intent, flows naturally, and feels effortless to read and write. If you find yourself twisting the language, jumping through hoops, or hacking around its limitations to make something work, then it lacks expressiveness. You're facing its opposite: boilerplate-heavy, verbose, complicated, and opaque code.

To better illustrate expressiveness, let’s briefly consider two quick snippets of Java code side by side performing the same task. I will deliberately avoid explaining their purpose upfront because truly expressive code should be clear and understandable at a glance.

if (book instanceof HardcoverBook) {
  HardcoverBook hb = (HardcoverBook) book;
  printCover(hb);
} else if (book instanceof PocketBook) {
  PocketBook pb = (PocketBook) book;
  printPocket(pb);
} 
 

Now consider the second version.

5.1 Understanding expressiveness

5.1.1 Traditional switch in Java

5.1.2 Java enhanced switch

5.1.3 Kotlin if/else

5.1.4 Kotlin when with a sealed hierarchy

5.1.5 Haskell pattern matching and direct domain modeling

5.2 The limits of expressiveness

5.3 Summary