"New" is a Dirty Word
In OO programming, instantiating, delivering and utilizing object instances is pretty serious work. If you don’t think carefully about where and when to use “new”, your entire system can suffer – code reuse and refactoring become more and more difficult, and you may not even know why it’s happening. Calling “new” in the wrong place is not uncommon… but it can be disastrous.
A number of coding strategies we employ – TDD and Presenter First (http://atomicobject.com/files/PresenterFirstAgile2006.pdf), for example – lean heavily toward highly decomposed systems of objects, each object specially (and narrowly) designed to do a simple job, and not much else. We design these objects by delegating any complex behavior we encounter to subcomponents, which have been provided to us by somebody else. The need to this was driven on the ground by the need to test the higher-level object in terms of its interaction with its components.
If we’d called “new” on the subcomponents in the main component’s constructor, we couldn’t have tested the way we needed to. We made it someone else’s responsibility to give us the objects we needed. We expected to be able to change these demands at will, and get more or less objects brought in to do our work, and we didn’t expect to have to pay much for it.
Our fight for testability kept leading us down the path to ever smaller, narrow-purpose objects that could have their special behaviors isolated from their real-life circumstances (ie, the objects they use to accomplish their tasks). But as we started to delegate responsibility, the issue of object composition and delivery became monstrous. Who should create these objects was often conflicting with who could create the objects. Who has access to the components needed to build object A, and then, who needs to be composed with object A… the locations were not always consistent. We began to hate and fear “constructor chains, ” and indeed the “new” operation itself.
Unfortunately, we found the “owning” objects of these demanding components to be a little overburdened with the need to change whenever one of their “owned” objects needed something new. It became more and more difficult to keep them supplied with the materials they needed to construct and compose those other objects.
We identified that to create an object from thin air is a fairly important responsibility for a class. So if a class instantiates objects, and we’re going for classes of single responsibility, all that class can do with its objects is send them somewhere else. Which means that any class that instantiates objects in its own constructor for is own use is already doing to much and needs to be decomposed.
The quick-n-dirty method is to have a class or factory method somewhere that does all or most of the object composition for a major area (or all) of an application.1 2 3 |
contact_editor_model = ContactEditorModel.new contact_editor_view = ContactEditorView.new ContactEditorPresenter.new(contact_editor_model, contact_editor_view) |
1 2 3 4 |
contact_editor_view: contact_editor_model: contact_editor_presenter: compose: contact_editor_model, contact_editor_view |
1 2 3 4 5 |
delete_confirmation_dialog: dialog_shower: compose: delete_confirmation_dialog contact_editor_model: compose: dialog_shower |
- isolate the composition responsibility from the rest of the code
- do not have the opportunity to write code in your compositing area that you have no business putting there. The devil may not tempt you.
- can easily generate documentation about the composition of your system, including tables and graphs (we’ve used a combination of WEBrick and Graphviz to create a local webapp for interactively navigating the object structure of a large .NET desktop app… it was very instructive at times.)
- feel encouraged to decompose more and more of your code, because there is no pain associated with it now. It’s fun.
Tips In reference to system-level (architectural) objects:
- Don’t call new() unless it’s your explicit job to do so
- Find tools that call new() for you
- If you build it, you cannot use it.
- Pass it off, or notify others to come and get it.
- Use constructor-based injection
- An object cannot really function without its primary components.
- Prevents dependency cycles in your design
David Crosby Says:
December 12th, 2006 at 07:39 AMThat Law of Demeter link is broken; here's what it was supposed to be: http://en.wikipedia.org/wiki/Law_of_Demeter Or just Google for it. /C
ratjoream Says:
August 31st, 2008 at 01:05 AMbuy soma money order Order xanax online without prescription buy viagra overnight delivery Buy xanax online without prescription generic viagra cheap online no prescription Buy viagra without a prescription overnight Buy xanax online with no prescription cheap tramadol without a prescription Buy xanax no prescription buy generic viagra in canada online without a prescription Buy xanax online without prescription order xanax with no prescription Buy xanax online with no prescription Buy cheap online Cialis Order Soma without prescription Carisoprodol overnight delivery viagra free overnight fedex delivery tramadol online overnight Generic Cialis overnight delivery Xanax without prescription cheap xanax shipped overnight no prescription