Design Patterns are a mechanism whereby design knowledge can be encapsulated, considered and applied in a commonly understood way. Patterns form the basis of a design grammar that allows architects to discuss the composition of the design in a clear and unambiguous fashion using common and well understood terminology. They also gather knowledge of design constructs in a format that allows them to be readily shared and applied in multiple contexts.

Design patterns tend to have significantly better reusability than software components. This is because design patterns are abstract knowledge that may be applied, whereas software components have concrete implementation. Having a concrete implementation subjects them to specific business requirements that may not be generally applicable. Designing for generic application is difficult and error prone as well as having potential negative consequences on the usability, performance and maintainability of the component. As such, reuse of a software component is hard. Reuse of an idea in the form of a design is simpler because the only the business requirements relevant to the problem need be considered.

Numerous software development techniques and methodologies have has their partisans claim that they are the silver bullet that will solve reuse problems. This has been claimed for object orientation, components and more recently approaches such as Service Oriented Architecture. Experience has shown that where these technologies have succeeded it is because they offer advantages over alternate methods, but that they do little to address the problems of reuse. It is my opinion that design patterns are the single most successful approach to reuse as they may be applied widely across multiple domains and platforms in a way that realised software components cannot.

In Design Patterns: Elements of Reusable Object Oriented Software Gamma et al (known as the Gang of Four) identify four essential elements of a software pattern:

  1. The pattern name
  2. The problem for which the pattern is applicable
  3. The solution the pattern provides
  4. The consequences of applying the pattern

Of these, the purpose of the pattern name, the problem and the solution are self-evident. It is the consequences that are of particular importance. Every design choice implies tradeoffs where choosing an alternative will make some things simpler and others difficult. Knowing these consequences is the most factor in making an informed design decision. If you adopt a design pattern without considering its applicability you are essentially gambling that the benefits outweigh the costs for your application and this is not a gamble you can consistently win.

The Gang of Four describe a number of generic patterns applicable to a wide variety of software scenarios. These are a good foundational set but do not cover (and do not seek to cover) all possible software domains. Patterns exist that are relevant only within particular domains. Example of this include Martin Fowler's Patterns of Enterprise Application Architecture and Enterprise Integration Patterns: Designing, Building and Deploying Messaging Solutions by Gregory Hohpe and Bobby Wolfe. I have also seen books discussing patterns in the context of a specific programming language. I can't help but feel this partially misses the point: by focusing on use in a specific programming language the distinction between design and implementation is blurred in a fashion not necessarily conducive to good design.

One of the reactions to design patterns has been the identification of anti-patterns; things that are commonly done that represent poor practice and inadequate design. Whereas design patterns provide guidance on what to do anti-patterns provide examples of what not to do. They therefore encapsulate knowledge of approaches that don't work, have poor performance, that destroy maintainability or otherwise negatively impact the quality of the software being developed. Familiarity with common anti-patterns is important so that they may be recognised and eliminated.

Anti-patterns can be somewhat problematic in that they often arise out of lessons learnt from using previous leading edge technologies or are created when new technologies expose problems in older approaches. One of my preferred examples of an anti-pattern is in fact a pattern in the Gang of Four book: Singleton.

The problem with Singleton is not with the pattern itself. Where there are limited or expensive resources it may be a legitimate strategy. The problem is the with the ridiculous overuse of the pattern in development projects of all types. The problem is so bad that the term Singletonitis has being coined to refer to ill-advised use of the Singleton pattern. This results from an unthinking application of the pattern regardless of actual need.

One of the biggest reasons I've seen for using the Singleton pattern is to prevent multiple object constructions in a classic premature optimisation. The use of the pattern here seems to be due to an assumption that creating objects is expensive. This is indeed sometimes true. For instance creating a NHibernate session factory is an expensive operation and Singleton may actually be applicable in some applications to prevent construction of multiple session factories. The key here is that the creation is expensive, as the session factory needs to do a lot of work (such as reading configuration, reflecting over assemblies and creating proxy objects). Most objects don't do that much work. Indeed most of the objects I've seen made into singletons don't have any instance fields and do no work on construction. Creation of such objects in .NET is very cheap. Your singleton check to see if the object is instantiated (depending on how you've implemented it) is likely to be more expensive. You've just de-optimised in the name of performance, not exactly the most brilliant of decisions.

There are patterns where the test can be avoided, but this misses the point. Creating the object is trivial (unless you're making large numbers in which case your algorithm is probably wrong). Optimising out a trivial construction is a false economy. Introducing a Singleton also makes unit testing and mocking more difficult. In a modern development project you should optimise for maintainability by preference. Selecting Singleton to give you some highly suspect performance increase does not meet this criteria.

What the above example shows is that applying patterns without thinking about them is itself an anti-pattern. One common feature when a developer first encounters patterns is that in their initial enthusiasm they will attempt to apply as many patterns as possible and to use patterns in all circumstances. This tends to lead to an overcomplicated design with flexibility in all the wrong places. The appropriate approach is to make each pattern justify its own existence and to refactor out patterns that cannot be supported by a clearly defined need. This promotes a cleaner and simpler design that is ultimately easier to work with.

This posting is the beginning of my preparation for a presentation on patterns. For a more comprehensive treatment I strongly recommend starting with the Gang of Four book which in my non-humble opinion should be mandatory reading for all software developers and application architects.