Wednesday, July 21, 2010

IProvider to sidestep dependency problems.

This is another not-new concept, but it's one that I haven't found explained simply and might benefit some people.

When you have a three tier structure like I've suggested, and you've got a process that requires looking though a large amount of data for a matching item, it may seem like you've got yourself in a pickle. Since the Data  assembly is dependent on the Core assembly, Core can not use Data directly. The first instinct may be to just relate all the Core objects and set up mappings to permit this data to be lazily loaded during the process by NHibernate. This does work, actually, but it has a few smells to it. First, Core is now being modified by our data concerns. Sometimes these relationships are appropriate from a purely business need, but many times they are not. Second, Data is now being modified by our Core concerns. The mapping tweaks such a solution would probably require to be palatable are not likely to be useful in other areas of the system.

So how else would you do this? Using a provider.

The first step is to define, using an Interface in Core, the query you want to run. Lets say you want to grab all orders above a specific quantity shipped to a specific state. Maybe you want to step though them to find out their frequency and see if you should advise a later ship date to save on freight by combining shipments. Something like that.

public interface IQueryOrders 
{
     IEnumerable FindOrders(string ToState, int AboveQty);
}

 Next, you want a place for this to live in your Core assembly.

public static class Providers
{
      public static IQueryOrders OrdersProvider { get; set; }
}

Now, you need to create this provider in the Data assembly.

public class OrderProvider : Core.IQueryOrders
{
     public IEnumerable FindOrders(string ToState, int AboveQty)
     {
          // Your Query logic goes here. 
     }
}

So now we've got the Core assembly setting up a contract, and the Data assembly setting up a facility to handle that contract. All that's left is to connect one to the other. I do this in the UI assembly.

Core.Providers.OrdersProvider = new Data.OrderProvider();

And finally, you can write your code in Core to consume the output of this provider and act upon it. Not ground breaking, but simple, and useful.

0 comments:

Post a Comment