martinfowler.com logo Home Blog Articles Books About Me Contact Me ThoughtWorks

ConstructorInitialization design 7 February 2006 Reactions

One of two approaches to initializing a new class, the other is SetterInitialization.

Constructor initialization is the approach where you try to ensure that you always create a class in a valid state by passing in all the collaborators that the object needs in the creation method of the object. So to create a person with firstname, lastname, and a collection of favorite bars we might see something like

# ruby
mf = Person.new('martin', 'fowler', 
                ['Turners Oyster Bar', 'Square and Compass'])

By doing this you are always sure you have an object in a reasonably well-formed state that's ready to go. It's also a nicely compact approach, allowing you to get the object going in one line. If you only want to do one thing with the object, you can also assign it or call a method on it in that single line, which means you don't need a variable lying around.

Declaring all the necessary collaborators in the constructor makes it clear which collaborators are needed, making it easier to see how to get the class going. You'll need one constructor method for each valid combination of mandatory collaborators. It's usually handy to provide constructors that include commonly needed optional collaborators too.

This approach makes it easy to see the difference between immutable and updatable attributes as immutable attributes don't have a setting method, they are just initialized in the construction method.

Constructor Initialization is my first choice. There are cases when it's difficult to set things up this way and I do occasionally prefer setter initialization, but most of the time constructor initialization is the best bet.

Common Issues

What if there's lots of different legal combinations for a new object? Often people get worried that there will be a gazillion constructor methods if you use this approach. Most of the time, this isn't an issue - there's only a few. You only really need the mandatory collaborators here, and there's hardly ever more than a handful of combinations of them.

What if there's a lot of collaborators to provide in the constructor? A large list of construction parameters, like any large parameter list, is a CodeSmell. Usually when I see these I find that many of the parameters are DataClumps and should be replaced by their own object. Having said that it's not unusual for constructor methods to have more parameters than other methods - but they are a good place to spot data clumps.

How does this square with ContextualValidation? The context here is basic usage of the object - essentially a minimally useful state. This probably won't be valid for various other activities, but it should be valid enough to be useful.


Links
home
bliki
feed 
Translations
Japanese
Spanish
Korean
Chinese
Thai
Categories
agile
design
dsl
leisure
refactoring
ruby
thoughtWorks
tools
uml
writing
Blog Roll
ThoughtBlogs
TW Alumni
Nicholas Carr
Steve Cook
Brian Foote
Simon Harris
Gregor Hohpe
/\ndy Hunt
Ralph Johnson
Patrick Logan
David Ing
Brian Marick
Jeremy Miller
Jimmy Nilsson
Samuel Pepys
Keith Ray
Johanna Rothman
Kathy Sierra
Dave Thomas

martinfowler.com logo mingle logo thoughtworks logo

© Copyright Martin Fowler, all rights reserved