Template Method Pattern without Inheritance
I go back and forth with Template Method. I find it convenient, but sometimes I think it can be too confusing if it is overused. I feel like the best code requires the least knowledge in order to use it. Template Method has always felt like white box re-use. Another problem I have is that it requires me to inherit in order to plug in my functionality. Well, I think I have an alternative.
I independently discovered (along with thousands of others I’m sure) a way to do Template Method without inheritance. To be honest, I don’t really know if this pattern has another name. I suspect it does. And I certainly won’t make any claims as whether or not it is good OO. I do know that I find it very convenient to be able to override behavior without having to inherit from a base class.
Here’s the relevant part of a class that I am using to call WCF services (look at the ConfigureBinding property):
public class WcfProxy<TService, TBinding> : IDisposable
where TService : class
where TBinding : Binding, new()
{
public Action<TBinding> ConfigureBinding { get; set; }
public WcfProxy()
{
ConfigureBinding = (binding) => { };
}
private ChannelFactory<TService> CreateChannelFactory(string serviceUri)
{
// doing some stuff here
// create and configure binding
var binding = new TBinding();
ConfigureBinding(binding);
// creating and returning ChannelFactory here
}
// ... more stuff is down here
}
In this example, I want to use WSHttpBinding internally but I need a way to allow the caller to configure the binding. For instance, maybe the caller needs to set send and receive timeout’s or message size limits.
In order to accomplish this, I have defined a public Action
In this way, the caller can provide new behavior:
var proxy = new WcfProxy<IMyService, WSHttpBinding>(uri);
proxy.ConfigureBinding = (binding) =>
{
binding.Security.Mode = SecurityMode.Transport;
binding.ReceiveTimeout = TimeSpan.FromMinutes(10);
binding.SendTimeout = TimeSpan.FromMinutes(10);
};
// make call on the proxy here
This sounds like JavaScript-style prototype-based inheritance. I like it.
Template Method is a pattern for inheritance.
“Template Method lets *subclasses* redefine certain steps of an algorithm without changing the algorithm’s structure.”
What we see here is nothing more than Dependency Injection.
As a developer, I’d much rather see:
public class WcfProxy : IDisposable
where TService : class
{
private readonly IBindingConfiguration bindingConfiguration;
public WcfProxy(IBindingConfiguration bindingConfiguration)
{
this.bindingConfiguration = bindingConfiguration;
}
private ChannelFactory CreateChannelFactory(string serviceUri)
{
// doing some stuff here
// create and configure binding
var binding = bindingConfiguration.CreateBinding();
// creating and returning ChannelFactory here
return null;
}
// … more stuff is down here
#region Implementation of IDisposable
public void Dispose()
{}
#endregion
}
public interface IBindingConfiguration
{
Binding CreateBinding();
}
class ExampleBindingConfiguration : IBindingConfiguration
{
private readonly Action configuration;
public ExampleBindingConfiguration(Action configuration)
{
this.configuration = configuration;
}
public ExampleBindingConfiguration() : this(b=>{})
{}
#region Implementation of IBindingConfiguration
public Binding CreateBinding()
{
var binding = new NetTcpBinding();
configuration(binding);
return binding;
}
#endregion
}
Oops, thinking back, I think the word I wanted to use is “JavaScript-style prototype-based polymorphism” which actually makes sense.
I just did something similar for our project for building test data.
Whether Chris’ traditional C# implementation is easier to follow for other developers is an entirely different question. I prefer the delegate/prototype-ish solution, but I’m not sure if I should deduct points for it not following the traditional Java/C# DI rule of “inject everything through an interface”.
On our current project, the pendulum has swung way too far away from using interfaces/DI properly, and so I’m constantly trying to introduce interfaces. But I’ve also introduced several prototype-ish interface-avoiding APIs that look a lot like SystemTime.Now (see link below). We don’t have an IClockProvider interface and we’re much happier for it.
(see http://ayende.com/blog/3408/dealing-with-time-in-tests )
I’ve also seen some (now this is rare, but I’ve seen it) premature-interfaces in our codebase. Where someone implemented 5 interface implementations, and I come around later and determine there is only 1 hardcoded property difference between all 5. The code of course was difficult for me to understand.
I’ve been following @bigballofmud on twitter, and he’s as harsh against Ravioli code as he is against Spaghetti code.
http://c2.com/cgi/wiki?SpaghettiCode
http://c2.com/cgi/wiki?RavioliCode
The more interesting question to me ISN’T which API you or I prefer, BUT IS which API should we all prefer, and why? Is it within reason to add an interface + injected dependency where an inline delegate would do, just because more people understand the interface-based solution? How much code indirection is too much?
Anyway, enjoy your evenings, etc. -Peter
I just reread my last comment. It’s terribly disjointed, and I blame twitter and bullet point-flavored work email for ruining my writing style. Maybe it’s time to blog again.
Maybe instead of leaving that long, rambling comment, I should have just pointed to the Caliburn.Micro source, which is probably where I’m getting my newfangled ideas from anyway. E.g. http://caliburnmicro.codeplex.com/SourceControl/changeset/view/5764a107cea0#src%2fCaliburn.Micro.Silverlight%2fViewModelBinder.cs
This has also been rattling around in my mind:
http://openmymind.net/2011/5/3/Dealing-with-Now-and-why-i-am-almost-done-C%23-and-J
with the better follow-up comment by Karl:
http://openmymind.net/2011/5/3/Dealing-with-Now-and-why-i-am-almost-done-C%23-and-J#comment-196285793
So maybe I’m just repeating Karl and saying: do we have to do intefaces because it’s the C# way and everyone’s comfortable with it, or can we start to make use of delegates now that they’re easy to use (since .NET 3.5)?
Also, and I’ve never used AutoFac, but apparently it’s the IoC container that makes it much easier to inject delegates in a way that may make everyone happier.