A couple of months ago I wrote a Dependency Injection component for the Zend Framework. It’s a simple solution to a complex problem: removing hidden dependencies and injecting mocked objects. The component has evolved quite a bit since I first created it, and it’s now part of a bigger system, where objects are persistent, can have different states and are part of an interconnected network of objects.
Pádraic Brady, one of the Zend Framework developers, wrote a nice article about Zend_Di:
“Dependency Injection is both the ultimate bane and blessing in PHP programming. If you’re an experienced object oriented programmer, chances are you already know what the term means, and why it’s an all-consuming obsession. If you don’t, then here’s an overview.”
An AntiPattern is a pattern that tells how to go from a problem to a bad solution. For example:
- The Blob
Procedural-style design leads to one object with a lion’s share of the responsibilities, while most other objects only hold data or execute simple processes. The solution includes refactoring the design to distribute responsibilities more uniformly and isolating the effect of changes.
- Continuous Obsolescence
Technology is changing so rapidly that developers often have trouble keeping up with current versions of software and finding combinations of product releases that work together. Given that every commercial product line evolves through new releases, the situation is becoming more difficult for developers to cope with. Finding compatible releases of products that successfully interoperate is even harder.
- Lava Flow
Dead code and forgotten design information is frozen in an ever-changing design. This is analogous to a Lava Flow with hardening globules of rocky material. The refactored solution includes a configuration management process that eliminates dead code and evolves or refactors design toward increasing quality.
- Ambiguous Viewpoint
Object-oriented analysis and design (OOA&D) models are often presented without clarifying the viewpoint represented by the model. By default, OOA&D models denote an implementation viewpoint that is potentially the least useful. Mixed viewpoints don’t allow the fundamental separation of interfaces from implementation details, which is one of the primary benefits of the object-oriented paradigm.
- Functional Decomposition
This AntiPattern is the output of experienced, nonobject-oriented developers who design and implement an application in an object-oriented language. The resulting code resembles a structural language (Pascal, FORTRAN) in class structure. It can be incredibly complex as smart procedural developers devise very “clever” ways to replicate their time-tested methods in an object-oriented architecture.
Poltergeists are classes with very limited roles and effective life cycles. They often start processes for other objects. The refactored solution includes a reallocation of responsibilities to longer-lived objects that eliminate the Poltergeists.
- Boat Anchor
A Boat Anchor is a piece of software or hardware that serves no useful purpose on the current project. Often, the Boat Anchor is a costly acquisition, which makes the purchase even more ironic.
- Golden Hammer
A Golden Hammer is a familiar technology or concept applied obsessively to many software problems. The solution involves expanding the knowledge of developers through education, training, and book study groups to expose developers to alternative technologies and approaches.
- Dead End
A Dead End is reached by modifying a reusable component if the modified component is no longer maintained and supported by the supplier. When these modifications are made, the support burden transfers to the application system developers and maintainers. Improvements in the reusable component are not easily integrated, and support problems can be blamed upon the modification.
- Spaghetti Code
Ad hoc software structure makes it difficult to extend and optimize code. Frequent code refactoring can improve software structure, support software maintenance, and enable iterative development.
- Input Kludge
Software that fails straightforward behavioral tests may be an example of an input kludge, which occurs when ad hoc algorithms are employed for handling program input.
- Walking through a Minefield
Using today’s software technology is analogous to walking through a high-tech mine field [Beizer 97a]. Numerous bugs are found in released software products; in fact, experts estimate that original source code contains two to five bugs per line of code.
- Cut-and-Paste Programming
Code reused by copying source statements leads to significant maintenance problems. Alternative forms of reuse, including black-box reuse, reduce maintenance issues by having common source code, testing, and documentation.
- Mushroom Management
In some architecture and management circles, there is an explicit policy to keep system developers isolated from the system’s end users. Requirements are passed second-hand through intermediaries, including architects, managers, or requirements analysts.
Times arise where a class (One) is supposed to do everything another class (Two) does and more. The preliminary temptation would be for class One to extend class Two , and thereby inheriting all of its functionality. However, there are times when this is the wrong thing to do, either because there isn’t a clear semantic is-a relationship between classes One and Two , or class One is already extending another class, and inheritance cannot be used. Under such circumstances, it is useful to use a delegation model (via the delegation design pattern), where method calls that class One can’t handle are redirected to class Two . In some cases, you may even want to chain a larger number of objects where the first one in the list has highest priority. The following example creates such a delegator called ClassOneDelegator that first checks if the method exists and is accessible in ClassOne ; if not, it tries all other objects that are registered with it. The application can register additional objects that should be delegated to by using the addObject($obj) method. The order of adding the objects is the order of precedence when Class OneDelegator searches for an object that can satisfy the request:
Today I came across an interesting post written by Troels Knak-Nielsen. We all know that patterns are not perfect in all situations and the Registry pattern is no exception. Here is what Troels has to say about this:
The subject of polymorphism is probably the most important in OOP. Using classes and inheritance makes it easy to describe a real-life situation as opposed to just a collection of functions and data. They also make it much easier to grow projects by reusing code mainly via inheritance. Also, to write robust and extensible code, you usually want to have as few as possible flow-control statements (such as if() statements). Polymorphism answers all these needs and more.