Knowing when to Apply a Design Pattern
I've been reading up on design patterns lately, particularly those in Core J2EE Patterns. Design patterns are great - they help software architects rely on the collective knowledge and experience gathered from past projects; they also allow designers, developers, and analysts to use a common language.
It occurred to me while flipping through the Core J2EE Patterns that several of them are either outdated or at least their utility has been diminished by advances in JavaEE. (Not to mention that this may mean some of the Core J2EE 'patterns' are too implementation specific and may be better labeled as strategy than pattern).
After seeing a pretty funny blog entry last week on Dart-board Driven Design, I thought I'd finish off a blog post I started on deciding when to use design patterns.
My argument is that the cost of the additional layer of 'pattern' code should be outweighed by the value the pattern delivers; further, you must evaluate the value when implementing any pattern.
The following rules should apply when determining the value of a pattern:
- Knowing when to apply a pattern requires understanding what problems the pattern solves
- Knowing how to apply a pattern requires understanding how the pattern works
- Knowing your environment is essential to knowing what problems a pattern solves
- Knowing when to apply a pattern is more important than knowing how to apply the pattern
So, let's take the Value Object pattern (later renamed the Transfer Object pattern) as an example.
To understand the Value Object pattern, it's most important to know when to use the pattern, which requires knowing what problems the pattern is designed to solve. Typically, discovering the intended use of a design pattern can be found in its origin; in the case of the VO pattern, its origin has been covered thoroughly across the web, so I won't go in depth - but in short:
The Value Object pattern was developed to circumvent performance problems in earlier versions of JavaEE (specifically Entity Beans in EJB2.1 and earlier).
So, in the case of the Value Object pattern, recent improvements to JavaEE (EJB3 or JPA more specifically) mean that in most cases, the pattern won't be necessary if your environment has those recent improvements. In other words, the cost associated with the pattern (initial development time, maintenance costs, higher developer learning curve) outweighs its value in most cases.
The first step to making design pattern decisions should be: break down your assumptions and present yourself with a decision. Note this will require becoming thoroughly knowledgable on your environment and possibly removing FUD related to the technology in your environment (or, inversely, disproving the hype).
Note that I haven't said "don't use the value object pattern" - that's not my point. My point is that the use (or non-use) of a design pattern should be based on whether the pattern solves problems that you actually have (or will actaully have - before you get up in arms see subjectivity point below).
In fact, I think there are scenarios in an EJB3 environment where the value object pattern should be applied; for example, if a given use case requires retrieving large sets of coarse-grained entities and your non-functional requirements can't be met through existing constructs available in your environment (lazy loading, etc.).
Said another way, I argue that when developing complex software, architects should favor less complexity and implement patterns (and custom pattern glue / framework code) only as non-functional requirements demand it.
Regardless, knowing when to implement a design pattern is undeniably subjective: requiring unmeasurable levels of foresight and past experience. I argue, nonetheless, that questioning assumptions and getting to know your environment will lead to better design pattern decisions, which will in turn lead to more efficient (and more profitable) projects.
References
- http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html
- http://java.sun.com/developer/technicalArticles/ebeans/ejbperformance/
- http://java.sun.com/developer/technicalArticles/J2EE/jpa/
- http://en.wikipedia.org/wiki/Data_Transfer_Object
- http://en.wikipedia.org/wiki/Non-functional_requirement
