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

Saturday, August 29, 2009

Many-To-One Composition Relationships

Many-to-one relationships are very common, especially in applications involving databases. The reason for this is that the many-to-one paradigm is a common scenario in the real world, and programming languages, databases, and other technical constructs attempt to represent the real world.

Consider the relationship between a car and its tires. Composition solves the problem of how a car "has" tires. It would go something like this:


///Here is a generic implementation of a Car class
public class Car
{
   private List _allFourTires;

   public Car()
   {
      _allFourTires = new List();
   }
}

///And here is the class "Tire", which composes Car
public class Tire
{
   private string _model;

   private string _type;

   private int _width;

   private double _aspectRatio;

   ///You get the idea
}


The List<> type is a great way to solve the problem of many-to-one composition, but there is another way in C#, and it is called "Collections."

Collections are implemented in a lot of the base .Net objects, including DataSets and DataTables.

For instance, consider the below code:


///Assume I have a DataSet called myDataSet, and it has
///a bunch of datatables in it
foreach(DataTable table in myDataSet.Tables)
{
   foreach(DataRow row in table.Rows)
   {
      ///Do some stuff with the table
   }
}


The reason DataSet has a .Tables and a DataTable has .Rows is because they implement the IEnumerable .Net interface.

As mentioned above, an alternative to implementing the IEnumerable is to have a DataSet have a List<> variable with DataTables, and to have a DataTable have a List<> variable of DataRows, but over time, the IEnumerable is easier to manage.

Interfaces are a public contract between classes. They're basically a grocery list, and if you plan on using them, you must have everything on the grocery list. Luckily, IEnumerable has only one "item" on the list. That item is a public method called GetEnumerator().

When implementing a paradigm such as this, the effect you're really having is to create a bridge between the container class (Car), and the containee class (Tire). So, in between Car and Tire goes the IEnumerable class. In the below example, we'll call it TireCollection


/// The container class
public class Car
{
   ///A global variable of the bridge (IEnumerable) class
   private TireCollection _tireCollection;

   /// Constructor - makes a tire collection based
   /// on the model
   public Car(string model)
   {
       makeTireCollection(model);
   }

   /// This is just sort of a factory method - I could
   /// get more abstract, and create a TireCreatorFactory
   /// class, but I think this is sufficient for this example
   private void makeTireCollection(string model)
   {
       if (model == "Ford")
          makeFordTireCollection();
   }

   /// Makes the tire collection for Ford cars
   private void makeFordTireCollection()
   {
       List tireList = new List();
       tireList.Add(new Tire("Bridgestone", "P", 215, 75));
       tireList.Add(new Tire("Bridgestone", "P", 215, 75));
       tireList.Add(new Tire("Bridgestone", "P", 215, 75));
       tireList.Add(new Tire("Bridgestone", "P", 215, 75));
       _tireCollection = new TireCollection(tireList);
   }

   /// This is an unnecessary attribute, but if I didn't have this
   /// I would have to do:
   /// foreach(Tire in car)...
   /// With this attribute, I can do
   /// foreach(Tire in car.Tires)
   /// I like that better
   public TireCollection Tires
   {
       get { return _tireCollection; }
   }
}


Notice in the above, I have an attribute called Tires. As mentioned in the comments, this is an unnecessary attribute, but I think it looks cleaner when we go to implement the Car class.

Below is the IEnumerable class TireCollection. Note that it has a method called GetEnumerator():


/// This essentially acts as a bridge between
/// the Car class and the tire class
public class TireCollection : IEnumerable
{
   ///We do have a List<> variable in the TireCollection.
   ///So, in effect, we don't get away from having a List<>
   ///variable...the collection simply buys us a "decoupling"
   ///effect
   List _tireList;

   public TireCollection(List tireList)
   {
       _tireList = tireList;
   }

   public IEnumerator GetEnumerator()
   {
       return (_tireList as IEnumerable).GetEnumerator();
   }
}


Then, the Tire class looks pretty typical


/// This is the Tire class - there are many tires on a car
/// Well...four, anyway
public class Tire
{
   private string _model;

   private string _type;

   private int _width;

   private double _aspectRatio;

   /// Constructor
   public Tire(string model, string type, int width, double aspectRatio)
   {
       _model = model;
       _type = type;
       _width = width;
       _aspectRatio = aspectRatio;
   }

   /// This is simply a public method
   public string GetTireProperties()
   {
       return "Tire is of model " + _model + " with type " + _type;
   }
}


Now comes the question of how to implement this code. This part is the simple part:


Car car = new Car("Ford");
foreach (Tire tire in car.Tires)
{
   ///Output tire.GetTireProperties()
}


It is a few more steps to implement an IEnumerable interface, but it's worth it for those solutions that wish to have looser coupling between the composition relationship.

In the comments in the makeFordTireCollection() method in Car, I mention that I could have just as easily implemented a TireCreatorFactory class that assembles a Tire collection for me. The effect of doing so would have provided a higher degree of decoupling between Car and Tire, which is probably a more optimal situation, since loosely coupled class interactions are highly valued in object oriented design.

Friday, August 21, 2009

Is-A Versus Has-A

Is-A versus Has-A

Believe it or not, the concept of whether a class "Is a [something]" or "Has a [something]" comes up quite a bit in object oriented design. For instance, consider the questions "Is a transmission a car?" and "Does a car have a transmission?"

Clearly, the second question is the only of the two that one would answer in the affirmative. A transmission is not a car, but a car does have a transmission. This is a classic "Is-A/Has-A" example. And sometimes the answer to the questions are not so clear cut, particularly if the relationship is more obscure, like the relationship between a wall and sheetrock. For example, sheetrock, if hanged, could perform the duties of a wall, and a wall can contain sheetrock. The implementation of the solution to that question could probably be solved with either implementing a "Is-A" paradigm, or a "Has-A" paradigm.

So, I haven't described how "Is-A" and "Has-A" are implemented in object oriented design. Well the answer to that is really quite simple:

"Is-A" is implemented via INHERITANCE
"Has-A" is implemented via COMPOSITION

INHERITANCE

Inheritance is a good solution when some component would be logically defined, more abstractly, as another object.

For instance, think of fruit. Fruit is really more of an abstract concept than it is an implementation. Fruit can either have seeds (raspberries), or not have seeds (bananas). It can also have rind (bananas), or not have rind (raspberries). These attributes (seeds, rinds) are values that the more abstract "fruit" has.

The implementation of this code could be as follows:

///Below is the "Fruit" class

public class Fruit
{
   private bool _hasSeeds;
   private bool _hasRind;

   ///Public attribute for whether or not the fruit has seeds
   public bool HasSeeds
   {
      get { return _hasSeeds; }
      set { _hasSeeds = value; }
   }

   ///Public attribute for whether the fruit has a rind
   public bool HasRind
   {
      get { return _hasRind; }
      set { _hasRind = value; }
   }   
}

///Public implementation of Banana
///Inherits from Fruit
public class Banana : Fruit
{
   ///Because the nature of a banana lends itself
   ///to knowing whether or not it has seeds and rind
   ///I will set those attributes in the constructor
   ///There is no reason that the class who calls
   ///Banana should have to know that a banana does not
   ///have seeds and does have a rind.
   public Banana()
   {
      this.HasSeeds = false;
      this.HasRind = true;
   }

   public void Peel()
   {
      ///Do some kind of action to peel the banana
      ///Since Peel() is not common among all fruits
      ///Peel() does not have to be in the Fruit class
      ///However, there may be reasons to put it in there
      ///anyway. It depends on how similar the behavior
      ///is for all fruits' Peel() behavior
   }
}

///Public implementation of Banana
///Inherits from Fruit
public class Raspberry : Fruit
{

   ///Like in Banana, raspberries HasSeeds and HasRind
   ///attributes are set
   public Raspberry()
   {
      this.HasSeeds = true;
      this.HasRind = false;
   }
}


As you can see, this example lends itself very well to the "Is-A" paradigm, because clearly, Bananas and Raspberries are "Fruit." Also note that in the above, I did not put the Peel() method in the Fruit class, because it didn't seem to belong there. If I have an issue where many fruits need to have the Peel() behavior defined in them, I could do one of the following:

1. Create an interface, and have any peelable fruit invoke it:

public interface IPeelableFruit
{
   ///Notice how there is no implementation in the interface's Peel()
   ///This is because an interface has no implementation
   ///It is simply a public contract between anyone implementing it
   void Peel();
}


Making an interface like the above would make a lot of sense if each fruit's implementation of Peel() were significantly different from one another.

With an interface, when I declare Banana, or any other peelable fruit, it would look like:

public class Banana : Fruit, IPeelableFruit
{
   public void Peel()...
}


2. I could create a PeelableFruit class, and a NonPeelableFruit class, and have subsequent classes inherit:

public class PeelableFruit : Fruit
{
   public PeelableFruit()
   {
      this.HasRind = true;
   }
}


Then declare Banana as follows:

public class Banana : PeelableFruit
{
...
}


What would happen in the above example is: PeelableFruit would be a fruit. Banana would be ("is-a") a PeelableFruit, and also a Fruit, because it would inherit from both. The technical term is "inheritance chain".

COMPOSITION

"Has-A" lends itself to object relationships where something contains something else, like the above example of a Car and a Transmission. But, suppose we wanted to really define, in a fruit, what a "Rind" is. This would give us a pretty good example of "Has-A", because a PeelableFruit "Has-A" Rind.

So, if I wanted to build a "Rind" class, I would do something like the following:


public class Rind
{
   private string _color;
   //Let's say this is how difficult the rind is
   //to peel
   //A banana would be something like 2, and an orange would
   //be 5
   private int _difficultyToPeel;

   private int _thicknessInMillimeters;

   ///Each of these private members would also have
   ///corresponding public members. I'll omit those

   public Rind(string color, int difficultyToPeel, int thicknessInMillimeters)
   {
      _color = color;
      _difficultyToPeel = difficultyToPeel;
      _thicknessInMillimeters = thicknessInMillimeters;
   }
}


So, now that the Rind class is defined, we can now put a Rind object into the PeelableFruit Class:


public class PeelableFruit : Fruit
{
   ///In the constructor, I instantiate the Rind object
   ///Otherwise, later on in the execution, I may forget
   ///and exceptions will get thrown
   ///Note the constructor had to be changed to facilitate
   ///the necessity to instantiate the
   ///Rind object (the color, difficulty, and thickness)
   ///parameters
   public PeelableFruit(string rindColor, int difficultyToPeel, int thicknessInMillimeters)
   {
      this.HasRind = true;
      this.PeelableFruitRind = new Rind(rindColor, difficultyToPeel, thicknessInMillimeters);
   }

   protected Rind PeelableFruitRind;
}


Then, when it comes time to instantiate a banana, doing so gives the banana much more robustness:

public class Banana : PeelableFruit
{
   ///I don't really know if this is "best practice" to make a class so knowing of how
   ///it implements a parent class, but I don't care. This is how I will continue
   ///to invoke this sort of inheritance
   public Banana() : base("YELLOW", 2, 7)
   {

   }
}


Note that, when Banana gets instantiated, it will inherit the PeelableFruit's protected variable PeelableFruitRind, and that fruit rind will have a color of "YELLOW", a peeling difficulty of 2, and a thickness of 7 millimeters. Now, Banana "Has-A" rind, and that means it's using COMPOSITION.

Followers

Search This Blog

Powered by Blogger.