When Does a Function Do 1 Thing?

Number 1 on a wall

Functions should do one thing. They should do it well. They should do it only.

Robert C. Martin in Clean Code

You probably agree, but what’s 1 thing?

What about the core.clj file’s -main function?

That does almost everything in the app. 

Definitely more than 1 thing, right?

Here’s how you know if it does 1 thing:

Can you name the function without and?

Here’s a function that fails that test:

(defn delete-img! [img] 
  (remove-image! img)
  (tree-shake-images!))Code language: Clojure (clojure)

delete-img! is the wrong name, because it also tree-shakes all images (removes deleted images from content).

So maybe:

(defn delete-image-and-cleanup! [img]
  ...Code language: Clojure (clojure)

…but that has and

So maybe a more general name like:

(defn update-images! [img]
  ...Code language: Clojure (clojure)

But the parameter img doesn’t make sense.

Why is update-images! plural, when when it accepts a parameter of a singular img?

This makes sense:

(defn update-content! [] 
  (let [img (to-delete!)]
    (delete-img! id)
    (tree-shake-images!)
    ;; More content things
  Code language: Clojure (clojure)

The name update-content is general enough that you know it’s doing a lot.

But you can describe it as 1 thing:

It updates content.

The content is 1 thing at this level of abstraction.

The name doesn’t mislead you. 

But why can’t we ignore “1 thing”?

Sure, “1 thing” is a best practice.

But if we ignored that rule sometimes, we could open PRs faster.

Why does it matter?

Because one of the nastiest bugs I wrote came from hiding tree shaking in a function. 

The function’s name said it did 1 thing: delete an image.

That worked fine, until I called the function in a 2nd place.

This caused a subtle bug that I wasted a day debugging.

The tree-shaking deleted another image that it shouldn’t have.

Why would I suspect the tree-shaking caused a problem?

It’s a necessary part of deleting an image.

But it’s actually not.

Tree-shaking images is orthogonal to deleting an image.

Tree-shaking operates on all images, while deleting an image operates on 1.

So it’s more than 1 thing.

And it should have been its own function call. 

Names can hide what a function does.

If a function is general, like update-content!

It’s fine to name it like that.

Functions are honest when they do 1 thing.

Leave a Reply

Your email address will not be published. Required fields are marked *