- for "missing?" we often need to query database to check if an item exists. If predicates are truly independent, we will need to do the query again to return the item.
- "data flow" looks something like this (in Prismatic's Graph lib):
(def stats-graph
{:n (fnk [xs] (count xs))
:m (fnk [xs n] (/ (sum identity xs) n))
:m2 (fnk [xs n] (/ (sum #(* % %) xs) n))
:v (fnk [m m2] (- m2 (* m m)))})
or as a picture:
This is basically a data structure that more-or-less explicitly encodes data dependencies between functions and allows to check stuff like "all data needed for a function is already computed when it's called".
On the other hand, "decision graph" (it can be encoded as FSM, as in the case of your HTTP decision diagram) is all about callbacks and outcomes. In all practical implementations that I've saw, callbacks were allowed to pass something "downstream" (in state
or query
) to solve the problem mentioned in (1). However, this introduces implicit data dependencies between callbacks that are inferior to explicit "data flow" model.
Therefore, it seems preferable to somehow "merge" both approaches, but I don't know yet how. It would be interesting to hear your thoughts on this.
Let me double-check that I understand you correctly: you mean that beside that decision tree (DAG, actually) encoded as FSM with callbacks there would be an abstract (and spec'ed) dependency structure between callbacks? Seems very reasonable, but I'm not sure if this is flexible enough.
Here is an example: let's say we have
get-etag
callback for forming ETag of an entity. In some cases, ETag is a function of an entity itself, soget-etag
may depend onget
(e.g., hash an entity). However, some databases (Datomic) provide better ways to "tag" particular version of an entity (in case of Datomic, transaction id). To leverage this, one will need to return a map fromget
with an actual entity and it's ETag value and peel it inget-etag
, therefore introducing "opaque bucket" that you've mentioned.