Code4IT

The place for .NET enthusiasts, Azure lovers, and backend developers

Clean code tip: Principle of Least Surprise

2021-06-22 2 min read Clean Code Tips
Just a second!
If you are here, it means that you are a software developer. So, you know that storage, networking, and domain management have a cost .

If you want to support this blog, please ensure that you have disabled the adblocker for this site. I configured Google AdSense to show as few ADS as possible - I don't want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

Thank you for your understanding.
- Davide

The Principle of least surprise, also called Principle of least astonishment is a quite simple principle about Software design with some interesting aspects.

Simplifying it a log, this principle says that:

A function or class should do the most obvious thing you can expect from its name

Let’s start with an example of what not to do:

string Concatenate(string firstString, string secondString)
{
  return string.Concat(firstString, secondString).ToLowerInvariant();
}

What is the problem with this method? Well, simply, the Client may expect to receive the strings concatenated without other modifications; but internally, the function calls the ToLowerInvariant() method on the returned string, thus modifying the expected behavior.

So, when calling

var first ="Abra";
var second = "Kadabra";

var concatenated = Concatenate(first, second);

The concatenated variable will be abrakadabra instead of AbraKadabra.

The solution is really simple: use better names!

string ConcatenateInLowerCase(string firstString, string secondString)
{
  return string.Concat(firstString, secondString).ToLowerInvariant();
}

Functions should do what you expect them to do: use clear names, clear variables, good return types.

Related to this principle, you should not introduce unexpected side effects.

As an example, let’s store some data on a DB, and wrap the database access with a Repository class. And let’s add an InsertItem method.

public void InsertItem(Item newItem)
{
  if(repo.Exists(newItem))
    repo.Update(newItem);
  else
    repo.Add(newItem);
}

Clearly, the client does not expect this method to replace an existing item. Again, the solution is to give it a better name: InsertOrUpdate, or Upsert.

Lastly, the function should use the Design Pattern suggested by its name.

public class RepositoryFactory
{
    private static Repository instance = null;
    public static Repository Instance
    {
        get {
                if (instance == null) {
                    instance = new Repository();
                }
                return instance;
        }
    }
}

This article first appeared on Code4IT

See the point? It looks like we are using the Factory design pattern, but the code is actually the one for a Singleton.

Again, being clear and obvious is one of the keys to successful clean code.

The solution? Use better names! It may not be simple, but luckily there are some simple guidelines that you can follow.

👉 Let’s discuss it on Twitter or on the comment section below!

🐧