title: Smaller methods, cleaner code description: > Refactoring large methods into classes with smaller methods. categories: posts
Table of Contents
In a 4 line function there's no chance for deeply nested code or complex if
statements. This promotes the use of well chosen, highly descriptive names which
will tell you what a function does.
This style of programming also promotes the extraction of predicates from if
statements and while loops into boolean methods.
Large methods should be refactor into one or more classes with tiny methods. This will make your code easier to understand, to read, to change, and maintain, which is ultimately the kind of code you want to work with.
It takes time to eliminate redundancy and make things small, but by doing so, we get a better understanding of what we are solving. On the contrary, keeping large methods places a burden on the reader, who will have to figure out the thought process that delivered that code every time she needs to work with it.
A large method is a scope usually seen as major indentation sections. Those sections communicate with each other using variables local to the entire scope. A class, on the other hand, although it has variables these aren't necessarily accessible from anywhere in the class. Also, major sections are recognizable as methods rather than by white space. Since a large method has a rather similar structure to that of a class it should be extracted in to one or more classes.
When extracting classes out of large functions you should consider: (assume green tests after each step)
A method should do one and one thing only. But saying "one thing" is ambiguous. Let's dig a bit deeper to see what "one thing" implies. If a method is composed of many different sections then it's clearly doing more than one thing. If a method manipulates more than one level of abstraction is doing more than one thing. For instance, path parsers and page crawlers are implementation details at a low level of abstraction. Whereas reports are business concepts at a high level of abstraction. We don't want one method manipulating both concepts. Instead, we want to separate the levels of abstraction into different methods. Hence, if we want our methods to do only one thing they should never cross levels of abstractions.
The only way to ensure a method does one thing only is to continuously extract other methods from your code until you can't extract any more methods. After all, if you can extract a method from another one then, by definition, the original method was doing more than one thing. The end result should be classes with methods no longer than 5 lines long.