Clean code tip: Principle of Least Surprise

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;  
        }  
    }  
} 

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!

🐧

code4it

Ciao! I'm Davide Bellone, a .NET software developer! Let's keep in touch on Twitter!