[ANN] modularity.org

522 views
Skip to first unread message

Malcolm Sparks

unread,
Jan 8, 2015, 9:42:12 AM1/8/15
to clo...@googlegroups.com
I've created a new website to help new Clojure developers get started with Clojure and specifically with Stuart Sierra's component/reloaded-workflow pattern. 

On http://modularity.org you can find documentation about modular. Modular comprises :-

- a set of pre-written components
- a template system for creating new projects
- some optional utility libraries

There are also full instructions for creating new Clojure projects that are based on component, which involves typing the following :-

$ lein new modular <project-name> <template> 

where <template> is one of a number listed on the site here: http://modularity.org/docs.html

Don't expect everything to work perfectly yet, and please help if you can by suggesting improvements to make this easier for new Clojure developers.

Thanks,

Malcolm

PS: There is a Google group mailing list 'modularity'. If you want to get more involved with this project, please join the list.

Torsten Uhlmann

unread,
Jan 8, 2015, 9:52:38 AM1/8/15
to clo...@googlegroups.com
Awesome, thank you!

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
AGYNAMIX(R). Passionate Software.
Inh. Torsten Uhlmann | Buchenweg 5 | 09380 Thalheim
Phone:     +49 3721 273445
Fax:         +49 3721 273446
Mobile:     +49 151 12412427
Web:        http://www.agynamix.de

James Reeves

unread,
Jan 8, 2015, 9:55:44 AM1/8/15
to clo...@googlegroups.com
Out of curiosity, does Modular have a mechanism for abstracting groups of Ring routes?

I'm wondering how much work can be shared between Modular and other projects, such as my own Duct template, which has similar ideas.

- James

--

Malcolm Sparks

unread,
Jan 8, 2015, 10:10:25 AM1/8/15
to clo...@googlegroups.com
Hi James,

Yes. The idea here is that you want individual components to be able to 'contribute' groups of routes. That way, you can avoid the common practice of having one big 'god' namespace containing all the Ring routes, which is then tightly coupled to all your Ring handlers. Instead, it's nice to have the flexibility to compose systems from different combinations of components.

One implementation approach is to have a 'router' component that delegates to its dependencies. That way, routes can be 'plugged in' using dependency declarations. 

Currently I only implemented this with bidi, which I'm slightly biased towards (because I wrote it). My 'router' implementation is here: https://github.com/juxt/modular/blob/master/modules/bidi/src/modular/bidi.clj

But I have been meaning to add a Compojure equivalent, just haven't yet done so.

Is this what you mean? If so, does Duct implement a similar pattern or does it do things differently?

Also, I'm hoping that many of these pre-written components will be compatible with each other. For example, modular components are compatible with Daniel Szmulewicz's 'system' https://github.com/danielsz/system, and vice versa. 





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/YP_VM6Zf4RQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

James Reeves

unread,
Jan 9, 2015, 11:34:05 AM1/9/15
to clo...@googlegroups.com, Malcolm Sparks
On 8 January 2015 at 15:10, Malcolm Sparks <mal...@juxt.pro> wrote:
The idea here is that you want individual components to be able to 'contribute' groups of routes. That way, you can avoid the common practice of having one big 'god' namespace containing all the Ring routes, which is then tightly coupled to all your Ring handlers. Instead, it's nice to have the flexibility to compose systems from different combinations of components.

One implementation approach is to have a 'router' component that delegates to its dependencies. That way, routes can be 'plugged in' using dependency declarations. 

Currently I only implemented this with bidi, which I'm slightly biased towards (because I wrote it). My 'router' implementation is here: https://github.com/juxt/modular/blob/master/modules/bidi/src/modular/bidi.clj

That's an interesting setup. Are you merging the data-driven bidi routes together?

If I may, let me run past you an idea I've been experimenting with that has a similar goal.

I've been using functions that take in a configuration map (in practice, a component) and return a handler. I call these "endpoints" (highly original, I know).

  (defn hello-endpoint [config]
    (fn [request]
      {:status  200
       :headers {"Content-Type" "text/plain"}
       :body    "Hello World"}))

Wrapping endpoints in a component is relatively straightforward:

In Duct, the template/framework I'm designing, I use the Compojure mechanism of trying endpoints in turn until one returns a non-nil value. However, one could quite easily write a routing mechanism that dispatches on a context path, or a regular expression.

This approach is pretty minimal, but has a few advantages:
  1. It's not tied to a particular routing library
  2. It's a simple interface
  3. Configuration is passed down via a closure & destructuring
As a more practical example, consider an endpoint that relies on a database connection:

  (defn product-endpoint [{db :db}]
    (routes
     (GET  "/" []        (list-products db)
     (POST "/" [product] (add-product db product))
     (GET  "/:id" [id]   (find-product db id))))

When we come to write our system, we wrap the endpoint in a component, and have it depend upon the database component:

  (defn new-system [config]
    (-> (component/system-map
         :db      (database (:db config))
         :product (endpoint-component product-endpoint))
        (component/system-using
         {:product [:db]}))

(In the above example I've omitted the component that combines all the endpoints together into a handler, as I think that's a more opinionated component.)

Do you think this "endpoint" approach could work in Modular? I like the idea of having a standard way of defining a subset of routes that depend on a configuration.

- James

Malcolm Sparks

unread,
Jan 12, 2015, 8:13:34 PM1/12/15
to clo...@googlegroups.com, mal...@juxt.pro, ja...@booleanknot.com
Hi James,

If I understand your pattern correctly, you assoc a :routes entry to each component that contains routes. Then your router component depends on these components, selecting those that have a :routes key, and call each :routes value function in turn until one return a non-nil Ring response.?

I think the two approaches share the same essential design.

First, the db (or anything else) is injected via the closure's lexical scope, which I think is one of the nicest aspects of the component pattern (compared with alternative approaches listed here http://stuartsierra.com/2013/03/29/perils-of-dynamic-scope)

The component-with-routes-to-try is 'marked' as such by having a :routes key. With my bidi-based design I similarly 'mark' a component, but with a protocol (modular.bidi.WebService). Essentially bidi works the same way as Compojure - rather than calling functions, it keeps trying to match patterns until it gets one that returns a non-nil map.

Aside: The reason I mark components with a protocol is because I need the component to provide two maps - one from routes to keywords, the other from keywords to handlers. This is not a core bidi idea, but something extra I've built on top by extending bidi's protocols in modular.bidi, which has to do with wanting the option of url formation (from the keyword back to the path). I'm not yet sure if this is the right design.

In summary, yes, I think that the endpoint-component approach would work very well with Modular and having a Compojure router component (together with the endpoint-component function/pattern) would be very valuable.

Regards,

Malcolm
Reply all
Reply to author
Forward
0 new messages