Skip to main content

Functions Should Do One Thing

What this concept is

A good function does one coherent job at one level of abstraction. It should not mix orchestration, validation, data transformation, logging, formatting, and persistence in the same block unless that is genuinely one inseparable operation.

Why it matters here

Functions are where readability debt accumulates fastest. Most messy code is not broken because of syntax. It is broken because one function quietly does four jobs and forces every reader to track all of them at once.

Concrete example

This function mixes too many levels:

def register_user(request):
if "email" not in request:
raise ValueError("email required")

normalized_email = request["email"].strip().lower()
user = {"email": normalized_email, "created_at": now()}
db.insert(user)
logger.info("registered %s", normalized_email)
return {"status": "ok", "user": user}

One improvement:

def register_user(request):
email = require_email(request)
user = build_user(email)
save_user(user)
log_registration(user)
return success_response(user)

The second version exposes the story first. Details can move into smaller helpers.

Common confusion / misconception

"One thing" does not mean "one line." It means one cohesive intention. A function can have several steps if those steps all serve the same single responsibility at the same abstraction level.

How to use it

Inspect a function for these warning signs:

  • it needs comments to explain phases
  • it mixes business rules with infrastructure details
  • it contains multiple reasons to change
  • parts of it could be named as separate steps
  • some lines are high-level decisions while others are low-level mechanics

Those are extraction signals.

Check yourself

Why is "one level of abstraction per function" often easier to detect than "one thing"?

Mini drill or application

Take one 20-40 line function. Mark each line as decision, validation, transformation, I/O, or presentation. If more than one category dominates, split the function into named steps.

Read this only if stuck