I see where you are going. You don't actually need to store the system in an atom as it can be directly referenced from reloaded.repl.system, but I get your point (i.e. adapters).
Thanks Marc. On 25 February 2015 at 14:26, Marc Limotte <[email protected]> wrote: > Hi Colin, > > Nesting defmethod in the start fn of the Component does have a bad smell. > This actually seems counter to the intention of Component, which is to make > these dependencies explicit and external. I might do it like this: > > 1. Create a "pure" implementation using Component as it was intended. > 2. Stash the system map in an atom at startup > 3. Write some convenience functions with are the lower-arity versions, and > use the system in the atom for the missing arguments. Might be a good place > to use a macro if you're doing lots of these. > > This way, you have isolated the "friendly" (but less pure) API from the core > system. You can still fall back to the versions of the functions which have > explicit deps, which could be useful for testing and other scenarios. > > Example: > > > ; define your components and system > ... > > ; Tuck the system in here at startup > (defonce system (atom nil)) > > (defmulti handle-command first) > > (defn add-customer [db eventstore customer] > ...) > > ; Convenience function that pulls system from an atom > (defn add-customer [customer] > (add-customer (@system :db) (@system eventstore) customer)) > > (defmethod handle-command :add-customer [[_ customer]] > (add-customer customer)) > > (defn export-query [db pdf-generator] > ...) > > ; Convenience function that pulls system from an atom > (defn export-query [] > (export-query (@system :db) (@system :pdf-generator))) > > (defmethod handle-command :export-query [[_]] > (export-query)) > > > > marc > > > > > On Wed, Feb 25, 2015 at 8:23 AM, Colin Yates <[email protected]> wrote: >> >> Not as curious as me! Naval gazing is happening right now :). >> >> I realised this is part of a bigger question: >> https://groups.google.com/d/msg/clojure/C3mYu9fMXec/gGUF5rhhZfwJ >> >> On 25 February 2015 at 13:19, Jeroen van Dijk >> <[email protected]> wrote: >> > Sounds reasonable. Though destructuring a component (I was guessing "db" >> > etc >> > were fields of this particular component) isn't the same as passing the >> > whole system. I'm guessing that you have a lot bigger system in mind >> > than >> > these few commands. I don't have experience with that approach. I'm >> > curious >> > to see what you'll end up with. >> > >> > Cheers, >> > Jeroen >> > >> > On Wed, Feb 25, 2015 at 2:01 PM, Colin Yates <[email protected]> >> > wrote: >> >> >> >> Yes, I did consider that but didn't like the idea of passing the >> >> system around. Also handle-command would need access to the system as >> >> well. >> >> >> >> I am wondering whether simply having a 'registry' component which >> >> handlers register themselves with (e.g. a map of {predicate handler}) >> >> isn't a way forward and not using defmulti... >> >> >> >> On 25 February 2015 at 12:51, Jeroen van Dijk >> >> <[email protected]> wrote: >> >> > So I guess another question is where "handle-command" is being >> >> > called. >> >> > What >> >> > about providing the component as argument to the multimethod (there >> >> > are >> >> > other approaches too depending on your need). So: >> >> > >> >> > (defmulti handle-command(fn [component command] (first command))) >> >> > >> >> > (defmethod handle-command :add-customer [{:keys [db eventstore} [[_ >> >> > customer]]] >> >> > ... ) >> >> > >> >> > Isn't something like this enough? >> >> > >> >> > Jeroen >> >> > >> >> > On Wed, Feb 25, 2015 at 1:34 PM, Colin Yates <[email protected]> >> >> > wrote: >> >> >> >> >> >> Hi Jeroen - sure. >> >> >> >> >> >> I have a gateway which can handle a number of 'commands', let's say: >> >> >> >> >> >> AddCustomerCommand >> >> >> ExportQueryCommand >> >> >> >> >> >> to handle the AddCustomerCommand I need access to a database and an >> >> >> eventstore. To handle ExportQueryCommand I need access to the >> >> >> database, a PDF service and so on. >> >> >> >> >> >> One way of achieving this is (assuming commands are of the form >> >> >> [:command-discriminator payload]: >> >> >> >> >> >> (defmulti handle-command first) >> >> >> >> >> >> (defn add-customer [db eventstore customer] >> >> >> ...) >> >> >> >> >> >> (defrecord AddCustomerComponent [db eventstore] >> >> >> ... >> >> >> (start [this] (defmethod handle-command :add-customer [[_ >> >> >> customer]] >> >> >> (add-customer db eventstore customer))..) >> >> >> >> >> >> (defn export-reports [db pdf-generator] >> >> >> ...) >> >> >> >> >> >> (defrecord ExportQueryCommand [db pdf-generator] >> >> >> ... >> >> >> (start [this] (defmethod handle-command :export-query [[_]] >> >> >> (export-query db pdf-generator))..) >> >> >> >> >> >> and so on. >> >> >> >> >> >> Fundamentally my question is one of dispatching where the target of >> >> >> the dispatch requires collaborators that aren't part of the dispatch >> >> >> payload. >> >> >> >> >> >> Does that clarify? >> >> >> >> >> >> On 25 February 2015 at 12:11, Jeroen van Dijk >> >> >> <[email protected]> wrote: >> >> >> > I would try to stay away from any nested def's in components (but >> >> >> > also >> >> >> > in >> >> >> > other functions). I'm using component a lot and I never had the >> >> >> > need >> >> >> > for >> >> >> > this. >> >> >> > >> >> >> > Maybe you can elaborate on why you think you need a multimethod >> >> >> > inside >> >> >> > the >> >> >> > component? Maybe a full example? >> >> >> > >> >> >> > Cheers, >> >> >> > Jeroen >> >> >> > >> >> >> > >> >> >> > >> >> >> > On Wed, Feb 25, 2015 at 12:08 PM, Colin Yates >> >> >> > <[email protected]> >> >> >> > wrote: >> >> >> >> >> >> >> >> Hi, >> >> >> >> >> >> >> >> I have a number of commands flying around which need to be >> >> >> >> handled. >> >> >> >> defmulti/defmethod seem a nice answer. The problem is that each >> >> >> >> command >> >> >> >> handler will need different collaborators (those with long >> >> >> >> memories >> >> >> >> will >> >> >> >> realise this isn't new ground here ;)). >> >> >> >> >> >> >> >> I want to do something like: >> >> >> >> >> >> >> >> (ns one) >> >> >> >> (defmulti handle first) >> >> >> >> >> >> >> >> (ns two) >> >> >> >> (defrecord CommandAHandler [collab-1 collab-2] >> >> >> >> component/Lifecycle >> >> >> >> (start [this] >> >> >> >> (defmethod handle :command-a .... >> >> >> >> (collab-1 ...))) >> >> >> >> >> >> >> >> I realise that the lifecycle of defmethod doesn't match the >> >> >> >> component >> >> >> >> (i.e. stopping can't unregister the defmethod), but my main >> >> >> >> reservation >> >> >> >> is >> >> >> >> that a nested defmethod feels a bit weird. Has anyone done >> >> >> >> anything >> >> >> >> like >> >> >> >> this before? >> >> >> >> >> >> >> >> Thanks! >> >> >> >> >> >> >> >> -- >> >> >> >> You received this message because you are subscribed to the >> >> >> >> Google >> >> >> >> Groups "Clojure" group. >> >> >> >> To post to this group, send email to [email protected] >> >> >> >> Note that posts from new members are moderated - please be >> >> >> >> patient >> >> >> >> with >> >> >> >> your first post. >> >> >> >> To unsubscribe from this group, send email to >> >> >> >> [email protected] >> >> >> >> 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 [email protected]. >> >> >> >> For more options, visit https://groups.google.com/d/optout. >> >> >> > >> >> >> > >> >> >> > -- >> >> >> > You received this message because you are subscribed to the Google >> >> >> > Groups "Clojure" group. >> >> >> > To post to this group, send email to [email protected] >> >> >> > Note that posts from new members are moderated - please be patient >> >> >> > with >> >> >> > your >> >> >> > first post. >> >> >> > To unsubscribe from this group, send email to >> >> >> > [email protected] >> >> >> > 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 [email protected]. >> >> >> > For more options, visit https://groups.google.com/d/optout. >> >> >> >> >> >> -- >> >> >> You received this message because you are subscribed to the Google >> >> >> Groups "Clojure" group. >> >> >> To post to this group, send email to [email protected] >> >> >> Note that posts from new members are moderated - please be patient >> >> >> with >> >> >> your first post. >> >> >> To unsubscribe from this group, send email to >> >> >> [email protected] >> >> >> 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 [email protected]. >> >> >> For more options, visit https://groups.google.com/d/optout. >> >> > >> >> > >> >> > -- >> >> > You received this message because you are subscribed to the Google >> >> > Groups "Clojure" group. >> >> > To post to this group, send email to [email protected] >> >> > Note that posts from new members are moderated - please be patient >> >> > with >> >> > your >> >> > first post. >> >> > To unsubscribe from this group, send email to >> >> > [email protected] >> >> > 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 [email protected]. >> >> > For more options, visit https://groups.google.com/d/optout. >> >> >> >> -- >> >> You received this message because you are subscribed to the Google >> >> Groups "Clojure" group. >> >> To post to this group, send email to [email protected] >> >> Note that posts from new members are moderated - please be patient with >> >> your first post. >> >> To unsubscribe from this group, send email to >> >> [email protected] >> >> 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 [email protected]. >> >> For more options, visit https://groups.google.com/d/optout. >> > >> > >> > -- >> > You received this message because you are subscribed to the Google >> > Groups "Clojure" group. >> > To post to this group, send email to [email protected] >> > Note that posts from new members are moderated - please be patient with >> > your >> > first post. >> > To unsubscribe from this group, send email to >> > [email protected] >> > 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 [email protected]. >> > For more options, visit https://groups.google.com/d/optout. >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to [email protected] >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> [email protected] >> 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 [email protected]. >> For more options, visit https://groups.google.com/d/optout. > > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to [email protected] > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > [email protected] > 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 [email protected]. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
