
David Abrahams wrote:
on Sat Aug 16 2008, "Christian Holmquist" <c.holmquist-AT-gmail.com> wrote:
calling the set_address method which will result in either a Default or Configured state. He intentionally described that as undefined behavior. Sorry for breaking in, I'm no expert on state machines at all but.. isn't
However, nothing stops me from simply the goal of expressing a FSM by the aid of the proposed to library to minimize the chance of undefined behaviour?
*The* goal? There are lots of potential reasons one might want to use a library. In general, a library that allows a fairly direct expression of the FSM as described in its "native" language (OK, maybe graph diagrams won't work, but you could use state transition tables) should lead to code that is more correct and maintainable.
David, you won't argue that every tool has its purpose, will you? I'm sure it is possible to put a nail in the wall with a microscope, but it's not the microscope's flaw that it's too fragile for that. State machines, as I see it, are meant to define an object behavior, IOW reduce the amount of undefined behavior. It is pointless to use them to implement undefined behavior.
I find the code written using the proposed library rather procedural in nature (rather than declarative), thus the OP's comparison is very apt from my point-of-view. The hand-rolled code actually looks clearer and more direct to me.
Please, have a look at my reply to Phil. I've attached a code snippet with a transition map. Does that look more declarative?
Note that when the OP wrote "undefined behavior" I don't think he meant that the C++ standard would say it was undefined; rather that his state machine implementation was not going to promise any particular results on invalid inputs. Avoiding undefined behavior is certainly not always the primary goal of using a library.
If the OP's state machine doesn't guarantee its valid state,
It guarantees a valid state as long as the inputs are valid, just as
x / y
or
*p
do, where x, y, and p are primitive types. Most libraries I know have similar contracts.
I don't fully agree with this. On the one hand, yes, most libraries rely on the valid input and this is "the right thing". On the other hand, FSMs are often used in domains where input is not always valid (parsers, protocol clients, GUI and so on). And FSMs are one of the tools to define behavior even in face of invalid input. It's the difference between a good and bad application: the good one doesn't blow up the Sun if you push the wrong button. :)