It sounds like it depends on whether the collaborators are properly known
to the command, e.g. at command generation/creation time, or to the
handler, e.g. at handler creation/registration time.

If the former, then it would make sense for each command to be a record
that was created with all required collaborators and participated in a
Handle protocol, called by the gateway.

if the latter, then handlers are simple functions that take collaborators
as initial parameters, followed by a command parameter. Then the bindings
for collaborators are wrapped in a partial prior to registration, so the
gateway calls the registered function with the command map as the single
parameter.

A factor by which to decide- do the collaborators remain the same per
command for the lifetime of the app? If the same, then assigning them every
time a command is created is wasteful, but if different, then assigning per
command is required.

That said, an issue I've run into when using types like this is that the
type distinction required for dispatch is complected with field membership
of the records. When the same fields need to be handled in potentially
different ways, then different command records need to have the same
fields; or when different fields need to be handled the same way, either
different command records dispatch to the same handler, or a single record
contains the union of fields needed for the handler. All of those are
unpleasant, so unless the handler functions neatly map to distinct
collections of fields, just using maps is more appealing.



On Mon, Aug 12, 2013 at 12:05 PM, Colin Yates <colin.ya...@gmail.com> wrote:

> Hi Russell,
>
> Maybe the concrete case will help.  I have a single entry point into which
> Commands can be posted, let's call it a CommandGateway.  This gateway will
> do many things, the least of which will be to delegate the handling of the
> command to the command handler registered with the gateway.  The strategy
> is 'how to handle a command'.
>
> Now, the handler for :command-a needs a database for example.  The handler
> for :command-b needs another collaborator.
>
> CommandGateway has no idea about this and defines a defmulti called
> handle-command which dispatches on the :type of the command (which is
> really a trivial map).
>
> The command handler for :command-a registers a defmethod for :command-a
> but how does the body of that defmethod access the database connection for
> example?
>
> I can see a few options:
>  - give up on avoiding global state and have a bound 'system' register
> (i.e. a global/static service locator) - please no.
>  - don't use multi-methods for this and have CommandGateway have a map of
> predicate:handler.  The handler for command-a would then register itself
> and use lexical scoping to access the required collaborators
>  - use multi-methods, but have a CommandAHandler which is a stateful
> record and retains its collaborators (i.e. the database) and extends itself
> to implement command-handler)
>
> My question is really 'when does using types stop being idiomatic'.  So
> far I have gotten surprisingly far using maps/sequences and passing
> collaborators around.  Now it seems to use multi methods to dispatch the
> command I need the target of the dispatch to be stateful to remember its
> collaborators.
>
> Might all be a storm in a teacup :), hence the clarity request.
>
>
>
> On 12 August 2013 16:50, Russell Mull <russell.m...@gmail.com> wrote:
>
>> Generally, I'd go for a simple strategy (ahem) like this:
>>
>> (defn make-handler [wibblie wooblie]
>>   (fn [woosy]
>>     <eloquent code here>))
>>
>> But perhaps there's something about your case that I don't understand;
>> I'm not entirely sure where multimethods need to come into it, unless you
>> need to change which handler you're using based on the thing it's handling.
>>
>> Russell
>>
>> --
>> --
>> 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 a topic in the
>> Google Groups "Clojure" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/d/topic/clojure/hRKZTclcllQ/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to
>> clojure+unsubscr...@googlegroups.com.
>>
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>>
>>
>
>  --
> --
> 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/groups/opt_out.
>
>
>

-- 
-- 
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/groups/opt_out.

Reply via email to