Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Wicked Cool Jobs

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Composed Method Pattern

This was supposed to be a part of a much longer post on writing maintainable code, but I'm having trouble finishing the bigger post and I wanted to see an actual code-centric post before the new year.

I've talked a lot about Object Oriented concepts in the past, but there's always procedural code lurking inside each and every class.  I feel very strongly that long methods and big classes are a veritable breeding ground for bugs.  Small methods (and classes) are easier to troubleshoot by inspection, and hence, less likely to have bugs than a long method.  To keep methods small and easily understandable, I like the Composed Method pattern first described by Kent Beck.  The Composed Method pattern states that:

  1. Divide your code into methods that only perform a single, identifiable task. 
  2. Keep all of the operations in a single method at the same level of abstraction.  Think of a method that iterates through a collection and performs an operation with each child object.  If we apply the Composed Method pattern we would move the operation on the child object into a separate method that is called from the main method.
  3. Following the Composed Method pattern will lead to the kind of small methods that make trouble shooting easier.

In other words, using the Composed Method means assiduously avoiding the ArrowHead Anti-Pattern (deep if/then or looping hierarchies in a single method).

Here's an example that I lifted from Joshua Kerievsky's Refactoring to Patterns book that illustrates the application of Composed Method.  Pretending that the ArrayList class in .Net doesn't exist, create a resizable collection class that can be locked into a read only mode.  The internal storage is just an array.  As necessary the class will create a new, larger internal array.  If we use pure brute force coding to build the Add() method in one big method we might get this code below.

    public class MyExpandableList

    {

        private object[] _elements = new object[10];

        private bool _readOnly;

        private int _size = 0;

 

 

        public void Add(object child)

        {

            if (!_readOnly)

            {

                int newSize = _elements.Length + 1;

                if (newSize > _elements.Length)

                {

                    object[] newElements = new object[_elements.Length + 10];

                    for (int i = 0; i < _size; i++)

                    {

                        newElementsIdea = _elementsIdea;

                    }

 

                    _elements = newElements;

                }

 

                _elements[_size] = child;

                _size++;

            }

        }

 

        public bool ReadOnly

        {

            get { return _readOnly; }

            set { _readOnly = value; }

        }

    }

It's not the biggest, hairiest method in the world, but it could definitely be better.  Let's clean up the Add() method by doing these 6 refactorings.

  1. Invert the "readonly" check to a Guard Clause
  2. Extract Method - void addElement(object)
  3. Introduce Explaining Variable - shouldGrow
  4. Decompose Conditional - bool atCapacity()
  5. Inline Variable - shouldGrow --> atCapacity()
  6. Extract Method - void grow()

Applying that series of refactorings to the Add() method leads to this second version of the expandable list class.

    public class MyExpandableListRefactored

    {

        private object[] _elements = new object[10];

        private bool _readOnly;

        private int _size = 0;

 

 

        public void Add(object child)

        {

            if (_readOnly)

            {

                return;

            }

 

            if (atCapacity())

            {

                grow();

            }

 

            addElement(child);

        }

 

        private void grow()

        {

            object[] newElements = new object[_elements.Length + 10];

            for (int i = 0; i < _size; i++)

            {

                newElementsIdea = _elementsIdea;

            }

 

            _elements = newElements;

        }

 

        private bool atCapacity()

        {

            int newSize = _elements.Length + 1;

            return newSize > _elements.Length;

        }

 

        private void addElement(object child)

        {

            _elements[_size] = child;

            _size++;

        }

 

        public bool ReadOnly

        {

            get { return _readOnly; }

            set { _readOnly = value; }

        }

    }

I ended up adding several new methods, but the methods are very simple, and the Add() method is far more readable.  I'm sure that the obvious objection to Composed Method is that the longer stack traces and call stacks making the code harder to debug.  My simple answer is that a combination of using Test Driven Development and well factored code should minimize the need for the debugger.


Posted Sun, Dec 3 2006 1:58 PM by Jeremy D. Miller

[Advertisement]

Comments

Justin Michel wrote re: Composed Method Pattern
on Sun, Dec 3 2006 5:35 PM

1) The Add() method silently does nothing if the list is in ReadOnly mode. If you think about it this is really conceptually equivalent to writing the following:

public void Add(object 0) {

 try {

   if (_readOnly) {

     throw new ReadOnlyException("Can't Add to ReadOnly List.");

   }

   ...

 } catch (ReadOnlyException) {

    // ignored

 }

}

It would be better to create a ReadOnlyException class and throw from Add().

2) The atCapacity() method always returns true. It should be comparing _size to _elements.Length.

I also don't see any value in this trivial method. Is the following really any less readable?

if (_size >= _elements.Length)  {

 growBy(1);

}

It also might be a little easier to read IMHO if growBy() contained the check.

3) This code shouldn't use a for loop to copy array elements. Array.Copy() already exists.

4) As with atCapacity(), the addElement() method is really too trivial to warrant its own method.

5) Growing by 10 seems rather strange. The generally accepted practice is to grow by 50%.

I might do it like this:

public class MyExpandableList {

 private int _size = 0;

 private object[] _elements = new object[INITIAL_SIZE];

 private bool _readOnly;

 public void Add(object o) {

   if (_readOnly) {

     throw new ReadOnlyException("Can't add to readonly list.");

   }

   growBy(1);

   _elements[_size - 1] = o;

 }

 private void growBy(int count) {

   _size += count;

   if (_size < _elements.Length) {

     return;

   }

   object[] tmp = new object[_size + (_size / 2)];

   Array.Copy(_elements, 0, tmp, 0, _elements.Length);

   _elements = tmp;

 }

 public bool ReadOnly {

   get {

     return _readOnly;

   }

   set {

     _readOnly = value;

   }

 }

}

Ian Horwill wrote re: Composed Method Pattern
on Mon, Dec 4 2006 3:42 AM

You're right - refactoring does help you spot bugs! atCapacity() always returns true.

Steve Mitcham wrote re: Composed Method Pattern
on Mon, Dec 4 2006 6:53 AM

I spotted the at capacity bug as well.  What I've noticed as I've gotten into refactoring and this composed method pattern is that I'll pick apart some code into separate methods.  The new methods can usually be optimized now that they are separate and .  

If the new smaller (many times one line) method is not being used in multiple places, I can put it back in the original method from which it was extracted.  When I'm finished, a 30 line method has been reduced to a 10 line method with much more readable structure.  

SteveJ wrote re: Composed Method Pattern
on Mon, Dec 4 2006 7:26 AM

I'm a big fan of small classes and small methods, but I find a great deal of people have a hard time knowing where to start when they're trying to figure a component out and it doesn't have one humongous master class that does everything important.  Has anyone come across a good way to provide a centralized starting point for a major component without resorting to code bloat?  I guess I'm looking for something more substantial than a common interface pattern, the people I work with at least want to dig down into the source and see what the code is REALLY doing before they call methods on it (i.e abstraction isn't really trusted).

For instance I'm writing a pretty complex component that has 150+ classes (50,000+ LOC).  (I've seen linux kernels that try to do less than this component).  Even those classes are a bit too big for me.  But I'm wary of refactoring farther when I know it's already too hard for someone else to figure out what all those packages are for.  

Anyway, any concrete suggestions and examples would be useful.  Are there any open source projects that you know of that seem pretty easy to grasp even if they are matching the complexity of an OS?  I'd like to have a structure (outside of a design doc or comments) that allows a maintenance programmer the ability to grasp what each package does at a glimpse.  Something self-referential so one could work their way backwards and forwards through the code without a rosetta stone.

Mike Nichols - Son of Nun Technology wrote Refactoring Example
on Mon, Dec 4 2006 7:54 AM

Refactoring Example

ScottBellware wrote re: Composed Method Pattern
on Tue, Dec 5 2006 9:53 AM

SteveJ,

I do it with tests.  By convention, I like to keep tests that demonstrate the primary responsibility(s) of a class at the top of the test class.  Tests that exercise helper methods show up later in the class.

I don't really grok the idea of a component having an entry point though.  That's not really part of my design work.  If a component is a container for classes that are focused on the same architectural concern, how would one class in the component by more primary than another?

IMO, the best way to demonstrate what a class is for is to just demonstrate it with client code.  The best way to do that in my experience is to use a client-driven design practice like test-driven development, behavior-driven design, etc.

Jason Haley wrote Interesting Finds: December 5, 2006
on Tue, Dec 5 2006 10:21 PM
Jason Haley wrote Interesting Finds: December 5, 2006
on Tue, Dec 5 2006 10:26 PM
Ian Goodsell - Dev Emporium wrote Good Articles on Unit Testing, Design, and Test-Driven Development
on Thu, Apr 19 2007 4:04 PM

Jeremy D. Miller has some really good articles on unit testing, design and TDD. Here are some gems: ...

Colin Jack wrote re: Composed Method Pattern
on Sun, May 6 2007 6:50 AM

Good article, as stated by a previous reply though I don't like the readonly guard statement silently returning.

Rhonda Tipton’s WebLog Web Links 12.03.2006 « wrote Rhonda Tipton&#8217;s WebLog Web Links 12.03.2006 &laquo;
on Sun, Aug 19 2007 4:59 PM

Pingback from  Rhonda Tipton&#8217;s WebLog Web Links 12.03.2006 &laquo;

Jeremy D. Miller -- The Shade Tree Developer wrote Best of the Shade Tree Developer Part II
on Thu, Oct 18 2007 9:20 AM

About a year ago I hit a patch where I wasn&#39;t able to blog much (something about finding a new job

dave^2=-1 wrote Link: Refactoring walkthrough
on Fri, Feb 1 2008 5:22 AM

Jeremy Miller recently posted a " Best of... " compendium that included the following post: Composed

Jeremy D. Miller -- The Shade Tree Developer wrote Rightsizing your approach
on Tue, Apr 22 2008 12:38 PM

My last post, I might be an elitist, but you&#39;re a misanthrope , has kicked up a great conversation

on Thu, May 15 2008 4:09 PM

I&#39;ve been refactoring the StructureMap codebase in preparation for wrapping up the 2.5 release. I&#39;ve

Community Blogs wrote Why do we Refactor?
on Thu, May 15 2008 4:45 PM

I&#39;ve been refactoring the StructureMap codebase in preparation for wrapping up the 2.5 release. I&#39;ve

The Productive Programmer: Book Review at Mark Needham wrote The Productive Programmer: Book Review at Mark Needham
on Thu, Sep 4 2008 7:16 PM

Pingback from  The Productive Programmer: Book Review at Mark Needham

Troy Sabin wrote Composed Method Pattern
on Wed, Oct 1 2008 10:24 AM

Composed Method Pattern

thiagodp wrote re: Composed Method Pattern
on Thu, Aug 13 2009 7:09 PM

@Justin Michel

I don't like the idea of growBy modifing _element and _size and addElement have to know about it.  Instead of knowing about the internals of growBy and make:

<code>

growBy( 1 );

_element[ _size - 1 ] = o;

</code>

it's better create a setLastElement method that does it:

<code>

public void setLastElement(object o)

{

   _element[ _size - 1 ] = o;

}

</code>

So we will have:

<code>

public void addElement(object o) {

  if (_readOnly) {

    throw new ReadOnlyException("Can't add to readonly list.");

  }

  growBy( 1 );

  setLastElement( o );

}

</code>

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us