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