I know, long method? Come on. That’s an easy one: just don’t write long methods. Easy right?
Not so fast. There are two issues worth discussing about long methods.
First, what is a long method? What exactly is “LONG”? How long is too long? Five lines? Certainly not. Twenty? Uh, probably not. Forty? Hmmm, probably. Eighty? Almost definitely. But like all code smells there’s rarely a hard and fast rule, and there are always exceptions.
There are really a few things you should take into account when deciding if a code smell needs to be refactored. One is the complexity of the method. If the method has a lot of loops and branches, then the longer it is, the worse it is. If the method mostly contains highly scannable code, such as configuration, text, HTML, or object/data definitions, then you can definitely tolerate a longer method.
Here’s a reasonable rule of thumb: between one half and one screen height max (depending on resolution and font size) for a single method. Yup, it’s inexact, and there’s plenty of exceptions, but it’s a good quick rule. Anything over that you should look closer.
Think of it like wasabi on your sushi. It’s hard to describe what “too much” is in micrograms, but you’ll know it when you taste it. :)
So you should also tune yourself to see methods as being too long at a glance. Don’t count the lines. Just follow your gut. If it looks too long, then look closer. Remember these are code smells. They don’t indicate a problem 100% of the time. They just give us guidelines to look closer and decide if we need to refactor.
The second issue with Long Methods that we have to be careful is that they are possibly one of the sneakiest kinds of code smells. If they were D&D characters, they’d have a +11 to stealth. Why? Because they don’t just appear suddenly. They slowly creep up on us. And we almost never write them first try. Instead, we start with a perfectly acceptable method length. Maybe ten lines long. Then a few weeks later we need to add a new condition to the method. It’s something simple. Just three more lines of code. Still not too long. And the logic we add DEFINITELY belongs inside this method.
Then a month later, we need to add another line of code to each of the three branches of our main condition in the method. Three more lines. That definitely doesn’t make it too long. Then a bit later we have to add more data to the return value. Two more lines. But you don’t refactor because you’re returning more data. So we don’t. The next week we get a critical bug in production. The quickest fix is to add another else branch. So we do that quickly. Four more lines of code. We were so stressed we didn’t even think about the length of the method. We just needed to get the bug fixed.
This pattern repeats and repeats. It’s insidious, and we never notice that somehow our method has become too long.
Which grain of sand turns a hill into a mountain?
Here’s a concrete example of some code (heavily modified) from the Thinkster.io codebase. Take a moment and just try to get the gist of what it’s doing.
Once we use this code smell to identify a possible problem, THEN we actually look closer and consider why we got to where we are, and what we should do about it. Generally extracting a few sub-methods will clean up the code, increase the readability, and fix several other kinds of issues.
Let’s look at a possible refactoring of the above:
What have we gained?
One thing we’ve done is given ourselves the ability to more easily read the method, and see what it’s doing. We’ve turned it from a long method that needs a lot of time to really see what it’s doing, to something that can be understood much more easily. You have to look at a lot fewer details to understand this version of the method.
That’s the beauty of keeping methods short. In order to do that we usually have to create more methods. Those methods have names. Those names give us better descriptions of what our code is doing. We get a better abstraction of our code that is easier to understand at our current abstraction level.
If you think about it, it’s kind of beautiful how the various methods of improving code quality work together. A code smell makes us look at some code. We decide there’s a problem and we refactor. The refactoring to tackle the code smell makes us use techniques that increase readability. Without meaning to directly improve readability we do that by nature of tackling the code smell. And it really doesn’t take that much time to do a refactoring like this.
But we have to be diligent, and we have to train ourselves on what to look for. And we also have to lower our tolerance to just “fix it later”. As the great band, Creedence Clearwater Revival so beautifully sang in 1972, Someday Never Comes.
Enjoy this discussion? Sign up for our newsletter here.