On Thursday, December 13, 2012 11:43:48 PM UTC+2, puzzler wrote:
>
> On Thu, Dec 13, 2012 at 1:31 PM, Timo Mihaljov 
> <ti...@mihaljov.info<javascript:>
> > wrote:
>
>> (ns example.patron
>>   "The patron doesn't have an artistic vision (that's the artist's job),
>> nor does it know how to talk to a graphics API (that's what the canvases
>> are for). What it *does* know is how many triangles and squares we can
>> afford, and where we want them drawn."
>>   (:require [example.artist :refer [create-masterpiece]
>>              example.canvas :refer [make-canvas]]))
>>
>> (defn commision-a-masterpiece []
>>   (create-masterpiece (make-canvas) 500 1000))
>>
>
> I like this idea of using multimethods to send information from the 
> concrete implementations back to the constructor in the core.
>
> But how do the concrete implementations ever get loaded?
>
> For example, if you start an empty repl and send the example.patron file 
> to the repl, none of the concrete implementations will get loaded, so 
> make-canvas will fail.  Same thing if, for example, you made 
> commission-a-masterpiece into the "main" function and compiled the whole 
> thing into an executable jar.
>
> How do you get around this?
>

You are right, I didn't think this through.

Frankly, after sleeping over it, I think that the multimethod trick wasn't 
a good idea. If your users know which implementation they want, they can 
just as well instantiate it themselves. And if the factory contains some 
logic for choosing the correct implementation, it necessarily operates on a 
closed set of implementations, and shouldn't live in a namespace that's all 
about the *protocol* and thus about *all the implementations*.

I think that the difficulty of partitioning code into namespaces is a 
design smell warning us of conflated responsibilities. The powerful 
namespace wrangling tools, such as immigrate, deal with the symptoms and 
not the cause. We should strive to have cohesive namespaces with clear 
acyclic dependencies, and we can reach that goal by applying the Single 
Responsibility Principle to namespace design. Here's another stab at the 
namespace partitioning, this time without a factory function and assuming 
there's a need for automatic, intelligent selection of a protocol 
implementation.

- canvas: Protocol definition, functions that operate on any protocol 
implementation. No dependencies.
- svg-canvas: Protocol implementation. Depends on canvas.
- png-canvas: Protocol implementation. Depends on canvas.
- canvas-selection: Automatic selection of a canvas from a known, closed 
set of canvases. Depends on svg-canvas and png-canvas.
- artist: Draws pictures. Depends on canvas.
- patron: Commisions pictures from the artist. Depends on artist. May 
depend on either canvas-selection or one of the concrete canvas 
implementations.

With this architecture there are no cyclic dependencies, and the users are 
free to choose between automatic canvas selection, one of the predefined 
canvas implementations, or a canvas implementation of their own.

--
Timo

-- 
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

Reply via email to