About Functional Web Architecture (with Ring and Compojure) by James Reeves

SkillsMatter has published the Functional Web Architecture talk by James Reeves some time ago, but it was only today when I found a few spare cycles to sink into it. I’ve been working with Ring for quite some time yet explaining how handlers/middleware work has never been easy.

James speaks about Ring’s handlers and middleware, and eventually Compojure in this podcast and explains it so well that I hardly imagine anyone else could do it better. His regular, calm speaking style makes the hard pieces so easy to comprehend. You should definitely watch it if you haven’t yet. Or do it again, if you have, but don’t think the podcast deserves attention.

Ring aside, I could once more learn how important the macros clojure.core/and and clojure.core/or are. I once wrote a blog post here – Single pull request can make a difference in your learning of Clojure – to make my appreciation heard. I’m still amazed how much simpler a function can become with these two macros. When I saw the slide at around 16:00 with the middleware wrap-cache and the or macro, it was when I realized I should really get my teeth into them! They’re very simple yet highly powerful in their approach to smooth functions once applied. That’s the role of macros after all, isn’t it?

At around 17:40 James presented the wrap-content-type middleware (a higher-order function) that’s almost what I meant once to write (!) I needed a routing macro (should I say “content negotitation”?) to have JSON requests be specially handled than HTML ones. I think I should expect it available in Compojure, and James mentioned a thing similar to it. I should have a look at Compojure’s source to check out whether or not it’s already available.

But I couldn’t understand why the wrap-content-type middleware uses the threading macro -> in the body of let, but not for the bindings. Wouldn’t it be nicer to have the function looked like this?

(defn wrap-content-type [handler]
  (fn [request]
    (let [ext (-> request :uri get-ext)
          type (-> ext ext-types)
      (-> request
          (content-type type)))))

Perhaps I shouldn’t use (-> ext ext-types) as a replacement for (ext-types ext), but the other places look nicer, don’t they? May I say “more idiomatic”?

During the talk I also learnt about the compojure.core/context macro. That just highlighted the fact that I should’ve been studied the compojure.core namespace more closely in the first place and it should be the very first step when any other library is in use. I’ll keep that in mind next time I jump into a library. I sort of do it with new languages when I read books first and then do a project, but it’s not the regular approach to Clojure libraries. I think I once did that for Enlive and however I had troubles to understand all concepts so much that my brain almost melt down, it ultimately was time very well spent.

James shared more ideas in his talk, but I’m not going to describe them all here as it would surely spoil the talk. I appreciate James’ efforts to explain Ring and Compojure so well and in such a short time. Thank you, James! I wholeheartedly recommend the talk.


Be Sociable, Share!
This entry was posted in Languages.

Leave a Reply

%d bloggers like this: