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.
