I’d often come across the advice that methods (and classes) should “only do one thing”. That advice seemed almost ridiculous to me. e.g. saving to a file, you need to
- Open the file
- Write the data
- Close the file
So that’s three things. Then there’s error handling on top of that, which should count as another ‘thing’. So I could never see how to follow that advice.
However, I’d seen this guideline often enough that I also thought "a large group of smart programmers seem to believe this is a good idea". I’m (hopefully) not an idiot, so I was clearly missing something here.
It wasn’t until reading Clean Code earlier this year that it finally clicked.
What “doing one thing” really means
Clean Code talks about “doing one thing” in terms of levels of abstraction. This makes much more sense to me. Everything inside a method should be one level of abstraction below the method itself, which also means everything inside the method should be at the same level of abstraction. As Clean Code says:
“If a function does only those steps that are one level of abstraction below the stated name of the function, then the function is doing one thing. After all, the reason we have functions is to decompose a larger concept (in other words, the name of the function) into a set of steps at the next level of abstraction.”
After it clicked, I switched to thinking about it as meaning "one level of abstraction per method" which is something I can both understand, and agree with. It’s still hard to follow that guideline all the time, but at least I now know what I’m aiming for. Which is pretty close to what I’d been aiming for already.
As Clean Code also says:
“Mixing levels of abstraction within a function is confusing. Readers may not be able to tell whether a particular expression is an essential concept or a detail. Worse, like broken windows, once details are mixed with essential concepts, more and more details tend to accrete within the function.”