Avoiding two phase initialization
I've been doing some reading and the general opinion seems to be that two
phase initialization is to be avoided where possible. I agree with much of
what it said. But I'm not finding it so easy to eliminate.
Here is an entirely made up example, although strongly based on some real
code -
Imagine I am building a game. The main game class needs to construct a
"RenderDevice" object that does the 3d rendering. But in order to
construct this it needs some settings to be loaded from a configuration
file. And a Window object to draw into. And a logger object, and a memory
pool. My code now puts all of those things as class members where the
constructor does little and then calls an init function on each object
with the relevant parameters, something like :-
// Much simplified code to make a point
Game::Game()
{
memoryPool_.init(10000000); // Amount of memory to allocate
logger_.init("logfile.txt", memoryPool_);
window_.init(2000, 1000); // Make a nice big window
renderDevice_.init(window_, logger_, memoryPool_);
}
That to me seems to work reasonably well. But it's two phase. Each object
is only partially constructed by it's constructor. So I'd have to do
something much like this instead to make the code "clean".
Game::Game() :
memoryPool_(1000000),
logger_("logfile.txt", memoryPool_),
window_(2000, 1000),
renderDevice_(window_, logger_, memoryPool)
{
}
Now that code seems rather ugly to me, but also rather fragile as the
order of initialization depends on the order they are declared in the
class, NOT the order listed here. As more data gets added to the class, it
gets even worse. The objects here only require a few parameters but if
they need more data this will rapidly get out of hand.
It has the advantage that each object is constructed ready to do it's job,
but it looks ugly to me and seems rather fragile and error prone...
So my question is have I missed the point? Is there a better way to do
this? Should I stop worrying and just do this, or should I use my original
code? Or is my whole design wrong at a higher level in some way and so the
question isn't useful?
Basically what is best practice?
No comments:
Post a Comment