Tuesday, August 9, 2011

I'm not afraid of clocks.

I started at AMD during the second sprint of our project. I realized that DateTime.Now was sprinkled about the code in a few places and I argued that it was an external dependency that should be isolated in such a manner that it could, at the very least, be swapped with DateTime.UtcNow painlessly in one place. I got my way and plans were formulated for what to do regarding our newfound pain point.

The first approach was what I'm used to (IoC and interfaces). I added this to services.xml:

<object id="dateService" type="MyApp.Services.DateService, MyApp.Services" autowire="autodetect" singleton="true" >

</object>

 
I added an interface at MyApp.Core.Services.IDateService:

using System;

namespace MyApp.Core.Services

{

   public interface IDateService

   {

      DateTime Now();

   }

}

 
I created MyApp.Services.DateService next.

using System;

using MyApp.Core.Services;

namespace MyApp.Services

{

   public class DateService: IDateService

   {

      public DateTime Now()

      {

         return DateTime.UtcNow;

      }

   }

}

 
One could then wire up DateService for use like so:

<object id="checkUtility" type="MyApp.Core.Utils.Check, MyApp.Core.Utils" autowire="autodetect" singleton="true" >

<property name="DateService" ref="dateService" />

</object>

 
One would use it in a class like this:

public IDateService DateService { get; set; }

...some code...

var foo = DateService.Now();

 
This approach for managing timekeeping is comparable to our approach for managing interactions with Active Directory in that there is real isolation from the core and the interaction with either timekeeping or accounts is done through an interface.

After some talk, things went another way. There was a consensus that the clock was not a "scary" external dependency. It was just something that needed to be changeable at one spot. It could just sit in the core in a static class that held one static method. That would make it as painless to use as DateTime.Now. There wouldn't be a bunch of legwork to do in the name of working around DateTime.Now.

using System;

namespace MyApp.Core.Utils

{

   public static class DateService

   {

      public static DateTime Now()

      {

         return DateTime.UtcNow;

      }

   }

}

 
One could use this code effortlessly like this:

var foo = DateService.Now();

Note: In my prior approach I couldn't even make a static class and a static method. There is no way in C# 4.0 to pull static stuff through interfaces. Also, I'm new to the Spring.NET IoC stuff and I was having trouble replacing some of the existing references to DateTime.Now with the interface approach. Why did this process have to be so hard? It didn't. There was no reason to be afraid of the clock.




No comments:

Post a Comment