June 3, 2011

What My Local Sandwich Shop Taught Me About Design Patterns

Where I live, there are a few regional sandwich shop chains that I like to frequent. These shops make and serve all kinds of sandwiches, both hot and cold, along with various appetizers and side dishes. I was perusing the menu of one of my local favorites when I had an epiphany about software design patterns!

You see, these shops actually have names for their sandwiches. When you walk in, you'll hear customers asking for an "Imperial", a "Special", or an "Italian, without the hots." Each of these names relates to a sandwich that is composed of specific meats, cheeses, and other toppings, and is served on a particular type of bread. For instance, a "South Philly" consists of:

  • Prosciutto
  • Genoa Salami
  • Capocollo [sic]
  • Roasted Red Peppers
  • Sharp Provolone
  • Lettuce
  • Tomato
  • Seasonings
...and a choice of additional toppings:
  • Oil
  • Mayonnaise
  • Onions
  • Hot Peppers
...and is served on a seeded roll.

Now, I want you to imagine that every time you walked into my local sandwich shop, you had to order a sandwich like the South Philly by its ingredients. Every. Time. How likely is it that you'd keep ordering that sandwich? How likely is it that the staff would consistently get your order right?

You see, naming a sandwich like the South Philly is not just clever marketing, it's a vital communication tool for both customers and restaurant staff alike. When a customer orders a South Philly, s/he doesn't have to worry about the details of what's on the sandwich. Similarly, when the order is passed on to the staff, they know precisely what to make. By naming their sandwiches, my local sandwich shop has reduced the complexity of ordering for the customer, and has also reduced the complexity of communicating among the shop staff about each order. As a result, customers more often get the sandwiches exactly the way they ordered them, and there is more consistent communication among staff about each order. The shop earns a good reputation for its service, and customers keep coming back to order more Imperials, Italians, and South Phillys.

So, what does all this have to do with software design patterns?

You see, when I was first introduced to design patterns, my implicit assumption was that they represented a sort of solution template for certain types of software design problems. Of course, this assumption is correct, however it's only part of the equation.

Like the sandwiches at my local sandwich shop, design patterns have names as well: "Facade", "Adapter", "Bridge", "Observer", "Decorator", and so on. Also like my local sandwich shop, these names represent a set of "ingredients" for each pattern: Problem Statement, Constraints, Solution, Collaborators, etc. Imagine if we had to specify every component in a pattern while communicating with other members of our teams about our software designs -- what do you think the results would be? Would we have fewer or more design defects? Would we have fewer or more implementation defects? Would the quality of the final software product be better or worse?

Design patterns are not just a way of solving certain software design problems; they are also a way of communicating about the solutions to those design problems in which there is reduced complexity and greater consistency in communication. When I say to my team, "I'd like to wrap our BLL API in a Facade," we all understand what that means, which allows us to produce exactly the software that our clients expect with a minimum of defects or other problems. Our shop earns a good reputation for its service and quality products, and customers keep coming back to order more applications.

May 31, 2011

Design Patterns Simplified: The Adapter Pattern

Introduction
Even though you may never have heard of the Adapter pattern or may never have seen it formally defined, chances are that you've used it in your coding practice countless times. Adapters are often referred to as "wrappers" and are used when the interface of an existing class must be adapted to match the interface of a target class. Not sure where to get started with the Adapter pattern? Well, then let's start with an example, shall we?

Author's Note: If you've already studied design patterns a little bit, you know that there are actually two adapter patterns: the Object Adapter Pattern and the Class Adapter Pattern. However, the Class Adapter Pattern is really only useful in languages that truly support multiple inheritance. Since that's a short list of languages, we're going to focus on the Object Adapter Pattern in this tutorial. However, feel free to browse some of the titles in the Further Reading section if you want to learn more about the Class Adapter Pattern. For the remainder of this tutorial, assume that "adapter pattern" refers to the Object Adapter Pattern only.

It All Starts with Headphones
I love my Beats Solo headphones. They're great for when I'm listening to my favorite music on my iPhone or listening to iTunes at work.
Monster Beats Solo High Definition On-Ear Headphones with ControlTalk (White)However, my cans don't work well with my m-audio recording interface because it expects a 1/4" connector and my Beats Solo headphones are only equipped with a 3.5mm connector. What's an audiophile to do? There are several options:

  1. I could buy another pair of headphones that have the expected 1/4" connector, however it would be difficult to justify the cost of a new pair of studio quality headphones for such a specific use case.
  2. I could modify my Beats Solo headphones by removing the 3.5mm connector and replacing it with a 1/4" connector, however doing so would make my Beats Solo headphones unusable on my devices that expect a 3.5mm connector, and is prone to error (the sound quality may suffer, or worse, my headphones may not even work after the mod!).
  3. Luckily, a third option exists: I can simply purchase an adapter at my local electronics store that will take my headphones' 3.5mm output as its input, while providing the expected 1/4" connector to my m-audio interface. When I no longer need a 1/4" connector I can simply remove the adapter and I can once again use my headphones with all of the devices I own that expect a 3.5mm connector.
Obviously, the third option is by far the most reasonable one.

The Adapter Pattern in Software Design
The motivation for using the Adapter Design Pattern is virtually the same as the motivation for using an adapter on my headphones. If we have a class that expects a certain interface and another class that provides the functionality we want but doesn't match the necessary interface, then we want to use an adapter class that will provide the expected interface while leveraging the functionality that we already have.

Here's a UML class diagram showing what the adapter pattern looks like:


In the example above, Target is an abstract class that provides the interface that Client expects to use. ConcreteTargetA and ConcreteTargetB are concrete implementations of Target. TargetBAdaptee is a pre-existing concrete class that provides some or all of the functionality promised by ConcreteTargetB, but doesn't provide the interface that Client expects. Rather than recreate the functionality contained in TargetBAdaptee within ConcreteTargetB, we can create an instance of TargetBAdaptee in ConcreteTargetB, and then leverage the states and behaviors of the former within the implementation of the latter, which provides the necessary interface to Client.

Got it? No? Okay, let's recreate the UML diagram above but use the objects contained in our real-world example:


In the diagram above, my m-audio studio recording interface (Client) expects a certain connector type from any headphones (Target) connected to it. SonyMDR (ConcreteTargetA) provides both the functionality and type of connector (interface) that my m-audio interface expects. My Beats Solo headphones (TargetBAdaptee) provide the necessary functionality, but not the connector type, that my m-audio interface expects. However, my 1/4" TRS Adapter (ConcreteTargetB) can provide the connector type that my m-audio interface expects while also using the functionality provided by my Beats Solo headphones.

Got it now? Good.

Adapter Pattern Rationale
The first question that is likely on your mind right now is: "Why use the adapter pattern at all?"

After all, you could simply alter the interface of your target class to make it compatible with the interface that your would-be adaptee provides, and then alter portions of code outside the target class hierarchy to use the new interface. This may seem somewhat attractive at first, but is really intractable in large systems, and violates the Open-Closed Principle.

In many cases, especially when using open-source libraries, it's tempting to simply alter the implementation of a class so that its interface meets your needs, rather than create another class to wrap its implementation within the required interface. However, altering the implementation or interface of a class that already exists is in violation of the Open-Closed Principle, and makes for very tightly-coupled software design. Following this approach rather than using the adapter pattern would be like cutting the existing connector off your headphones and attaching a different connector.

Alternatively, some novice programmers take to copying and pasting code from an existing class into their concrete implementations, however this is actually more work than adapting an existing class, can result in unresolved dependencies, and will undoubtedly require very careful testing. Taking this measure would (roughly) be the equivalent of buying a new pair of headphones rather than using the ones you already have.

The adapter pattern is an ideal choice because it allows you to add existing functionality to your system without altering the targeted interface, client code, or the implementation of the existing functionality. Therefore, while it may seem like more effort at first to create an adapter class, it actually requires less effort than any other proposed option when you consider all facets of the development process.

Adapter Pattern Use Cases
Like any other design pattern, the adapter pattern is not applicable in all cases. Here is the typical use case:

  • You have a requirement to provide (or maintain) a particular interface to client objects (e.g.: Headphones).
  • There is a class that already exists that provides the required implementation, but does not provide the required interface (e.g.: Beats Solo).
If your design requirements do not include the above, then the adapter pattern is likely not the right choice for your solution.

Conclusion
I hope you've enjoyed this introduction and overview of the Adapter Design Pattern, which is part of the Design Patterns Simplified series. If you like what you've read so far, feel free to subscribe to my feed in the sidebar on the right. If you have questions, suggestions, or errata, please feel free to comment below or send me an email at brian [at] brian [hyphen] driscoll [dot] com.

Further Reading

May 20, 2011

Just The Code: Two Telerik RadGrid Extension Methods


Last night I found myself needing to add the same functionality to several RadGrids in my application. Rather than copy & paste, I decided to be kind to my future self and thus created two extension methods:
  1. SetDefaultSort -- This method sets a default sort on a RadGrid - for instance, to sort by a datetime column when the page loads.
  2. ClearFilters -- For a RadGrid that has filters implemented, this method allows you to consistently clear filters - for instance, when a user clicks a "Refresh" or "Clear Filters" button.

    Here is the code:



Want to learn more about extension methods? Check out Professional C# 2008 (Wrox Professional Guides), it's how I learned all about them.

Happy Coding!


(P.S.: Want to give me some feedback? You can always leave comments here, email me directly (brian at brian-driscoll.com), or catch me on Twitter (I'm @driscollwebdev)

May 12, 2011

Design Patterns Simplified: The Facade Pattern

Introduction

The Facade design pattern is one that is used throughout the software world as a way to make interacting with complex system APIs simpler. A facade class is one that encapsulates part or all of the public APIs of several system classes as its public API; the result is that one only has to deal with a single API, that of the facade, rather than the APIs of many classes. Sound complex? Hopefully not. But just in case you're still a little bit fuzzy, we'll start with a real-world example.

A Real-World Facade Pattern Example

Whether you realize it or not, you probably encounter examples of the facade pattern in your everyday interactions quite often. Take, for example, a visit to your favorite table service restaurant. Once you are seated, your waiter takes your beverage order and brings it to the bar. The bartender reads your order and makes your drinks. When the bartender has made your drinks, she alerts the waiter who retrieves them from the bar and brings them to you. In similar fashion, the waiter takes your dinner order and brings it to the kitchen. The kitchen staff reads your order and makes your meal. When the kitchen staff has made your meal, it alerts the waiter who retrieves it from the kitchen and brings it to you. In the event that a particular dish that you ordered is no longer available, the kitchen staff informs the waiter who in turn informs you and requests a different order from you.

You see, you interact with your waiter by placing your order, and he interacts with the rest of the restaurant staff on your behalf. If this were not the case, you'd be responsible for ordering your drinks directly from the bartender, listening for the bartender to tell you that your drinks are ready, then retrieving your drink order from the bar; the case for your dinner order and the kitchen staff would be quite similar. In this way, the waiter is the facade between you and the inner workings of the restaurant.

The Facade Pattern in Everyday Technology

You may also not realize that you see the facade pattern in your everyday interactions with technology. If you're a working stiff like I am, chances are you interact with an Enterprise Resource Planning application that manages requests for time off, benefits administration, performance reviews, departmental metrics, etc. If you're a student, you likely interact with a similar application that manages your course registration, grades, transcript requests, graduation application, financial aid, etc. In either the professional or academic case, the application you interact with is a facade that coordinates the transactions among the different underlying systems for each domain. This facade implementation allows you to interact with the different systems responsible for managing time off, benefits, course registration, or financial aid through a single interface rather than through separate interfaces for each system.

The Facade Pattern in Software Design

The facade pattern is used extensively in software design. Public APIs for web applications and services such as Twitter provide a facade for developers to interact with the internals of the system. However, before attempting to use the Facade Pattern in the design of your application you should make sure that it is appropriate to do so. There is nothing worse for a developer than having to maintain an application that has been shoe-horned into a particular design pattern. Here are some check points to make sure that the Facade Pattern is right for your case:

  • Do you have a set of related classes?
  • Do you frequently perform the same operations with these classes in your code?
  • Would adding a facade class reduce the complexity of working with these classes?
While the list above is not exhaustive, it should point you in the right direction. Here is an example UML class diagram for an implementation of the Facade Pattern:



As you can see, the MyFacade class is composed of instances of MyClassFoo and MyClassBar, and we can assume that the method doSomethingWithFooAndBar is one that will incorporate the use of both of the composed classes. Here is a look at some sample code for this facade implementation, written in C#:



So now you've seen what the Facade Pattern looks like in everyday life, technology, and software design. But, if you're not quite ready to run out and use it, or if you just want to get some more background on the Facade Pattern or design patterns in general, feel free to take a gander at the reading list below.

Further Reading

See below for further reading to help you understand the Facade Pattern and its use in application code.

Design Patterns: Elements of Reusable Object-Oriented Software
Design Patterns Explained: A New Perspective on Object-Oriented Design (2nd Edition)
Facade pattern (Wikipedia)
C# Design Patterns - The Facade Pattern (GeekDaily)
Facade Clears Complexity (JavaWorld)
Introducing the Facade Pattern in PHP 5 (DevShed)

Talk to me, Goose

I love getting feedback. No, really, I do. Feel free to leave comments or questions below or email me at brian at brian-driscoll dot com.

March 31, 2011

Just The Code: ScriptTimer class

Today I found myself faced with a page that took 22 seconds to load (!) and no explanation why. So, I created the ScriptTimer class below to help me figure out where the time sink in my code was. I was able to find it, thanks to this class, and fix the problem ASAP (the page now loads in <2 seconds).