Hi all, (apologies for the wall of text but I think the context might be useful)
I am using event sourcing so the world, at any given point in time is simply a `reduce` over those events. Throughout the application different things are interested in different events. A design that is emerging is the notion of a 'world' which knows how to consume the various events and allows other parts of the system to respond to certain states having happened. All of this is in-memory and could be client or server side (yay for .cljc and ClojureScript). In concrete terms imagine I have am modelling shopping baskets (again, all in memory). I might be interested in knowing: - whenever a certain item is added to a basket - whenever a basket is cancelled - whenever a complete basket is ordered I could of course just filter the event log and pick out those events but I typically want the entire entity _as it was when that event happened_, so the event itself isn't sufficient. My question is how best to model the 'I am interested in pre-x and post-y'. In general, it is interesting to know the event, the aggregate root (shopping basket) that event is associated with and the world (both the aggregate root and the world as they were at the time of the event). I could have an EventObserver: (defprotocol EventObserver (observe [this event entity world]) which the world notifies. One part of the system will have one set of EventObservers, another will have a different set of EventObservers. Also, some parts need to know _before_ the event and others _after_ the event. I don't want each Observer to have to specify every single event so a protocol defining a pre/post method for each event wouldn't work because (AFAIK) you can't have a default implementation of a protocol and you can't have a partial implementation of a protocol. Where I am at is thinking that the world understands a map of EventObservers, with one key for each pre/post event: {:pre-event-one EventObserver :post-event-one EventObserver :pre-event-two EventObserver :post-event-two EventObserver} etc. and each Observer can register their own map of EventObservers. I can optimise the code by either having the world handle nil EventObserver or having a default fully-populated map of EventObservers which Observers can simple assoc their own handlers onto. Building the world is then trivially (usual disclaimer - hacky stream-of-consciousness code): (defn- locate-entity [world entity] ...) (defn- update-entity! [world entity] ...) (defn- process-event [{:keys [observers world] :as result} event] (let [pre-handler-kw (keyword (str 'pre-' (name (:event-type event)))) post-handler-kw (keyword (str 'post-' (name (:event-type event))) pre-entity (locate-entity world event) new-world (update-entity world entity) post-entity (locate-entity new-world event] (do all (for [o observers :let [pre-event-observer (pre-handler-kw o) post-event-observer (post-handler-kw o)]] (when pre-event-observer (pre-event-observer event pre-entity world)) (when post-event-observer (post-event-observer event post-entity new-world)))) (assoc result :world new-world)) (defn build-world [events observers] (reduce process-event {:world {} :observers observers} events)) The above code could be improved in a myriad of ways, but hopefully it is clear enough to highlight the problem: what mechanism is idiomatic in Clojure to implement the Observers where each Observer is interested in a subset of before and after a subset of events. If you are thinking 'duh, this is obvious - use X' or 'what! that's not true of course you can do X with protocols' then yep, I have almost certainly overlooked something. Finally - yeah, at times like this I really miss AOP. Thanks for still reading :-) Colin -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.