“Extract Method is one of the most common refactorings I do. I look at a method that is too long or look at code that needs a comment to understand its purpose. I then turn that fragment of code into its own method.

I prefer short, well-named methods for several reasons. First, it increases the chances that other methods can use a method when the method is finely grained. Second, it allows the higher-level methods to read more like a series of comments. Overriding also is easier when the methods are finely grained.

It does take a little getting used to if you are used to seeing larger methods. And small methods really work only when you have good names, so you need to pay attention to naming. People sometimes ask me what length I look for in a method. To me length is not the issue. The key is the semantic distance between the method name and the method body. If extracting improves clarity, do it, even
if the name is longer than the code you have extracted.”

Uncle Bob’s post provides an example of extracting until nothing else can be done, and then he ends with this comment:

“Perhaps you think this is taking things too far. I used to think so too. But after programming for over 40+ years, I’m beginning to come to the conclusion that this level of extraction is not taking things too far at all. In fact, to me, it looks just about right.

As he predicts, many people do think he’s going too far. Here’s a couple excerpts from the post’s comments:

“Following the flow of the data through the fully extracted version becomes difficult, since the developer will need to jump around constantly throughout the body of the class.

If the goal is to make development and maintenance easier and fully extracting the class makes it more difficult for a developer to follow the flow of the data is it better to fully extract just for the sake of following a rule?

My point is that patterns in code are easier to see when things are not broken down into such small chunks. At the fully decomposed state it isn’t obvious that an Adapter on the Matcher would simply fit into place. By decomposing the methods so fine you lose context, so much so it isn’t evident how the method relates to the accomplishing the goal of the class.”

and, another:

‘A function by definition, returns 1 result from 1 input. If there’s no reuse, there is no “should”. Decomposition is for reuse, not just to decompose. Depending on the language/compiler there may be additional decision weights.

What I see from the example is you’ve gone and polluted your namespace with increasingly complex,longer,more obscure, function name mangling which could have been achieved (quick and readable) with whitespace and comments. To mirror a previous poster, I rather see a javadoc with proper commenting than to trace what’s going on for such a simplistic case. I’m afraid to ask what you plan to do when the class is more complex and symbolExpression(..) isn’t descriptive enough!’

These arguments make a good point. However, these arguments also apply to object-oriented code in general. Reading and navigating object-oriented code can often be more difficult than its procedural counterparts. However, we hope to overcome these disadvantages by creating a structure that is more readable and reusable overall.

In Uncle Bob’s example, the newer, more granular methods provide a more complete and accurate view of the behaviors and capabilities of the SymbolReplacer class. In isolation, it might appear as overkill and “polluted namespaces”. However, if you were maintaining a large codebase and needed to understand how to use (or reuse) SymbolReplacer, I believe Uncle Bob’s approach would make your task much easier. You don’t need to read through javadoc (as one commenter prefers). Instead, the method names are more clear, the size is smaller and easier to override, and the class itself almost becomes readable English. In my opinion, these advantages outweigh the loss of navigability.

But, perhaps, as Martin Fowler mentions “it does take a little getting used to”. Uncle Bob said almost the same thing: “Perhaps you think this is taking things too far. I used to think so too. But after programming for over 40+ years, I’m beginning to come to the conclusion that this level of extraction is not taking things too far at all. In fact, to me, it looks just about right.”

With the wisdom of those two, I think we owe it to ourselves to set aside our skepticism and give it a real try. We can come back later, compare results, and make a decision then. I have found that those who are willing to try their advice, in the end, never go back. Perhaps, you will will find that your code gets cleaner and opportunities for reuse start showing themselves in surprising ways.

Post navigation

5 thoughts on “Extract Method – How Much is Too Much?”

It makes sense to me. It seems like some of this would depend on mindset of the team you work with. Some devs (and I’m in the C# space), are not used to OOP, and thus are not used to navigating layers and objects. You can easily become the black sheep of the group when extracting methods to do one thing, if you’re the only one doing it. And that’s regardless if the black sheep of the team is a good or bad thing for you. If you work with people who are used to OOP (lots of objects/methods), then navigating through a piece of code using extract till you drop becomes second nature (especially with the tools we have now). I have found less than 50% my teammates through my career really knowing OOP, and more than 50% creating superclasses and putting all their logic in the code behind and get mad at me when I try to Object Orientate.

On a similar note, this would also seem to be difficult for people who are coming from a top down (i.e. mainframe). Have you noticed the same?

Thanks, A’braham, you make some excellent points. Even if we have a “better” way of doing things, being a black sheep hurts the team as a whole. Just imagine a back-and-forth scenario where one developer extracts code and the others merge it right back!

In our careers, we will work with all types of developers. As you mention, many of them will not understand good OO principles. When we’re in a healthy team (with good attitudes about learning and sharing), this is a great opportunity to form internal study groups and increase the level of understanding, including our own! In an unhealthy environment (developers don’t care), it is especially frustrating. We can look at ourselves to see how to present our ideas better. But after a sincere effort with no success, it might be best to find a tribe of other black sheep :-)

While I have yet to really give it a shot, one benefit I’ve read* about that makes sense is that it’s often only once you have all of these methods extracted that you begin to see new classes that can be extracted from them.

Extracting methods, classes, making cohesive class groups,
and cohesive libraries is what OOP is really about I would think. That’s the direction we should be taking our code. The other direction leads to a single method encompassing the entire system. Instead, we break the whole problem into methods, group the methods and data into classes, group the classes into packages/namespaces, and group the packages/namespaces into libraries.

Thanks, Dave, I certainly agree. And, you owe it to yourself to “really give it a shot”, too :-) Not only will you begin to see new classes that can be extracted (as you mentioned), but you will start to learn about your code at an entirely new level. This helps in removing duplication in all sorts of ways, which leads to more maintainable code, which helps you understand your domain better. The process becomes particularly important as the codebase and the time frame increases.