Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

This is a doodle about a re-frame idea that's been rattling around in my head for a few days. It hasn't quite clicked, but I don't want to let it go yet.

I propose a new standard effect.

Currently, re-frame has the :db effect which replaces what's in app-db holus-bolus.

Imagine a new effect named, say: :db-crud.

You would use :db-crud instead of :db.

The value of :db-crud would be a vector of proposed changes to app-db. Update this. Delete that. Add another.

Imagine:

   {:db-crud   [{:add  [:some :path]  :val  2}
                {:del  [:a :path]}
                {:upd  [:a :b 2 :c]   :val  "hello"}]

The format used is not very important right now. The sketch above is just for flavour.

Question: why do it this way?
Answer: more information

When you use :db to make a complete app-db change, you pass on one piece of information - state has changed. But you don't say what, how or why.

A :db-crud effect says more. It says what path(s) changed, and how. It could even say (somehow) "why" the path changed, maybe. More information.

So, how could this additional information be useful?

Assume we could look at the nominated paths looking for matches (maybe using something like meander)

On finding a match we could, what? ...

  • rerender?
  • dispatch an event ?
  • compute further app-db crud?

A simpler, less pure variation of alex-dixon's precept?

This information could be used like a database WAL. Or a Kafka-like, event-sourcing bus-ish thingo.

There's a good, useful idea lurking in here, I think.

But ... the key is working out what useful thing can be done with the "extra information".

Every bit of flexibility is potentially useful, yes, but it always comes with a cost. I'm still trying to figure out the tangible benifit.

@jpmonettas

This comment has been minimized.

Copy link

jpmonettas commented Jun 29, 2019

Can't the what and how of the state change be calculated with something like clojure.data/diff ?

@niquola

This comment has been minimized.

Copy link

niquola commented Jun 29, 2019

good idea, worth to play with

@fmnoise

This comment has been minimized.

Copy link

fmnoise commented Jun 29, 2019

I like the idea. However shouldn't we allow passing a function in addition to value for :upd operation?

@vemv

This comment has been minimized.

Copy link

vemv commented Jun 29, 2019

One possible defect of :db-crud (which would be shared with the original :db efffect) is that updates express the final desired state, and not the actual programmer intent.

It's the same reason why clojure.core/swap! is preferrable to clojure.core/reset! the former is safer to use in concurrent programming, and it expresses the intent of updating, rather than expressing a final result (which provenance might not be so immediately clear in comparison, and which value would be less useful in an event log).

So, the following might could be better:

   {:db-crud/v2  [{:assoc-in  [:some :path] 2}
                  {:dissoc-in [:a :path]}
                  {:update-in [:b] inc}]}

Note that my :assoc-in and :dissoc-in are essentially equivalent to :add and :del. But they help make more evident whether :update-in would have been better, by using an homogeneous and familiar api (given the clojure.core/*-in functions)

Is {:update-in [:b] inc} a glorified version of (clojure.core/update-in [:b] inc)? Yes, but 'glorified function calls' are common/necessary in reactive frameworks (e.g. Redux actions, re-frame.core/dispatch).

@olivergeorge

This comment has been minimized.

Copy link

olivergeorge commented Jul 1, 2019

I like the idea of describing the change (e.g. like assoc-in) instead of passing and mutating db directly. One thought, I find it difficult to write helpers to which pass and contribute to generating the fx context. For example, if two helpers use :dispatch then one clobbers the other. I guess the fix is some kind of consolidation step in between each helpers. Specific issue related to :db-crud is how to apply :db-crud to db so that a helper gets a unified view of db. Not sure I've communicated that well.

@niquola

This comment has been minimized.

Copy link

niquola commented Jul 2, 2019

I would call it :db/transaction or :db/tx. Probably changes can be merged and batched. To simplify usage some helper functions like rf/assoc-in rf/udpate-in can be provided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.