GRASP Patterns - Information Expert - Create a Shopping Cart

I am a huge fan of Object-Oriented Programming and have come to believe that most of our programming challenges can be solved by focusing on the basics.  Although clever solutions to problems can be very cool, it often means that reading through the code can be challenging, time consuming, and require a lot of documentation.

Applying UML and Patterns by Craig Larman discusses several principles, called GRASP, that can help you with the fundamental challenges of object-oriented programming - assigning responsibilities to objects.

The first GRASP Pattern to mention is Information Expert.

  • Pattern Name: Information Expert
  • Problem:  What is a basic principle by which to assign responsibilities to Objects?
  • Solution: Assign a responsibility to the class that has the information needed to fulfill it.

I will be the first to say that this means absolutely nothing unless we have a concrete example.  In fact, it sounds so vague that it doesn't seem to have any value at all.

Let's take the code in my post, Create a Shopping Cart, to help clarify the power of this pattern.

In the shopping cart example, we wanted to have each Item show up only once in the cart.  If the same Item is being added to the cart, we wanted to increase the quantity of that Item as opposed to adding additional items in the _items ArrayList.

This programming challenge suggests that we need to determine if the item being added is equal to an item already in the shopping cart.  The question becomes, which object has the responsibility of deciding whether two Items are equivalent?

According to our business rules, two items in the shopping cart are identical if they have equivalent ProductID's.  Which object in our design model knows about ProductID?  The answer is Item.  And, according to the Information Expert GRASP Pattern, we should assign the responsibility of determing equality to Item, because it has the information needed to fulfill the responsibility.  As "luck" would have it, this is exactly what we did :)

In our shopping cart example, we used extensive use of the ArrayList.IndexOf method to determine if two Items are equal.  ArrayList.IndexOf uses System.Object's Equals method that we overrode to determine equality.  Thus, Item is determining equality with respect to other Item instances and the Information Expert GRASP Pattern is being fulfilled.

 

Item Class
public class Item : IFormattable
{
    // ...
    
    public override bool Equals(object obj)
    {
        if (obj == null) return false;
        if (Object.ReferenceEquals(this,obj))
return true; if (this.GetType() != obj.GetType())
return false; Item objItem = (Item)obj; if (_productID == objItem._productID)
return true; return false; } // ... }

 

As you can tell from the code above, the Item class determines equality with respect to other object's in the _items ArrayList via overriding System.Object's Equals method.  Below is the code that uses ArrayList.IndexOf in the Shopping Cart class:

 

ShoppingCart Class
public class ArrayListCart : ShoppingCart
{
    private ArrayList _items;
    
    // ...
    
    public override void AddItem(Item item)
    {
        int index = _items.IndexOf(item);

        if (index >= 0)
            UpdateItem(item);
        else
            _items.Add(new Item(item.ProductID,
             item.ProductName, item.Quantity, 
             item.UnitPrice));
    }
    
    // ...
    
}

 

The code in the Shopping Cart class AddItem method is small because it delegates the responsibility of equality to the Item class accordingly.  Although not shown in this example, a number of the Shopping Cart methods will also need to check the equality of two items in order to update and delete an Item in the cart.  By assigning responsibility of this function to the Item class, we also remove code smells from our application.

posted on Sunday, March 27, 2005 5:08 PM

My Links

Post Categories

Article Categories

Archives

Loose-Leaf Tea