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

Tuesday, December 29, 2009

Factory Design Pattern

I try not to get too wrapped up in design patterns, because one can really overuse them, or use them in inappropriate places, if one is not careful; that's not to say that design patterns don't have their place, because I think design patterns are common ways programmers have found to "best practice" object oriented programming.

But even though I try not to over-emphasize design patterns, there are several design patterns that I find myself using over-and-over again. One such pattern is the factory pattern.

Factory patterns are often used with inheritance or interfaces, because one of the best uses of a factory design pattern is for figuring out what the best version of object is to instantiate, based on some input.

A factory pattern is basically an object that has some method that is a big if-statement (or switch statement, if one prefers). For instance, suppose your configuration file had a configuration for what type of data access you want to use (MSSQL, XML, Oracle, mySQL, etc).

Here's a simple example. The classes (along with accompanying interface) would look something like this:

interface IAccessLayer
{
    string GetQueryResultsAsString(string query);
   DataTable GetQueryResultsAsDataTable(string query);
   void ExecuteModificationQuery(string query);
}

Implementing classes might look something like this:

class MSSQLAccessLayer : IAccessLayer
{
   ///Implement public contract from IAccessLayer
}

class mySQLAccessLayer : IAccessLayer
{
   ///Implement public contract from IAccessLayer
}

class XMLAccessLayer : IAccessLayer
{
   ///Implement public contract from IAccessLayer
}

class OracleAccessLayer : IAccessLayer
{
   ///Implement public contract from IAccessLayer
}

If the configuration file had a finite set of allowable strings for the access layer that were as follows:

MSSQL
ORACLE
XML
MYSQL

Then, the factory method would look something like this:


public IAccessLayer GetAccessLayer(string dataAccessMedium)
{
   dataAccessMedium = dataAccessMedium.ToUpper();
   if(dataAccessMedium == "MSSQL")
   {
      return new MSSQLAccessLayer();
   }

   else if(dataAccessMedium == "ORACLE")
   {
      return new OracleAccessLayer();
   }

   else if(dataAccessMedium == "MYSQL")
   {
      return new mySQLAccessLayer();
   }
   else if(dataAccessMedium == "XML")
   {
      return new XMLAccessLayer();
   }
   else
   {
      throw new Exception("Error. " + dataAccessMedium + " is not a valid data access method");
   }
}


The above is one application of the factory pattern. There are lots of variants, and lots of applications, which is why I felt so inclined to write about them.

By the way, check out my new project at SourceForge: TestAutomation. It helps to automate software testing in Windows environments. https://sourceforge.net/projects/testautomation/ . I'm always looking for people to join the project.

Monday, December 21, 2009

When to use Inheritance versus Interfaces

I tend to lean towards using interfaces, as opposed to inheritance. The reason for this is multi-fold:

1. I can implement multiple interfaces on a single class in C#. The only way I can implement multiple classes in C# is to have a big inheritance chain, which tends to get confusing, when going back to review code weeks or months later.
2. With interfaces, there's no ambiguity in who implements what behavior. There may be methods one overrides in C#, and that can get confusing when implementing a child class (ie Does the behavior this class uses match the parent class, or does it have different behavior?). With interfaces, I must define the behavior in each implementation.
3. In my world, and the types of applications I build, I don't see behavior being so expandable as to support a lot of inheritance; obviously, there are times when it makes complete sense to use inheritance, but for the most part, objects aren't that related.

That being said, there are times when I choose to use an interface, and find that it was an inappropriate choice for the solution I was trying to build. The reason it becomes inappropriate is because, when I first chose to use an interface, I didn't consider some of the granularity of the classes, and I start realizing that I'm re-doing a lot of work that I wouldn't have to do if I had chosen inheritance.

There are canned solutions that make solving these problems easier, such as abstract classes; however, in this example, I'll refrain from considering the abstract class as a possible solution.

Instead, I'll try to iterate some reasons to choose an interface, as opposed to inheritance, and vice-versa:

Reasons to choose an interface
1. Uncommon behavior, but a common "fingerprint": If you envision a set of classes having similar public methods, but uncommon private members, constructors, and behaviors, then an interface is probably the right choice
2. Defining multiple ways to arrive at a solution: The data access layer is a good example of this. An interface is a great way to have multiple options for database storage, and having that be a configurable piece of the software
3. Multiple developers working on common tasks: Interfaces were designed to solve problems that arise when multiple people are working independently of one another. Defining an interface (often referred to as a public contract) is a way to keep people on the same page.

Reasons to choose inheritance
1. Similar-looking classes: If classes begin to look very similar, especially at the private-member level, refactoring to make those private members protected, and implementing inheritance is probably a good decision
2. Common Behavior: Let's face it: interfaces exist because common behavior does occur between classes. "Inventing" common behavior, and forcing inheritance onto multiple classes that do not have a real relationship is not a good thing, though.

A lot of the decision to choose inheritance or interfaces comes down to style and preference; however, these are a couple "fun facts" I've gleamed in the process of writing code.

By the way, check out my new project at SourceForge: TestAutomation. It helps to automate software testing in Windows environments. https://sourceforge.net/projects/testautomation/

Followers

Search This Blog

Powered by Blogger.