Loading...

Two More Billion Dollar Mistakes

March 14, 2024
4 minutes to read
Share this post:

Hi,

You might have heard that null was referred to by its creator, Tony Hoare, as the “billion-dollar mistake.” In 2009, he publicly apologized at QCon for taking the easy path in 1965 by inventing null:

“I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object-oriented language (ALGOL W ). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.”

~ Tony Hoare (2009)

However, that’s not what I want to talk about today. I want to discuss two other anti-patterns that have likely also caused a billion dollars in pain and damage:

Unit Tests are Unrelated to TDD

This might surprise you. If you practice TDD, you probably write unit tests. Or at least, you might use JUnit. But is JUnit a unit test? We’ve come to use these terms interchangeably. JUnit is merely a tool for writing tests. With JUnit, we can also write integration tests, system tests, or acceptance tests.

When we talk about unit tests today, we often think of a test that isolates and tests a single class.

However, when TDD was emerging in various software communities around the world, this definition of unit tests did not exist. TDD was based on the idea of first expressing a code requirement in the form of a test and then writing the implementation for it, in as small iterations as possible.

The goal is for the test to become more specific over time while the implementation becomes more generic.

This is where the conflict with current practices lies. If we semantically tie a test to a class - as we do when we test CustomerService with CustomerServiceTest - we can only change our implementation to a certain degree without having to adjust the tests and their structure.

Current unit testing practices obstruct the effective practice of TDD. The test classes, their names, packages, and architecture should not be tied to the implementation.

Unit tests are unrelated to TDD. They are two fundamentally different concepts that intersect but are not identical. This misconception has led to the creation of billions of lines of test code that are difficult to maintain and fragile.

Microservices are Not Micro

The term “Microservice” suggests that we are talking about small services. But when is a service considered small? When it does just one thing? When it has just one endpoint? When it consists of only 100 lines of code? Is a service with two endpoints still small? Are 10 endpoints acceptable?

Each developer might see this differently. According to DDD (Domain-Driven Design), a service should represent a domain. Since DDD and microservices are often lumped together, there is an attempt to design a domain as a microservice.

And that’s where the “Micro” in Microservice becomes problematic. This label often leads to the assumption that a domain must be small, resulting in overly fine-grained divisions.

It tempts us to see domains where there are none.

Suddenly, a Customer Microservice emerges. Then a Tenant Microservice. And a Payment Microservice. But with my clients, who typically come from the German Mittelstand, there is usually only one domain. These services only arose because the term led us astray.

This misconception has caused billions of dollars in unnecessary development effort, performance issues, errors due to inconsistencies, and headaches.

Microservices are not micro!

ps. Since Monday, my new article “Mittelstand, Stay Away from Microservices!” has been available on golem plus. Check it out if you’re a subscriber 🙂

Rule the Backend,

~ Marcus

Top