Thank you for the toughtfull response.
Let me work through it:
Object oriented?… The approach that he favors, in which a state machine is specified by actions with pre- and post-conditions, has been the standard approach to specification since the 1970s for most specification languages (VDM, Z, B, Alloy, etc), and none of those languages are object-oriented.
Although in the example the FSM is specified with interactions between pre/post conditions and the invariants.
We could codify the whole FSM just in the invariants.
… scenarios provide a much more understandable overview of a dynamic behavior. Just look at Bertrand’s example and see if you can figure out what an insurance claim process involves, and compare that to the simple scenario. It’s just not that easy to infer traces in your head from pre- and post-conditions.
I agree that it’s difficult to visualize the simple scenario from the invariants.
But I love that:
- the whole FSM could be in a single place.
- since it’s in the invariant the FSM is warrantied to be respected during the execution of the program.
And although It’s difficult to create a trace of the process in my head,
It isn’t as bad as the current practice, which is to spread the FSM all over the code.
For example in the original example the invariants look like this:
invariant — “⇒” is logical implication.
is_evaluated ⇒ is_investigated
is_reserved ⇒ is_evaluated
is_resolved ⇒ is_agreed or is_imposed
is_agreed ⇒ is_evaluated
is_imposed ⇒ is_evaluated
is_imposed ⇒ not is_agreed
And just by flipping the arrows we can generate a state diagram like this:
[*] --> is_investigated : investigate
is_investigated --> is_evaluated : evaluate
is_evaluated --> is_reserved : set_reserve
is_agreed --> is_resolved : resolve
is_imposed --> is_resolved : resolve
is_evaluated --> is_agreed : negotiate
is_evaluated --> is_imposed : impose
Not too difficult,
and we can already there is something shady with that dangling
So I went to see the preconditions of
And discovered the FSM was incomplete in the invariant.
But with a couple modifications it was complete,
and this is the new diagram.
More fundamentally, I argue in my book that there’s a respect in which scenarios cannot be derived from actions. It’s true that the set of all possible scenarios can be derived; those are just the traces of the state machine that the actions define, and they can be automatically enumerated (Alloy will do this for you). But the point of scenario specification is to identify some key scenarios as being the essential ones for the design. These scenarios typically do not use all the actions, and they are chosen to show how the purpose is fulfilled.
Yeap… and this conversation we are having.
Has convinced me that scenarios must be documented as part of the code.
In a language like PyRet (by Brown University), they can be embedded in the
check clauses. [pyret]
In some others they can be documented as part of their DocTests. [doctest]
In other languages they can be part of examples (Smallatalk’s Glamorous Toolkit [gtoolkit])
And in all the others as part of the unit test framework. (xUnit).
But still the code must be able to fulfill all the valid traces,
not just the “main sucess scenarios”.
That’s why I think their proper place is in a unit test.
Pawson in both of his talks makes the point [dcfa], that:
Most management systems are “script” based,
and therefore they deprive the users (clerks)
from agency to solve the problems of the customers.
By using NakedObjects,
i.e. allowing all valid threads of execution.
Then users/clerks have a software that enables them to be:
“problem solvers, not just process followers”.
(This argument, btw, is inspired by Michael Polanyi’s argument for the operational principle, and his explanation of how knowing all the scientific properties of a device, eg a clock, is not enough to understand how it works—you need a scenario that puts it all together and demonstrates the purpose.)
Yeap completely agree.
While I dislike most of the UML notation.
I think the Sequence Diagram of the UML, the most useful one.
Because it shows the Dynamic view, (i.e. how the clock parts interact with each other, in time).
Vs all the other diagrams which show only the static view (i.e. the parts of the clock).
In case you might think that a delete action is always likely to be unimportant, note that in the AuthToken concept (in which a user generates tokens for other users to access a resource), the action that revokes the token (a kind of deletion) is essential to the operational principle, since it’s revocation that motivates the whole design!
And we can document in the invariant of the AUTHENTICATION class.
That in order to revoke a token,
first the token must have been issued before.
There is no contradiction there.
And we can document the operational principle,
as a TestCase of the AUTHENTICATION class.
Separating concerns. It’s interesting that Bertrand’s main example of over specification in the scenario is that the actions for settings a reserve and evaluating a claim might occur in a different order. I suspect this is because the management of the reserve, and the settling of claims, are actually two different aspects of functionality. Note that insurers set reserves even for events that do not yet have claims associated with them. From a concept design point of view, I would start from the assumption that Claim and Reserve are distinct concepts, and connected only by syncs. Then the lack of ordering becomes very natural and is no longer a subtle property of the specification.
Pawson clamis in the second video,
that since the Clerks are directly exposed to the Domain Model,
they quickly dis-ambiguate the situation.
Are reservations before a claim, after or are they independent?
Clerks will let you know, as soon as they try to perform the task,
and the model doesn’t let me.
Which I find a fascinating proposition,
to quickly converge to a correct model.
Agreeing with Bertrand. I do agree with Bertrand in some key respects though. For specifying the details of behavior, actions are much more succinct, and having to enumerate all use cases is very tedious. That’s why concept behavior is specified with actions and states (see the tutorials about state machines and concept states). On the other hand, highlighting one or two essential scenarios (the operational principle) lets you explain very compellingly how the action design meets the purpose.
So I’m converging to something like this:
All the behaviours must be modeled as part of FSM.
That will allow, all the threads of execution.
To be possible to be expressed in the system.
However, the happy path / main success scenario / operational principle.
Must be documented in an executable form (test-case).
So that we know for sure those most important threads of execution.
Are considered in the system.
Are objects enough? Back to the question you started with, which Pawson raises: can you describe intended functionality purely in terms of objects? In some trivial sense you can, because as we’ve noted, you can turn any process into an object. But in this case, objects seem to be an unnatural fit. In Bertrand’s example, he ignores the part of the scenario in which the claim is assigned to an adjuster. Where does that go? Perhaps Bertrand and Pawson would say that you can put that in a Clerk object, but that seems likely to end in trouble, since clerks presumably do all kinds of other things unrelated to this.
Yes, it would go in the Clerk object.
-- A Clerk starts a Claim, and assigns it to an agent.
new_claim := AClerk.start_claim(with: AgentBob)
I mean why wouldn’t it?
If a Clerk has many responsibilities in the real world,
then the Model should also reflect that reality.