Contents

Engineering Craft › Clean Code & Principles

Principle of Least Astonishment

Code and APIs should behave the way people expect.

Also known as: POLA, least surprise

The principle of least astonishment says that a piece of code or an API should do what its name and surroundings suggest. A reader should be able to guess the behaviour without reading the implementation, and when the behaviour is unusual, the surprise should be small and clearly flagged.

A classic Python surprise is a mutable default argument. The default list is created once, when the function is defined, so every call that uses the default shares it:

def add_item(item, items=[]):
    items.append(item)
    return items

add_item("a")   # ['a']
add_item("b")   # ['a', 'b']  -- the second call sees the first call's list

The fix makes the default explicit, so each call gets its own list:

def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

The trade-off is that “least astonishment” depends on the reader. What’s surprising to a newcomer may be a well-known convention to someone who has used the language for years. Consistency inside one codebase often matters more than matching a general ideal.

The classic mistake is naming a function for one thing and having it do another, such as a get_user that also creates the user when it’s missing, or a validate that changes the data. Names are the first contract a reader sees. Make the name match the effect, and when an effect is unusual, put it in the name or the signature. For the broader idea of conventions a team can rely on, see convention over configuration, and for querying versus changing state, command-query separation.