Solutions to Lab 3 exercises
Again, here are a few different designs. Here, we have a region for the output, so that we can see them in the simulation, but you should be prepared in the exam to solve this kind of exercise where Light.turn_on and Light.turn_off are operations that do not show up in the simulation.
The car compartment light
On Tuesday, we interpreted the requirements such that locking the door disables the light. Friday's group decided that it should still allow people locked in the car to turn the light back on, it should only go off when locked. A good way to evaluate these different designs below is to ask: how easily can you decide which decision was made by looking at the different designs.
Attempt 1
First attempt, we have the button controller deal with everything.
This works, but there is something smelly about it. If someone created a taxonomy of state machine smells, surely "state transitions as assignment" would make the list: we go from every state to precisely the same state indicated by the event.
Attempt 2
It seemed like a good idea to instead just model the button press as affecting boolean variables. We can set this up in the interface:
interface Button: in event turn_off in event turn_on in event make_sensitive var on: boolean var sensitive: boolean
While trying this design, it became apparent that the key information is whether the door is sensitive or not:
Note that all operations in this single state region can be moved into an internal interface, but even so, this design is fairly messy, but it was in this mess that I realized we only need to care about sensitivity. You might have seen that immediately, but I often need to try many different bad designs before I hit on the key insight.
Attempt 3
Once we realized only sensitivity matters, we can go back to a state based view, and the following actually looks pretty good:
This one distributes the logic of control, but it does so consistently; in each state, we react to the event changes of the other interface. Let me know if you have a nicer design!
The traffic light
The trick here is how to allow the cars to be green for at least a certain amount of time. I do not think we can avoid either a boolean variable or an integer variable to remember the state of the countdown. Here, we use a variable request to register that the pedestrian pressed the button and as soon as the minimum period has passed we check (using a choice node) if the request has already come. If not, we go into a waiting state where we react immediately to a push:
interface: in event push internal: event orange event green event red event peds var request: boolean = true