Herman J. Radtke III

Read more of my blog or subscribe to my feed.


Unit Testing and the Law of Demeter

Written by Herman J. Radtke III on 17 Jan 2010

I was writing some code today and not using Test-Driven development.  The reason was that I did not have a good understanding of what I was writing, so I decided to write some of the guts before writing the tests.  In the process of writing the guts, I recognized that I was paying very close attention to how I was going to later test each of the methods I was writing. I was paying especially close attention to the Law of Demeter.   The idea behind the Law of Demeter is to keep units of code distinct from one another. So how did this relate to my code?  To put it simply, my business logic methods did not use get methods. Assume we have a person class.  The class constructor takes the persons full name and we have a getter and setter for the full name.
setFullName($fullName);
    }

    public function setFullName($fullName)
    {
        $this->_fullName = $fullName;
    }

    public function getFullName()
    {
        return $this->_fullName;
    }
}
There is also a method that parses apart the persons full name into separate parts. The naive approach:
    public function parseFullName()
    {
        $nameParts = explode(' ', $this->getFullName());
        ...
    }
This code works fine, but think about how we will write a test for this function.  We have to first set the full name using a setter so the parseFullName method can retrieve that value with a getter.  This violates one of the principle rules of unit testing: testing individual units of code.  If there is a bug in the getter or setter functions, they may inadvertently affect my test.  This is a very real issue when using the magic __get and __set methods. It also means more work to setup your tests because you have to keep in mind an order of operations when testing. The better approach:
    public function parseFullName($fullName)
    {
        $nameParts = explode(' ', $fullName);
        ...
    }
Notice how the parseFullName function is being told what to parse rather than asking what to parse.  This subtle change now allows us to truly test this individual unit of code with the least amount of outside environment interaction.
Reblog this post [with Zemanta]