This post is the 6th in a series that started with the 10 practices that every developer needs to start right now
- Them: “… and so that is the pattern.”
- Me: “That’s it”
- Them: “Well, yeah.”
- Me: “But that’s how I’ve always done that.”
- Them: “Well, then you’ve always been following that pattern”
I find that is how a lot of people react when they first learn about patterns. “So a pattern is just giving a name to good software development” Well, yes and no. On the one hand – yes, a software pattern is recognizing common software challenges and the approaches that have worked in the past to over come those challenges – and naming it. On the other hand, don’t underestimate the power of giving something a name.
There is power in a common vocabulary. Think about it, every profession has one. From the dentist that cleans your teeth to the short order cook at Denny’s; from the mechanic that works on your car to the contractor that built your house. Every profession has it’s own vocabulary that gives people a fast and efficient way to communicate.
So that instead of taking time to walk through all of the details of your architecture and application design, you can have a conversation that goes something like this “We’re writing a facade layer here, and utilizing a DI container to act as our Abstract Factory, accessing our persistence layer with a repository pattern utilizing Interception for logging and MVVM to composite all of our UI.”
OK, so I know that there were a lot of buzz words thrown in there, but I hope you’re getting the point – a lot can be communicated in a couple of sentences.
Let’s face it – there is more to learn than any of us has time for. Patterns are like that. There’s a pattern for everything – like a bad Apple commercial, there’s a pattern for that. The important part is not learning every pattern under the sun – but learning the common patterns for the common challenges is where you’ll get the most bang for your buck.
Strategy | Factory | Abstract Factory – all related.
Factory. The goal of a factory pattern is to conceal the creation of an object from the consumers of the object. This is especially important for complex objects that take a lot of dependencies or configurations when you create them. Instead of repeating the set up code through out your application you move it to one place (the factory) and then call that from your code.
take this (slightly contrived) code example…
SqlCommand cmd = new SqlCommand();</p>
<p> SqlParameter parm1 = new SqlParameter();<br />
parm1.Direction = ParameterDirection.Input;<br />
parm1.ParameterName = &amp;amp;amp;amp;quot;Id&amp;amp;amp;amp;quot;;<br />
parm1.Value = 5;<br />
<p> SqlParameter parm2 = new SqlParameter();<br />
parm2.Direction = ParameterDirection.Input;<br />
parm2.ParameterName = &amp;amp;amp;amp;quot;State&amp;amp;amp;amp;quot;;<br />
parm2.Value = &amp;amp;amp;amp;quot;TX&amp;amp;amp;amp;quot;;<br />
<p> // etc...<br />
It would be much nicer to implement a reusable method as so…
SqlCommand cmd = new SqlCommand();<br />
cmd.Parameters.Add(getInParm(&amp;amp;amp;amp;quot;Id&amp;amp;amp;amp;quot;, 5));<br />
<p> // etc...<br />
<p> SqlParameter getInParm(string name, object value)<br />
SqlParameter parm = new SqlParameter();<br />
parm.Direction = ParameterDirection.Input;<br />
parm.ParameterName = name;<br />
parm.Value = value;<br />
return parm;<br />
This probably seems like an obvious and simple example (because it is), but the point is that not all patterns are ground breaking or earth shattering, just simple approaches to make your code more usable, maintainable and testable.
Abstract Factory. If you set up your factory to return an Interface instead of a concrete class then it is an abstract factory. This is especially useful when you want to return different implementations in different scenarios. For example, you might have an IDataLayer and in some cases you want to return a fake version for testing, or perhaps you need a local storage version for offline scenarios etc.. moving the creation of your data layer, it’s configuration and set up to a factory would make a lot of sense. By the way, this is also a text book definition of Object Oriented Polymorphism – the same interface with different behaviors with various implementations. And that brings us to the Strategy Pattern.
Take our example above, if we were to move that bit of code in to a shared data access helper class, we might want to consider a more generic approach.
IDbDataParameter getInParm(string name, object value)<br />
Strategy Pattern. The original goal of the strategy pattern was the grouping various algorithms in to common interfaces. So, for example, working with DES, Triple DES or Blowfish encryption shouldn’t be any different than driving a V8 is different from driving a 4 cylinder car – what’s under the hood (the implementation) doesn’t matter as long as you know hot to use the steering wheel and pedals (Interface). No code examples here. Go take a look at encryption in .NET, or the common approaches that ADO uses for data access. Also, hang on, we’ll go in deeper to code examples in just a bit when we talk about composition over inheritance (which is closely related to Strategy Pattern)
Up next: UI Patterns for Testability, Maintainability and Extensibility!
(Followed by Composition over Inheritance)