Why do we extract method?
Ever since I've read Uncle Bob's Clean Code book my approach to coding has been all about the 'extract method' refactoring - I pretty much look to extract method as much as I can until I get to the point where extracting another method would result in me just describing the language semantics in the method name.
One of the approaches that I've come across with regards to doing this refactoring is that it's only used when there is duplication of code and we want to reduce that duplication so that it's all in one place and then call that method from two places.
While this is certainly a valuable reason for doing extracting method I think there are other reasons why we would want to do it more frequently than just this.
Expressing intent
One of the main reasons we design code in an object oriented way is that it often allows us to describe the intent of our code more clearly than we would be able to it we wrote it with a more procedural approach and I think the same thing applies when extracting methods inside a class.
Quite often when reading code we're interested in knowing a bit more about a class than we can derive from its name but we're not really that interested in all the low level details of its implementation.
If methods have been extracted abstracting all that detail away from us then we're able to quickly glance at the class and fairly quickly work out what is going on and then move back to working out what we were actually doing in the first place.
It makes code easier to read
A consequence of extracting that detail away is that it makes the code easier to read because we don't have to hold as much information about what is going on in our head at any one time.
The aim is to try and ensure that the chunks of code that we extract into a method are all at the same level of abstraction - Neal Ford refers to this as the Single Level of Abstraction Principle (SLAP) in The Productive Programmer.
We would therefore not have a chunk of code which described some business concept or rule mixed in with a bit of code that was interacting with the database as an extreme example.
I find myself most frequently extracting method when I come across several lines of code doing similar operations, the aim being that when we read the code we don't need to care about each of the individual operations but just the fact that operations are being done.
It exposes semantic errors
One benefit which I hadn't actually appreciated until recently is that extracting a method can actually help to identify areas of code which shouldn't actually be where they are.
We were recently working on some code around starting up a Selenium session where the 'ResetSeleniumSession' method was doing the following:
public ISelenium ResetSeleniumSession()
{
if(Selenium != null)
{
Selenium.Stop();
}
Selenium = new CustomSelenium(....)
Selenium.Start()
Selenium.Open(ApplicationRootUrl);
Selenium.WindowMaximize();
}
We didn't think those last two lines belonged in there so we extracted them out so that we could make sure that the opening of the selenium client was still being done in all the places that ResetSeleniumSession was being called:
public ISelenium ResetSeleniumSession()
{
...
Selenium = new CustomSelenium(....)
Selenium.Start()
LoadAndMaximise(ApplicationRootUrl);
}
Later on another colleague passed by and saw us looking at this method and pointed out that it was wrong that we were launching the client from inside this method and had probably been added into that method by mistake!
Maybe that code would have been spotted anyway but it had been like that for a while and I think extracting it out into its own method to make it more obvious was useful for exposing that.
In Summary
That's all I can think of for the moment although I'm sure there are more reasons why we'd want to extract method.
From my experience extract method is the most useful refactoring that we can do and it can quickly make a bit of code that seems impossible to understand somewhat readable and it can help keep new code that we write easy for others to understand instead of becoming a legacy mess.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
dennis sellinger replied on Thu, 2009/06/04 - 3:30pm
However, I have a few problems with overzealous extract method refactorings.
1. We should never (ever) break encapsulation when extracting a method. I think that an extracted method should always be private, except where you extract a method to allow sub classes to share code, in which case they can be protected.
2. We should stop extracting methods when the name of the extracted method starts to resemble the containing method. The name of the method is an indicator of what the method does, so if you can't think up a new name, it is likely that the method is already doing just one thing. When I start seeing methods like PerformAction calling a method called DoPerformAction, I know I have gone to far.
3. Classes with a large number of small method become hard to navigate. I have noticed this sometimes when I have been particularly active in refactoring and I come back to find exactly where some action is accomplished, I have to navigate through five or six methods. Each of the methods along the way adds little to my understanding (especially if we approach the problem in point 2). In this case, I wonder if all my work was not counter-productive.
4. My biggest complaint about extract method is that it is really hard to implement a good extract method tool in the IDE and so we generally are under-exploiting the opportunities to improve code. I use mostly visual studio so other IDEs may vary, but my experiences with Eclipse are similar. I find that the extract method tools typically screws up the return values and the arguments. This is especially true if you are extracting code for reuse among two or more methods. In this case you will almost always have to have a method signature that is a compromise between different code blocks that will use the extracted member. Second, the tools I use just put the method at the front of the file or after the current method. Since I *HATE* messy code like this (e.g. mixing public and private methods) I always have to move the extracted method somewhere else. In the end, if I had just copied the code and created a new method in the right place and updated the arguments, without the extract method tool, I think I would have saved time. So in the end, I think the extract method tool, in general, makes for messy class files and in general reduces the effectiveness of the extract method refactoring.