Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

The Static Gateway Pattern

Now I am by no means claiming to be any sort of patterns naming authority, but after you see the same occurent pattern in your applications you often will try to formulate some sort of vocabulary among the team to express the concept that you see occurring over and over again. This is the very nature of how patterns popped up in the first place. This is a pet name that I have come up with for the “recurring” theme you will see demonstrated here. If you are not familiar with the Gateway pattern check out the definition here.

I am going to demonstrate this pattern with an example that most people should have in place at the beginning of a project. Logging.

One of the things about Logging, is that it should be simple. Let’s assume that to get things rolling I really only care about logging informational messages. Assume I have a Calculator class that wants to do some logging, here are some possible code fragments that demonstrate the calculator class taking advantage of logging capabilities:

    public class Calculator
    {
        private ILog log;

        public Calculator(ILog log)
        {
            this.log = log;
        }

        public int Add(int number1,int number2)
        {
            log.InformationalMessage("About to add two numbers");
            return number1 + number2;
        }
    }

In this scenario the calculator is constructed with a log which will take care of logging behaviour on its behalf. I don’t like this as Logging falls under that set of “cross-cutting” concerns, and I don’t want to have to provide all of the objects in my application (domain layer or not) with this extra dependency. Here is another option:

public class Calculator { private ILog log; public Calculator() { } public ILog Log { set { this.log = value; } } public int Add(int number1,int number2) { log.InformationalMessage("About to add two numbers");
return number1 + number2; } }

Again, this is not optimal as it clutters up my object with unecessary noise. From a simplicity perspective, is it simpe for me to specify that “all objects should have a field of type ILog if they want to consume logging functionality? I think that the simplest api would be something like this:

public class Calculator { public int Add(int number1,int number2) { Log.InformationalMessage("About to add two numbers");
return number1 + number2; } }

Right now someone somewhere is screaming about the fact that I just introduced, what looks like, a Singleton. From an API perspective, the line above imposes the least design restrictions on my classes that want to consume logging functionality. The only caveat is that any class that wants to leverage logging is now coupled to the Log class. IMHO this is only an issue if it decreases the ability for me to test or if it decreases the option for me to swap out logging implementations (ex. Log4Net, MS Logging etc).

By the looks of the code above, it would seem that I have pinned myself into a fairly rigid design. I am not going to focus on how I test drive this out, but taking the API above, how could I go about testing the Log class?

With the Static Gateway pattern, the Gateway (in this case the Log class) does not actually do any of the work. It just serves as the entry point to the functionality. If that is the case here is a cut at what the Log class could look like:

public class Log { private static ILogFactory logFactory; public static void InitializeLogFactory(ILogFactory logFactory) { Log.logFactory = logFactory; } public void InformationalMessage(string informationalMessage) { logFactory.Create().InformationalMessage(informationalMessage); } } public interface ILogFactory { ILog Create(); } public interface ILog { void InformationalMessage(string message); }

How could you go about testing this class (I am demonstrating test-after, though the end solution was driven out test first). Here are two tests that prove out the functionality of the log class:

 

[Test] public void Factory_should_be_leveraged_to_create_logger() { MockRepository mockery = new MockRepository(); ILogFactory mockLogFactory = mockery.DynamicMock<ILogFactory>(); ILog mockLog = mockery.DynamicMock<ILog>(); using (mockery.Record()) { Expect.Call(mockLogFactory.Create()).Return(mockLog); } Log.InitializeLogFactory(mockLogFactory); using (mockery.Playback()) { Log.InformationalMessage("blah"); } Log.InitializeLogFactory(null); } [Test] public void Informational_message_call_should_be_delegated_to_created_logger() { MockRepository mockery = new MockRepository(); ILogFactory mockLogFactory = mockery.DynamicMock<ILogFactory>(); ILog mockLog = mockery.DynamicMock<ILog>(); using (mockery.Record()) { SetupResult.For(mockLogFactory.Create()).Return(mockLog); mockLog.InformationalMessage("blah"); } Log.InitializeLogFactory(mockLogFactory); using (mockery.Playback()) { Log.InformationalMessage("blah"); } Log.InitializeLogFactory(null); }

As you can see, these are completely interaction based tests (hence the lack of assertions). I broke up the test for leveraging the factory to create the logger and the delegation to the actual logger into 2 separate tests. I am also using the SetupResult vs Expect in the second test to indicate that, it is not the behaviour I care about testing. It just needs to be there to focus on what I actually care about, the delegation of the Log class to the created ILog implementation (which is currently a mock itself).

The nice thing about this scenario is that neither the Log class, or the clients of the Log class are aware/tied to any one particular ILog implementation. As long as I can prove out the correct interaction between the Log class and it’s dependency, I should be able to swap in any implementation of ILogFactory and the Log class is none the wiser.

The only downside to the current implementation of the Log class is the need for the static field and static method to initialize that field. Outside of introducing other concepts too early, the initialization of the Log class with an ILogFactory implementation is something that can be done at application startup. It is very likely that is should be one of the first things that should happen, as many other objects in the system may rely on the functionality of the Log class.

The only problem with the current solution is that the Log class is coupled to any changes that may occur in the ILog interface. To ensure that the ILog interface can vary independently of the Log class, I am going to make a small change to the API. Instead of calling methods on Log directly. I am going to change Log, and ILogFactory to the following:

public class Log { private static ILogFactory logFactory; public static void InitializeLogFactory(ILogFactory logFactory) { Log.logFactory = logFactory; } public static ILog For(Type type) { return logFactory.CreateFor(type); } public static ILog For(object itemThatRequiresLoggingServices) { return For(itemThatRequiresLoggingServices.GetType()); } }

The nice thing about this change is that now the Log class does not need to have a mirroring method for every method that may exist on the ILog interface. The ILog interface is now free to change independently of the Log class. Which means I could easily add methods to log with a specific logging level, etc. The Log class is now strictly a “Static Gateway” to Logging functionality.

I’ll finish up by making a call into this API from the Calculator class: 

public class Calculator { public int Add(int number1,int number2) { Log.For(this).InformationalMessage("About to add 2 numbers"); return number1 + number2; } }

At this point the Calculator class is completely oblivious to the fact that there is currently no concrete ILogFactory/ILog implementation. It just cares about leveraging the Logging gateways “Static” method to have it log on its behalf. When we actually swap in a real ILogFactory & ILog, neither the Calculator or Log class will have to change at all.

In completion here is a quick implementation of an ILogFactory/ILog pair that will output log messages to the console (I’ll leave it up to you to come up with a more testable implementation of the following 2 classes):

public class ConsoleLogFactory : ILogFactory { public ILog CreateFor(Type type) { return new ConsoleLogger(); } private class ConsoleLogger : ILog { public void InformationalMessage(string message) { System.Console.Out.WriteLine(message); } } }

If you were to run the application now (after initializing the Log class with this ILogFactory implementation), you would see messages output to the Console, whenever the Add method on Calcuator was invoked.

In my next post, I’ll demonstrate how to leverage the Static Gateway pattern with respect to an IOC gateway, that will allow me to remove the static field and initilization method on the Log class.

This entry was posted in Featured, Patterns, Programming. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

7 Responses to The Static Gateway Pattern

  1. Dave Laribee says:

    i got you. still the subtlety factor of patterns bothers me somewhat. gateway vs. adapter? i think this is a point brought up on poeaa, but then again there’s the gateway chapter. i don’t have an opinion though i do think subtlety is a good thing as long as it’s understood (high oo skill in a team).

    here’s a question: how is this not just a factory method?

    public static ILog For(Type type);

    Factory Method Chain? maybe another pattern in there? i see you have one under ultimately resolving the log but it seems static gateway is really just two factories for the purpose of syntactic sugar (w/ testability).

    at any rate i see where Log is both a gateway and static. this is a very composite pattern with similar patterns delegating to similar patterns (looks like a service locator delegating to a service locator, or a factory method delegating to an abstract factory in places.) of course saying ‘static gateway’ tightens the langauge.

    ok. i buy it! :)

  2. SteveG says:

    Good article!

    I’d like to see this look something like this;

    [Logger] //inject the logger instead of a singleton- you need logging, you add the attribute
    public class Calculator

    Log.InformationalMessage(…)

    Different subject, but it made me wonder if Castle Windsor can do this type of injection ?
    It’s cleaner than your first example, but still uses injection without the use of a singleton.

    Thoughts on this?

  3. @Dave,

    You are one step ahead. The example that you just gave is a “Static Gateway” to container functionality. IOC becomes the Static Gateway, the actual IContainer implementation is the actual service locator, the IOC is just the entry point to access this functionality.

    Once you introduce a static gateway for the container (which I was going to do in my next post), the static initialization method on the Log class disappears, and each of its For methods gets changed to the following:

    public ILog For(Type type)
    {
    return IoC.Resolve().Create();
    }

    The point being, that once people have started leveraging the Log (static gateway), they are oblivious to the introduction of the IoC gateway and can carry on logging as normal.

    It is a subtle enough difference to make me not think that this is a Service Locator (Log, not the IoC).

  4. Dave Laribee says:

    How is this not a Service Locator?

    http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html

    We’ve surfaced this pattern with something like this:

    IoC.Resolve();
    IoC.IntializeWithContainer(mockContainer);

    This lets us use the IoC static members inside things like controllers, etc. But we’re also using it for services in pretty much the same way you describe. What’s interesting is to look at Ruby and things like mixins. They really change the dependency inversion principle, or recast it in a different technique.

  5. Joe Ocampo says:

    Thanks for the clarification.

    I find it astonishing on the number of composite patterns that can be formulated to solve business issues. The funny thing is that I find that developers in general don’t understand the basic GOF patterns to even recognize a composite pattern.

    Is this a bad thing? hmmm…Have to think about that.

  6. @Joe,

    Good eye!! I guess I should have taken the time to point out the players outside of the Gateway itself!! Like a lot of composite patterns, this just becomes a simpler term to use among team members.

    With regards to it being a singleton, the actual logging factory strategy may not be a singleton. In the current implementation of the Log class, the factory is definitely a singleton by nature of the static field. With the introduction of delegating to a container (coming up soon), this limitation goes away, while maintaining the testability aspect. In it’s current implementation, it circumvents typical issues associated with Singletons, as it does nothing other than delegate to something that can be mocked/swapped etc.

  7. Joe Ocampo says:

    This is awesome JP but isn’t this just combining a Bridge, Singleton and Strategy pattern into one? Just asking for clarification purposes on my end.

Leave a Reply