|
Boost Users : |
From: Joel de Guzman (joel_at_[hidden])
Date: 2006-09-12 19:10:33
Scott Meyers wrote:
> So I'm confused. Constructors that "really" initialize objects detect
> some kind of errors during compilation, but they make testing harder,
> are arguably contrary to exploratory programming, and seem to contradict
> the advice of the designers of the .NET API. Constructors that "sort
> of" initialize objects are more test-friendly (also more loosely
> coupled, BTW) and facilitate an exploratory programming style, but defer
> some kinds of error detection to runtime (as well as incur the runtime
> time/space costs of such detection and ensuing actions).
>
> So, library users, what do you prefer, and why?
One-phase construction definitely! Testing in isolation is a different
matter and should not degrade the interfaces. There are ways to allow
isolated testing without degrading the interface. It all boils down
to decoupling and isolating dependencies. My favorites:
1) Use a template where policies can be replaced by hooks to the
testing engine that tests the expected results. In your example,
I'd imagine this interface: template <class Printer> EventLog.
2) Use callbacks. In the example you provided, I'd imagine EventLog
calls logstream to print. So, I'd use a constructor like:
EventLog::EventLog(boost::function<void(std::string const&)> print)
instead. So, instead of calling logstream << stuff directly,
I'll call print(stuff). For the testing engine, I'll replace it
with something that tests the expected results.
All these falls under the "Hollywood Principle: Don't call us,
we'll call you". IMO, with proper design, you can have both single
phase construction *and* isolation testing.
Regards,
-- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net