Term of the Day: Principle Of Least Surprise


The principle of least surprise (AKA POLS) simply dictates that the interface to any given entity (method, for instance) should exhibit the bevahior that is least suprising to the user/programmer when there are conflicts or ambiguities between members of said interface.

Example:  

Let’s say that the following are true…

The following classes exist: Person, Address, People

Person has the following attributes: SSN, Name, Address

Person.SSN is used to identify Person instances

People is a service that manages a set of Person objects

People has to following methods: Add(Person):void, Get(SSN):Person

 

Now let’s say Joe programmer is using People to describe his blooming social life…

Joe says:

myFriend = new Person()

myFriend.Name = “John”

myFriend.SSN = 9999999999

myFriend.Street = 10101 Victory Lane

myFriend.City = San Mango

myFriend.Address.State = Texas

myFriend.Address.Zip = 93940

 

Then he says:

friends = new People() 

friends.Add(myFriend)

…Now Joe’s friends include a reference to John…

 

Later Joe wants to write a letter to his friend, so he says:

myFriend = friends.Get(999999999)

 

If the People class adheres to the POLS, the address of myFriend should be that same as it was when he added it to friends. 

 

Now here’s a scenario that we see on occasion that will give Joe a nasty surprise.  The author of People decided that states are implied by zip codes.  Instead of bothering with the State value that’s passed into People, it just stores the Zip code and gets the appropriate state based on the Zip repository that People’s author went through so much trouble to create.  Unfortunately for Joe, when Joe entered the data he had been reminiscing on his own address in central California and he accidentally entered his own Zip.  Now Joe’s lost contact with his only friend (poor Joe).

 

As a result, myFriend looks like this:

myFriend = new Person()

myFriend.Name = “John”

myFriend.SSN = 9999999999

myFriend.Street = 10101 Victory Lane

myFriend.City = San Mango

myFriend.Address.State = California

myFriend.Address.Zip = 93940

 

Person’s Add() looks like a setter and the Get() looks like a getter.  The interface does nothing to communicate that somewhere in between there is an implied mutation based on Zip.  This behavior would therefore violate the POLS.

 

The example may seem a bit silly, but I’m sure we’ve all run into similar scenarios more than we’d like to admit.  This concept isn’t new, just often ignored.

 

Another great JavaScript article