My struggles in understanding and learning about Object Oriented design, and the tools and knowledge I've taken from them.

Thursday, January 14, 2010

Collection Classes

In his book Prefactoring, Ken Pugh talks about collections of objects. Pugh's assertion is that: "If it has collection operations, make it a collection."

The above statement has been one of the most helpful axioms I have found in building object oriented applications. Before I was armed with the tool of the "Collection" class, I used some bastardization of arrays or lists, and did all their operations within the parent class. This made for pretty sloppy code. For instance, consider the following:

class ParentClass
{
   private List _childClassList;

   public ParentClass()
   {
      ///Create the new list object in constructor
      _childClassList = new List();
   }

   /*******************************
    * Here are all the behaviors
    * of the ParentClass object
    *******************************/

   public int GetChildClassCount()
   {
      return _childClassList.Count;
   }

   public void AddToChildList(string val)
   {
      _childClassList.Add(val);
   }

   public string GetLongestStringInChildClassList()
   {
      string longestString = String.Empty;

      foreach(string member in _childClassList)
      {
         if(member.Length > longestString.Length)
            longestString = member;
      }

      return longestString.ToUpper();
   }
}

The above code works, but the methods GetChildClassCount(), AddToChildList(), and GetLongestStringInChildClassList() don't belong in ParentClass. They belong in a separate class, and deserve their own separate implementations.

Before going further, bear in mind that as .Net progresses, many of these functionalities are becoming available in the "primitive types" that .Net offers. For instance, as of .Net 3.5, the List<> variable has a GetAverage() function that does this for you...it also has a lot of those other features; however, I believe that adding a layer of abstraction can be a powerful tool for both consistency of code in your application, and for coding standards, if you're working with multiple developers.

So, refactoring the above code, I would probably do something like this:

class ParentClass
{
   ///Notice here I substitute the List for a
   ///ChildClassCollection
   private ChildClassCollection _childClassList;   

   public ParentClass()
   {
      ///Create the new collection object in constructor
      _childClassList = new ChildClassCollection ();
   }

   /*******************************
    * Here are all the behaviors
    * of the ParentClass object
    *******************************/

   public void DoStuff(string input)
   {
       if( input.ToUpper() == _childClassList.GetLongestStringInChildClassList() )
          ///Do stuff here
   }

}

class ChildClassCollection
{
   private List _childClassList;

   public int GetChildClassCount()
   {
      return _childClassList.Count;
   }

   public void AddToChildList(string val)
   {
      _childClassList.Add(val);
   }

   public string GetLongestStringInChildClassList()
   {
      string longestString = String.Empty;

      foreach(string member in _childClassList)
      {
         if(member.Length > longestString.Length)
            longestString = member;
      }

      return longestString.ToUpper();
   }
}

In my mind, the above example of factoring out the first code example's behavior into 2 classes really looks better, and gets at something that I think is really important in building object oriented systems: class relationships.

Understanding relationships between different "things" in your code, and knowing how to represent them in a solid class relationship is key to building high quality code.

No comments:

Followers

Search This Blog

Powered by Blogger.