should we impose constraints exactly as specified?
An action may be replaced by a combination of other actions:
set(k, v) = reset({..., k: v})
remove(k) = reset({...}) (map without k)
move(f, t) = set(t, V(f)) + remove(f)
Probably should keep it simple. These are not technically equivalent though, maybe overthinking.
should we impose constraints in action() or apply()?
Imposing constraints in action() seems easier to do, but apply() may be the way to go because action objects may not be constructed by action(). Experiment with and test both.
if we impose constraints in apply(), will the inverses be valid?
Test the following cases,
upsert
if element present, inverse upsert
not present, inverse setDeleted
setDeleted, inverse setDeleted
move, inverse move
probably should return false from apply() if action is not allowed
User may use return to decide whether to sync with other stores.
Goal
Guarding state integrity from arbitrary actions. Known use cases:
Cover these cases first and add more constraints later.
API
Considerations
should we impose constraints exactly as specified?
An action may be replaced by a combination of other actions:
Probably should keep it simple. These are not technically equivalent though, maybe overthinking.
should we impose constraints in action() or apply()?
Imposing constraints in action() seems easier to do, but apply() may be the way to go because action objects may not be constructed by action(). Experiment with and test both.
if we impose constraints in apply(), will the inverses be valid?
Test the following cases,
probably should return false from apply() if action is not allowed
User may use return to decide whether to sync with other stores.