What are Development AntiPatterns?
(for a quick example, see the website's featured Development AntiPattern, Lava Flow)
Our first exposure to software development AntiPatterns was through the presentations
of Mike Akroyd, a hands-on software consultant to Motorola and other major firms [Akroyd
96]. The Akroyd AntiPatterns define classic problems in object-oriented software
design. Some of the development AntiPatterns in this book are extensions of his
concepts (see references). One attractive feature of all Akroyd AntiPatterns is the
inclusion of a refactored solution, the incorporation of which gives AntiPatterns
a valuable purpose: Not only to they point out trouble, but they also tell you how to get
out of it.
Proper AntiPatterns define a migration (or refactoring) from negative solutions to
positive solutions. AntiPatterns that describe only the negative solution are called
pseudo-AntiPatterns (or more typically, complaints -- think of
pseudo-AntiPatterns as flaming e-mail diatribes). After working with the Akroyd
AntiPatterns, we discovered examples of AntiPatterns and pseudo-AntiPatterns on the
Internet. The Pattern Languages of Program Design (PLoP) conference also discussed
some AntiPattern-related papers, such as the "Big Ball of Mud" [Foote 97].
Software Refactoring
A key goal of development AntiPatterns is to describe useful forms of software
refactoring. Software refactoring is a form of code modification, used to improve
the software structure in support of subsequent extension and long-term maintenance.
In most cases, the goal is to transform code without impacting correctness.
Good software architecture is essential for system extension and maintenance.
Software development is a chaotic activity, therefore the implemented structure of systems
tends to stray from the planned structure as determined by the architecture, analysis and
design. Software refactoring is an effective approach for improving software
structure. The resulting structure does not have to resemble the original planned
structure. The structure changes because programmers learn constraints and
approaches that alter the context of the coded solutions. When used properly,
refactoring is a natural activity in the programming process. For example, the
solution for the Spaghetti Code AntiPattern discussed in this book defines a software
development process that incorporates refactoring.
Refactoring is strongly recommended prior to performance optimization.
Optimizations often involve compromises to program structure. Ideally, optimizations
affect only small portions of a program. Prior refactoring helps to partition
optimized code from the majority of the software.
Read more about refactoring, and formal refactoring transformations in our book in
chapter five.
AntiPattern |
Synopsis |
Refactored Solution |
Ambiguous Viewpoint |
Lack of clarification of the modeling viewpoint
leads to problematic ambiguities in object models. |
Always clarify which of the 3 essential viewpoints is
modeled: business, specification, or implementation. |
Boat Anchor |
A costly
technology is purchased by a systems development project that goes unused. |
Send competent engineers to the product training course, in
order to evaluate, before you buy the product. |
Continuous Obsolescence |
Internet-time
technology releases surpasses our ability to keep up and keep other technologies
synchronized. |
Depend upon stable technologies and interfaces that you
control. Open systems standards provide stability. |
Cut and Paste
Programming |
Code reused by copying source
statements leads to significant maintenance problems. |
Black Box reuse reduces maintenance issues by
having a common source code, testing, and documentation for multiple reuses. |
Dead End |
Direct
modification of commercial software or reusable software creates significant maintenance
burdens for a software system. |
Avoid modification of supported software. Choose
mainstream, supported products and platforms whenever possible. |
Fire Drill |
Management waits until the last possible moment
to allow developers to proceed with design and implementation; then they want results
almost immediately. |
Proactive design and prototyping are often warranted; even
if customers and management staff are not completely on-board. |
Functional Decomposition |
Non-OO design (possibly from legacy) is coded in OO
language and notation. |
Since there is no straightforward way to
refactor: redesign using OO principles. |
Golden Hammer |
A familiar technology or concept is applied obsessively to
many problems. |
Expanding the knowledge of developers through
education, training, and book study groups exposes developers to new solutions. |
Input Kludge |
Custom-programmed input algorithms contain many
bugs which are easily encountered by users and testers. |
Utilize production-quality input processing techniques,
including lexical analysis, parser generators, and features matrices. |
Lava Flow |
Dead code and forgotten design information is frozen in an
ever-changing design. |
Configuration control processes that eliminate
dead code and evolve/refactor design towards increasing quality. |
Mushroom Management |
Keep the developers in dark and feed them
fertilizer. End-user interaction prohibited. |
Risk-driven development includes frequent user-interaction
to maximize usability and acceptance. |
Poltergeists |
Classes with a very limited roles and lifecycles, often
starting processes for other objects. |
Allocate the responsibility to longer-lived
objects and eliminate the poltergeists. |
The Blob |
Procedural-style design leads
to one object with numerous responsibilities and most other objects only holding data. |
Refactor the design to distributed
responsibilities more uniformly and isolate the effect of changes. |
Walking Through a Mine Field |
Software
technology is much less robust than people imagine; bugs are pervasive and potentially
catastrophic. |
Proper investment in software testing and inspection is
needed to reduce the frequency and density of software defects. |