Small!

From WikiContent

(Difference between revisions)
Jump to: navigation, search
Line 41: Line 41:
The point is that functions should be ''small''. How small? Just a few lines of code with one or two levels of indent.
The point is that functions should be ''small''. How small? Just a few lines of code with one or two levels of indent.
 +
 +
"You can't be serious!" I hear you say. But serious I am. It is far better to have many small functions than a few large ones.
 +
 +
"But doesn't the proliferation of functions make the code more confusing?"
 +
 +
No, just the opposite. Large and deeply indented functions are much more confusing that lots of simple little functions.
 +
 +
Think of it this way. When you were young you had a "system" for knowing where all your things were. They were on the floor of your room, or under the bed, or in a pile in your closet. Your mother would yell at you from time to time to clean up your room, but you did your best to thwart her intent because your system worked just fine for you. You knew that tomorrow's socks were right on the floor where you left them last night. The same for your underwear. You knew that your favorite toy was under your bed somewhere. You had a system.
 +
 +
But finally your mother got so frustrated that she forced you to help her (meaning watch her) clean up your room. You watched as she hung clothes up in the closet, and put toys on shelves or in drawers. You watched as she organized your things and put them away. And (sometime in your 30s) you realized that she had a point.
 +
 +
Yes, it's generally better to have a place for everything and put everything in it's place. And that's just what dividing your code into many small functions is. Large functions are just like all the clothes under your bed. Splitting them up into many little functions is like putting all your clothes on hangers and sorting them nicely in your closet. Large functions are a child's way to organize. Small functions are an adult's (or should I say a professional's) way to organize.
 +
 +
Of course it's more than just keeping functions small and simple. You also need to keep their coupling low. You don't want them to know about too many variables or take too many arguments. The more variables and arguments the tighter the coupling. I generally prefer that a function have fewer than 3 arguments. Two is better. One if even better! And of course ZERO is best!
 +
 +
Classes should also be small. A few dozen methods, and perhaps half a dozen variables is a good upper bound.

Revision as of 13:02, 18 November 2008

Look at this code:

 private void executeTestPages() throws Exception {
   Map<String, LinkedList<WikiPage>> suiteMap = makeSuiteMap(page, root, getSuiteFilter());
   for (String testSystemName : suiteMap.keySet()) {
     if (response.isHtmlFormat()) {
       suiteFormatter.announceTestSystem(testSystemName);
       addToResponse(suiteFormatter.getTestSystemHeader(testSystemName));
     }
     List<WikiPage> pagesInTestSystem = suiteMap.get(testSystemName);
     startTestSystemAndExecutePages(testSystemName, pagesInTestSystem);
   }
 }

Your first reaction is probably not positive. Not because the code is that complicated or daunting, but just because you don't necessarily feel like untangling the intent hidden in 11 lines of code with 3 levels of indent. You know you can do it, but it feels like work.

Now look at this function:

 private void executeTestPages() throws Exception {
   Map<String, LinkedList<WikiPage>> pagesByTestSystem;
   pagesByTestSystem = makeMapOfPagesByTestSystem(page, root, getSuiteFilter());
   for (String testSystemName : pagesByTestSystem.keySet())
     executePagesInTestSystem(testSystemName, pagesByTestSystem);
 }

Notice that it doesn't feel so much like work. You can look at it, and grasp the intent without much effort. Not much has changed, I've just cleaned up a few variable names and extracted a few functions. And yet that small change, so easy to do with modern refactoring browsers and a suite of tests, makes the function much easier to read.

The extracted functions are pretty easy to read too:

 private void executePagesInTestSystem(String testSystemName,
                                       Map<String, LinkedList<WikiPage>> pagesByTestSystem) throws Exception {
   List<WikiPage> pagesInTestSystem = pagesByTestSystem.get(testSystemName);
   announceTestSystem(testSystemName);
   startTestSystemAndExecutePages(testSystemName, pagesInTestSystem);
 }
 private void announceTestSystem(String testSystemName) throws Exception {
   if (response.isHtmlFormat()) {
     suiteFormatter.announceTestSystem(testSystemName);
     addToResponse(suiteFormatter.getTestSystemHeader(testSystemName));
   }
 }

The point is that functions should be small. How small? Just a few lines of code with one or two levels of indent.

"You can't be serious!" I hear you say. But serious I am. It is far better to have many small functions than a few large ones.

"But doesn't the proliferation of functions make the code more confusing?"

No, just the opposite. Large and deeply indented functions are much more confusing that lots of simple little functions.

Think of it this way. When you were young you had a "system" for knowing where all your things were. They were on the floor of your room, or under the bed, or in a pile in your closet. Your mother would yell at you from time to time to clean up your room, but you did your best to thwart her intent because your system worked just fine for you. You knew that tomorrow's socks were right on the floor where you left them last night. The same for your underwear. You knew that your favorite toy was under your bed somewhere. You had a system.

But finally your mother got so frustrated that she forced you to help her (meaning watch her) clean up your room. You watched as she hung clothes up in the closet, and put toys on shelves or in drawers. You watched as she organized your things and put them away. And (sometime in your 30s) you realized that she had a point.

Yes, it's generally better to have a place for everything and put everything in it's place. And that's just what dividing your code into many small functions is. Large functions are just like all the clothes under your bed. Splitting them up into many little functions is like putting all your clothes on hangers and sorting them nicely in your closet. Large functions are a child's way to organize. Small functions are an adult's (or should I say a professional's) way to organize.

Of course it's more than just keeping functions small and simple. You also need to keep their coupling low. You don't want them to know about too many variables or take too many arguments. The more variables and arguments the tighter the coupling. I generally prefer that a function have fewer than 3 arguments. Two is better. One if even better! And of course ZERO is best!

Classes should also be small. A few dozen methods, and perhaps half a dozen variables is a good upper bound.


by Uncle Bob

This work is licensed under a Creative Commons Attribution 3


Back to 97 Things Every Programmer Should Know home page

Personal tools