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:
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