
"Andreas Huber" <ah2003@gmx.net> wrote in message news:loom.20040527T133057-890@post.gmane.org...
Johan Nilsson <johan.nilsson <at> esrange.ssc.se> writes:
What's stopping me from always create them in constructor/delete in destructor, then just init/deinit them (if necessary) in entry/exit?
The fact that most classes (well-designed ones) don't have init/deinit.
I'm totally aware of the RAII idom and didn't literally mean that the classes had init/deinit methods which would totally initialize and clean up the state. I referred to actions (_manipulating_ already created members: classes/pods/built-ins) that _might_ be necessary to call depending on the state in question. Ideally a state should be state-less, right? Once created it should always be able to execute the same actions no matter when in time. IRL there's more likely something that needs to be done to initiate the state. Does it matter if this is a two-step procedure: Allocate in constructors + Initialize in entry or one-step: Allocate and initialize in constructor. Non-trivial states will doubtlessly need to perform at least some amount of actions that are not simply construct their members. If you by providing explicit entry()/exit() actions (which can be _guaranteed_ to be called using RAII AFAIK) you're also encouraging the users of the library to separate resource acquisition from resource init: this also enables policy-based state lifetimes. If users have no need for entry / exit actions - they could be made virtual so that users don't need to implement them. Yes - virtual calls are comparatively expensive; maybe this could be fixed using some template meta-programming magic, explicit policies or whatever. I don't know - I'm just a potential library user ;-). Thinking about it there's (at least) one technical argument agains mapping entry/exit to constructor/destructor calls - restrictions on calling virtual member functions. Is this a 'hard' technical argument of not ... depends on your point of view. For me personally the semantics of explicit entry/exit methods is (at least) equally important. [... snip ...]
In terms of speed, I've got no real opinions (so far). I guess it depends on whatever fits the particular application in question - another reason for policy-based state-lifetime management (if possible)?
Everything is possible. The question is: What exactly is the advantage? What are the use-cases?
Library user wants to keep his state alive during the entire fsm lifetime ;-)
- Nobody has so far presented hard technical facts that support the
view
that mapping entry/exit to ctor/dtor is wrong.
See at least the restriction I mention above.
<philosophical entry/> For me, hard technical facts aren't everything. All software engineering
is
an art and a craft as well, IMHO. Should one always choose a particular design on hard technical facts only, or should you also trust your gut-level feelings (open question)? </philosophical entry>
To me good design is 10% ideas, imagination and, yes, gut-level feelings.
The other 90% are technical facts. I believe the initial effort when crafting an interface is always gut-based, afterwards comes the long and tedious
Gut-level feelings are there all the time during development; refactoring; recognizing "code smells"; ... I think it amounts to much more than 10% of the time you spend implementing (aka low-level designing) your library. period of
verifying (with hard facts) that your gut feelings are right. If there are no hard facts to justify a feature then I unceremoniously throw it out. Not doing so means overloading an interface and elevating the risk of overwhelming potential users with unnecessary baggage.
A bit off-topic perhaps, but Ruby (the language) frequently "overloads" methods with multiple names - makes more users think that the interface is intuitive. Not saying that we should do it in C++ (bloated interfaces are ge nerally bad), but it's worth thinking about. Regards // Johan