EEZ Studio Watch: Separate the Initial Value from Later Change Notifications

An EEZ Studio Watch action can send a value before anything has changed. That first output is useful for initializing a display, but it can surprise a Flow that treats every received value as a new event. A command, audit entry or counter connected downstream may run once during initialization and again after a real change.

The Watch documentation describes an initial expression result followed by outputs when the result changes. The pinned framework implementation stores the first value and emits it when execution state is created; later evaluations compare against the stored value.

The implementation reference is framework commit dc9af2d5004201d6c31273a4c4fcfe27fc20c234. It is separate from the EEZ Studio v0.29.0 editor reference used for this investigation. Verify the runtime actually shipped by the project before relying on implementation details. This discussion concerns standard EEZ Flow, not Flow Lite.

Separate state initialization from event handling

Imagine a watched variable called mode, initially set to an existing operating mode. A label should display that mode immediately, so the initial Watch output is desirable. A log that claims “the operator changed mode” needs different evidence: the initial state alone does not establish an operator action.

Classify each downstream consumer. A state-display consumer can usually accept the first value as initialization. An event consumer needs an explicit policy for the first observation. Do not solve the issue by discarding the first value everywhere; that can leave the display stale until the next change.

An application-owned initialization flag can be one way to separate those paths, provided its lifetime matches the Watch instance being observed. The flag is part of the proposed design, not an implicit feature of Watch. Resetting it at the wrong time can either suppress a real transition or mislabel a new initial observation as a change.

Watch initialization emits the first value to a state consumer; subsequent equal or changed observations are distinguished, with an explicit first-output policy for event consumers.
Original Watch lifecycle model based on the pinned framework. It does not imply lossless capture of every transient source change.

Test equal values before testing complicated objects

Use a simple scalar and a diagnostic sink that records each output with its value. Start with 10, allow the Watch to establish its initial observation, assign 10 again, then assign 11. Finally, assign 10 once more.

The intended diagnostic distinguishes three categories: initial output, equal-value assignment and changed result. For the cited implementation, later output depends on comparison with the stored result, not merely on the fact that some code performed an assignment. A different input expression can therefore produce no new Watch output even when one of its underlying variables was written.

For example, if the watched expression maps several raw values into the same displayed category, transitions within that category may leave the expression result unchanged. That can be exactly right for a label and wrong for a raw transition counter. Choose the observed expression according to the consumer's requirement.

A Watch is not an event recorder

The documented change notification does not establish that every short-lived source transition is captured. If a value changes and changes back between observations, this source analysis supplies no guarantee that both intermediate states will be delivered. It also supplies no fixed sampling interval.

Use an explicit event or sequence record when the product must account for every occurrence. That is an application-design requirement, not a criticism of a state-observation component. A current-state display and a lossless event history have different contracts.

For the same reason, do not infer hardware-edge capture from a Watch connected to a variable updated by native code. The runtime observation schedule and the native producer's behavior need their own analysis. A visual test with slow manual changes does not establish behavior under a fast producer.

Include the Watch's lifetime in the test

Exercise the actual lifecycle that creates and destroys the relevant Flow state. Observe whether returning to a screen reuses the same Watch execution state or establishes a new observation in that project. Do not assume every navigation event restarts Watch, or that none of them do.

This matters when the downstream initialization policy uses a flag or prior value stored elsewhere. A persistent flag paired with a newly created Watch may classify the initial output incorrectly. Conversely, resetting an application flag while the Watch remains active can cause the next real change to be treated as initialization.

Keep these lifetime checks tied to the actual Flow placement. The source shows how a missing execution state is initialized; it does not make every screen-navigation pattern equivalent.

Start with a narrow equality contract

The implementation contains special handling for a stored string value and uses the framework's value comparison for later observations. That is not enough to promise deep structural equality for every array, object or mutable nested value. Test the types and mutation patterns the project actually watches before applying the scalar result to them.

A useful acceptance record therefore states the watched expression, its type, the first-output policy, the expected equal-value behavior and the lifetime boundary. The proposed experiment has not been executed here. Its purpose is to prevent a state initializer from being mistaken for proof that an external event occurred.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *