4.2 Elements of a Solution
4.2.4 Continuously Evaluated Functional Views
As described in Section 2.3.2, models and views are often best viewed as state machines. The state of these components is established by either directly setting the state (via transfer of all or part of the state from a replica) or by the execution of commands (state machine inputs) which modify the component state in some deterministic fashion. Initial state is often established via state transfer, after which the state is maintained via command execution. Assuming an initial component state
S0 and subsequent statesSi that result from the execution of commands Ci, the state
of a component after a command execution can be viewed as a function f of its previous state and the command to be executed:
Si+1 =f(Si, Ci+1) (4.1)
By induction, another form of this equation is:
Si+1 =f(S0, Cj|j ∈ {1..(i+ 1)}) (4.2)
That is, the current state of the component at any point in time depends on its initial state and the ordered set of commands that have been executed.
Non-determinism comes about when we do not have control over all of the inputs to the state machine. That is, the component actually operates deterministically, but it does not appear to do so from our perspective because we do not have access to all
of its inputs. If we represent all such uncontrolled inputs asX, Equation 4.2 becomes:
Si+1 =f(S0, Cj|j ∈ {1..(i+ 1)},X) (4.3)
In order for us to make guarantees about the behavior of our system, we must ei- ther assume that components to be replicated are coded such that they have no dependencies on external inputs (Equation 4.2), or that their behavior is well-enough understood that a careful choice ofCj|j ∈ {1..(i+ 1)}will avoid any non-determinism
introduced by X.
For completeness, we need to consider not only the state S of the component, but the outputs O emitted by that component on state transitions. If we simplify the equation by assuming that outputs are only emitted on the execution of commandsC
(which we can do without affecting the results of this discussion), the output equation corresponding to Equation 4.3 is:
Oi+1 =g(S0, Cj|j ∈ {1..(i+ 1)},X) (4.4)
Here again, we must assume we can eliminate the affect of any uncontrolled inputs. But since we must replicate the component multiple times, we must further constrain the outputs to be idempotent.
The salient point of the preceding discussion is that all collaborative infrastruc- tures must make assumptions about the coding of components they replicate. Where these components are state machines, we must assume that there exists a sequence of commands that will deterministically put the replica into the desired state, inde- pendently of any uncontrolled inputs, while producing only idempotent outputs.
the view components it replicates. In Concur, a view is best modeled as acontinuously evaluated function of known inputs rather than as a state machine. A continuously evaluated function is one whose output is always, modulo computation time, a func- tion of its inputs. The functional requirement means that the same inputs always produce the same outputs. This property is known as referential transparency.
Thus, in Concur, there is no state S, there are no uncontrolled inputs X, and commands C are replaced by inputsI. The relevant view equation for Concur is:
Vcurrent =v(Icurrent) (4.5)
That is, the current output V is a function v of the current inputs I. Uncontrolled inputs and non-idempotent outputs are also eliminated by the restricted container in which Concur view and controller code runs.
The requirement set imposed on the coding of functional view components is not substantially more burdensome than the requirements described above for compo- nents modeled as state machines. However, it has the following dramatic advantages:
• Latecomer support is simplified, because the infrastructure need never store the state of a view or the commands required to establish that state.
• Establishing a latecomer view can be more efficient, because it depends only on a bounded set of current inputs, not a sequence of commands that can increase in length indefinitely over the life of a session.
• Mobility support is simplified because there is no view state to maintain while no one is viewing an object.
• The robustness of the system is enhanced because the current view output does not depend in any way on previous state or inputs. Thus, if there is a
view code bug that causes the output to be incorrect for a given input, future outputs that are correctly computed are not affected. By contrast, in the state machine approach a view code bug can create incorrect internal state at one point in time that can invalidate future states and outputs indefinitely, even if the computation of these latter states and outputs is correct.
• Testing of the replica’s adherence to the infrastructure’s requirements is fa- cilitated, because setting up the current inputs to a function is simpler than establishing the state of a state machine, and because functional guarantees can be checked without knowing the semantics of the function itself.