1

Strategy in the Real World

by Jeremy 9. June 2011 16:13

I was recently working with a switch statement that was growing out of control, even as I was developing it.  In my opinion, if you have to scroll to see all cases of a switch statement, it's time to refactor.  So, I used this as an opportunity to apply the strategy pattern.

The switch statement looked like this when I started getting spaghetti-code nausea.  

switch (comparisonOperator)
{
   case Operator.IsEqualTo:
      return WhereFilter.Equal(property, whereCriteria.Value);
   case Operator.Contains:
      string likeExpression = string.Format("%{0}%", whereCriteria.Value);
      return WhereFilter.Like(property, likeExpression);
   case Operator.StartsWith:
      likeExpression = string.Format("{0}%", whereCriteria.Value);
      return WhereFilter.Like(property, likeExpression);
   case Operator.EndsWith:
      likeExpression = string.Format("%{0}", whereCriteria.Value);
      return WhereFilter.Like(property, likeExpression);
   case Operator.IsGreaterThan:
      switch (whereCriteria.ValueType)
         {
            case whereCriteria.ValueType.DateTime:
               return WhereFilter.GreaterThan(property, DateTime.Parse(whereCriteria.Value));
            default:
               throw new NotImplementedException();
         }
   case Operator.IsLessThan:
      switch (whereCriteria.ValueType)
      {
         case whereCriteria.ValueType.DateTime:
            return WhereFilter.LessThan(property, DateTime.Parse(whereCriteria.Value));
         default:
            throw new NotImplementedException();
      }
   //TODO: Implement all cases
   case Operator.IsGreaterThanOrEqualTo:
   case Operator.IsLessThanOrEqualTo:
   case Operator.IsNotEqualTo:
   case Operator.IsNotNull:
   case Operator.IsNull:
   default:
      throw new NotImplementedException();
}


As you can see, it's getting a bit out of hand and there are still quite a few cases (and even nested cases) that still need to be coded.  After I finished applying the pattern, the code in the corresponding class looked like this.

IOperatorStrategy operatorStrategy = OperatorStrategyFactory.GetStrategy(theOperator);
return operatorStrategy.GetWhere(property, criteria);


The OperatorStrategyFactory retrieves the appropriate strategy class based on the input parameter. 

internal static class OperatorStrategyFactory
{
   private static readonly IDictionary<OP, IOperatorStrategy> Strategies = new Dictionary<Operator, IOperatorStrategy>();

   static OperatorStrategyFactory()
   {
      Strategies.Add(Operator.IsEqualTo, new EqualToStrategy());
      Strategies.Add(Operator.Contains, new ContainsStrategy());             //These could be loaded via reflection as well, if beneficial
   }

   public static IOperatorStrategy GetStrategy(Operator @operator)
   {
      if (!Strategies.ContainsKey(@operator))
      {
         throw new NotImplementedException(string.Format("An operator strategy is not registered with the StrategyFactory for the operator '{0}'", @operator));
      }
      return Strategies[@operator];
   }
}


The returned strategy class knows the algorithm required to then supply the necessary result (i.e. where clause in this case). 

internal class EqualToStrategy : IOperatorStrategy
{
   public IWhere GetWhere(IQueryProperty property, Critera criteria)
   {
      //TODO: Implement Algorithm
      throw new NotImplementedException();
   }
}


This is a simple way to make your large switch statements more maintainable and keep the spaghetti-code sometimes associated with them to a minimum.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | Abstraction | Design Patterns | Software Maintainability

1

LINQ != LINQ to SQL

by Jeremy 16. September 2010 10:48

I've spoken with multiple developers who interpet "LINQ" as LINQ to SQL.  Yes, they are certainly related, but LINQ is not just LINQ to SQL.  LINQ to SQL is likely the most well known LINQ Provider, although its only a small part of the LINQ umbrella.  In fact, LINQ to SQL will likely fade into the sunset, as Microsoft will no longer be enhancing it, but rather focusing on the Entity Framework. 

LINQ provides an abstraction for querying data, regardless of where that data resides.  Consider the following line of code.

IQueryable<Comment> publicComments = comments.Where(x => x.IsPublic);


As a developer, I don't need to know where this data resides, or how it is retrieved.  It could be translated into SQL by LINQ to Entities, LINQ to NHibernate, or LINQ to LLBLGen.  It could be translated into CAML by LINQ to Sharepoint.  It could be translated into Twitter's API access code by LINQ to Twitter.  The bottom line is, as a developer consuming LINQ, I don't have to worry about it. If I am using a tested and proven LINQ provider, the internal details of that data access have already been hashed out by the provider developers. 

The number of LINQ providers continues to grow, and its well worth your time to learn the abstraction.  LINQ to SQL may fade away, but LINQ will not.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | Abstraction | C# | LINQ

1

TDD = CDD?

by Jeremy 21. August 2009 12:05
There's been a big industry focus on test driven development over the past few years.  Many advocates of TDD make it a point to say that TDD is not really about testing, it's about design.  Writing tests before application code forces you to think about the goal(s) of the application code.  For example, what should the input to a certain method be, and what output should it supply?  TDD forces you to think in terms of inputs/outputs and code interaction.  What input should be provided to the callee, what output should be provided to the caller - essentially, how will multiple objects (e.g. classes, methods, etc) interface.  

I've recently started practicing TDD a bit, and have found that instead of always writing unit tests with some type of testing framework (e.g. nUnit), I sometimes create a console application that calls certain methods and reveals the output.  Granted, these are perhaps more "integration" tests than unit tests, as I'm using them to view database contents.  None-the-less, it got me thinking about TDD, and the notion that "Test"-Driven development isn't really about tests.  In my opinion, a more appropriate name might be "Client"-Driven Development.  I'm not referring to the clients that pay your bills, but the client portions of your application (e.g. the UI which calls another application layer).  There are clients at every layer of your app - the UI calls one layer, that layer calls another layer.  Each caller is a client, and when writing tests first, we need to think in terms of the "client", what it should input, and what the result should be.

Isn't CDD essentially the goal of TDD?

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Abstraction | Software Maintainability | TDD

3

When is abstraction a bad thing?

by Jeremy 21. May 2009 08:50
Abstraction is a powerful concept in software development.  Abstracting away certain parts of an application can heavily reduce develop time and make for a maintainable solution.  One shining example of this is the multitude of Object-Relational Mappers on the market, which abstract away a large amount of details about database interaction.  However, as with most things in life, abstraction's highest value is realized when used in moderation.  

While picking up ASP.NET MVC, I've started to realize the significant abstraction that asp.net server controls provide.  ASP.NET MVC doesn't have the parallel (at this point) to the server controls of web forms.  There are html helpers, but those are a very minor abstraction in comparison.  

Whether using web forms or ASP.NET MVC, one could argue that there are always abstractions that don't pull their weight.  For example, it's not unheard of for developers to use label controls for every message they put on a page.  The label abstraction doesn't provide anything that an html span tag wouldn't.  As another example, html helpers in ASP.NET MVC don't always provide much bang for the buck.  In some cases, it's harder to learn the syntax of the html helper than to simply write the html itself.  Learning how to write the html always applies to web development, the helpers only apply to ASP.NET MVC.

Abstractions can make us lose sight of how something actually works.  I will certainly admit that asp.net server controls have prevented me from learning the inner workings of some html tags over the years.  At the same time, they have sped up my development in many cases.  Whether you use abstractions or not, you should first understand what each is doing under the covers.  This allows you to determine if it is adding value or just tacking on an extra maintenance burden.

Currently rated 4.4 by 5 people

  • Currently 4.4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Software Maintainability | Abstraction

Powered by BlogEngine.NET 1.4.5.0
Original Design by Laptop Geek, Adapted by onesoft