Should My Functions Be Five Lines

Should My Functions Be Five Lines

There is a book you probably heard about, "Clean Code" by Robert Martin, who also authored other famous books on Software Engineering and who stood behind many well-known engineering principles as well as the Agile.

Many of his works are often under a barrage of criticism. In particular, in regards to the "Clean Code" (which is basically a pretty strict and opinionated guideline), people are complaining about impracticality and complexity as well as about dogmatism of people following principles promoted in R. Martin's works. It kind of sounds like, "Yeah, it is never possible in a real-life project", "I worked with a guy who made codebase unmaintainable with clean code", etc. I also heard someone addressing passionate followers of his teachings as "zealots", and this tells a lot, I guess.

Now, I definitely wouldn't dare to raise a discussion about that (although, for the record, I love "Clean Architecture," but in regards to coding, I prefer "Code Complete" by Steve McConnel). What impressed me to the point of writing articles was one of his posts about keeping functions small:

Or, to be precise, it wasn't the post itself but people's reactions. The post itself is intentionally opinionated but completely chill, and yet in the quotes, it was like this:

Around half of the quotes (yes, I counted) are very critical and even rude, plus there was a hate wave in posts not linked to this one.

Some of these people are random strangers, but others do have pretty solid credentials. The other side, also pretty credible, speaks in favor of such principles. It can be really confusing: Who is right? Is it just a matter of opinion or taste? Let's talk about that.

First, if we actually read about it in the book (chapter "Functions" if you want to check yourself), we can see that this recommendation doesn't go alone. It is intended to be used in combination with "one abstraction level per function", "do one thing", "use descriptive names", etc. So obviously, if someone uses the "5 lines rule" without accounting for other rules, their code will be awful, and I don't want to be their colleague or even be a member of the same repository as them.

Secondly, you have to understand that things like "size of functions or files" are heuristics. They do not make much sense on their own, but they can be used as a metric for "Can this be better?". It is often hard to look at your freshly baked code from different angles to see potential spaces for improvements. But thinking like, "OK, this now works, but it is X lines; can I express it shorter?" and then filtering potential ideas against other software design rules, principles, and heuristics — that gives a much more visible direction.

So, basically, anyone saying this is a terrible bit of advice is as wrong as people practicing requesting code review changes regarding function size only. But using it as a heuristic in combination with other recommendations from "Clean Code" can indeed make you a better coder.

So what you should be doing is:

  • Never discuss any geometrical shapes of the code with your colleagues, as this is only important for your thinking process.

  • Establish metrics for yourself, the ones you would be comfortable with personally.
    For example, I am trying to keep files under one screen, which for me is 70 lines. But I never speak of this out loud, and I often exceed this boundary. Also, I lock the length of a line with prettier and then try to write code so that auto-formatting doesn't introduce unwanted newlines.

    • Use these metrics to fix up your code after you finish it.

    • Use these metrics to assess the code you got for review.
      If your colleague produces something that bothers you in this regard, find ideas they could use to make the code "fit" these metrics. Don't just ask to make the function smaller!

  • Again, never speak of such metrics out loud because it is usually cringeworthy.
    Unless you are writing an article or book or preparing a conference speech on this topic.

  • And yes, it's OK to have your functions longer.

I would also recommend briefly reading the "Functions" section of "Clean Code" to familiarize yourself with other recommendations that can be used as heuristics. Also, I'd recommend subscribing to this blog and sharing this article!

As a closing note, let's look at the example. It is a slightly simplified version of something that I have seen many times in my life:

This function is 28 lines, and there's nothing fundamentally wrong with it — it is clumsy but readable and maintainable. And I'd probably not want to change anything around it. However, if we employ function length heuristics, we can come up with some improvements.

Firstly, a lot of "screen real estate" is taken by that cheap if-error-showError error handling pattern. Now, if we make fail-able functions throw errors instead of returning them, it can become much smaller:

We remove the crossed-out stuff and get something like this:

We are now at 17 lines. And I wouldn't have come up with it if I hadn't considered making this function smaller.

Let's continue, though — if we look closer, the block about the toy box has nothing to do with the rest of the code. So we can totally hide it into a separate function, and then there is technically no reason to keep empty lines between code blocks:

Note that these are now 10 lines of exactly the same code. I didn't introduce any new cryptic abstractions that would ruin the codebase. I would probably stop here, but if we take this further and assume that such error handling is a pattern in a codebase, we can introduce a function that executes the passed function and invokes showError on the error message if something throws. Then our code will look like this:

Six lines! However, I wouldn't recommend doing it, as I don't think this would be a universally good abstraction. So, I would come back to the previous 10-line version and be happy with the shrinking results.

Of course, I am not saying this is how you should always approach such code situations; this is rather an example of a thinking process — I moved towards shortening but then did the sanity check and stopped before doing the wrong things.

If you want to understand better what makes an abstraction good — like and follow, as it might be the topic of one of the upcoming posts!