
Robert Bell <belvis <at> imageworks.com> writes:
However, no matter from what angle I start to think this through I always end up with the same bad feeling. If we introduce entry()/exit() for the reasons you give (more flexibility for optimization?)
More flexibility to change the implementation, for any reason (not necessarily optimization).
Why else would you want to change the implementation (while leaving the interface as is)?
By using constructors and destructors for entry and exit, you're telling users that fsm guarantess that States will be constructed and destroyed at specific times, which means that for all time fsm must provide those guarantees.
Yes, what's so bad about that? We'd have to guarantee the same with entry() and exit().
this essentially means to tell the users that they must not under any circumstances rely on when exactly constructors and destructors of state objects are called.
Keep in mind that it's entirely possible that I'm missign something. That said, they can't rely on when exactly constructors and destructors are called today.
Yes they can. It is clearly defined when state ctors/dtors are called.
Even worse, they must not even rely on how many times state ctors/dtors are called.
They can't rely on the number of times they're called now.
Again, yes they can. The docs clearly define how often they are called.
Today they might be called exactly as often as entry()/exit() but tomorrow they might be called only exactly once.
None of these issues having to do with when and how many times constructors and destructors are called sound bad to me; why would anyone care?
This means that most non-POD data members of states need to be created on the heap, as you otherwise wouldn't have a chance to create them inside entry() and destroy them inside exit(). And believe me, you definitely need to do that when you design non-trivial FSMs. Therefore, to me entry()/exit() means falling at least halfway back into medieval times where you always had to explictly call constructors and destructors yourself (Turbo Pascal).
I don't quite see it this way myself, but in any event, this is a concern for the implementer of fsm, not a user of fsm.
No, users are directly affected. Assume for a moment that we have entry()/exit () and that you want to create a non-pod object of type A in the entry action and destroy it in the exit action. For the reasons given before you cannot do this in the ctor/dtor. So, your state object cannot have a data member of type A, instead you need to either have A * (or the smart equivalent) as member. In entry(), you then allocate a new A object on the heap and set the data member pointer to that object. In exit() you need to delete the object and set the pointer back to 0.
- Nobody has so far presented hard technical facts that support the view that mapping entry/exit to ctor/dtor is wrong. To the contrary, I think I have almost proved in my discussion with Dave that exit actions must not fail and that you *can* recover from failing entry actions.
I'm not so sure there _are_ hard technical facts; there are just two different interface choices, each with different tradeoffs.
So what exactly are the tradeoffs then, if it isn't performance?
I'm sure you've thought this out more than I have. I'm just coming from a gut-level reaction I have to linking entry/exit to construction/destruction. It just feels weird. For example, if entry and exit actions are things a state "does", then I'd expect them to be overridable; constructors and destructors can't be overridden.
How exactly would you want to override entry and exit actions? I mean, I personally haven't ever seen a framework allowing this, much less UML.
(In the past, when I've implemented state machines I've made Action a separate class; that way, Actions are attached to States, which makes it easier to reuse Actions in different States.)
While I do sometimes reuse transition actions, I have never felt the urge to do so for entry and exit actions. If you need to do that, no problem: Just call a function from ctor/dtor
I don't quite understand the objection to entry() and exit() member functions, but then again I don't have to understand it for fsm to proceed.
The objection is that it violates KISS. If there are hard *technical* arguments in favor of entry()/exit() then I'll happily add them. I hope we agree that so far no such arguments have been presented. Regards, Andreas