Jay Fields is a software developer at DRW Trading. He has a passion for discovering and maturing innovative solutions. His most recent work has been in the Domain Specific Language space where he's delivered applications that empowered subject matter experts to write the business rules of the applications. He is also very interested in maturing software design through software testing. Jay is a DZone MVB and is not an employee of DZone and has posted 116 posts at DZone. You can read more from them at their website. View Full User Profile

Agile Development With Clojure

05.24.2012
| 3953 views |
  • submit to reddit
If you've ever spent any time learning Rails then you probably read one of the editions of Agile Web Development with Rails, and if you're like me (skeptical & pedantic) then you probably asked yourself: what the hell does Rails have to do with Agile development? At the time, I assumed that Dave and David were merely capitalizing on the buzz around Agile; however, even if that's the case, I think they did manage to highlight one of my favorite aspects to building websites with Rails: The ability to make a change, reload the page and see the results makes you a much more agile programmer - where 'agile' is defined as: Characterized by quickness, lightness, and ease of movement; nimble

It turns out, it's not very hard to get that same productivity advantage in Clojure as well. I would go so far as to say that the ability to change the server while it's running is assumed if you're using emacs+slime; however, what's not often mentioned is that it's also possible (and trivial) to reload your server code (while it's running) even if you're using IntelliJ, scripts, or anything else.

The majority of the servers I'm working on these days have some type of web UI; therefore, I tie my server side code reloading to a page load. Specifically, each time a websocket is opened the server reloads all of the namespaces that I haven't chosen to ignore. The code below can be found in pretty much every Clojure application that I work on.
(defonce ignored-namespaces (atom #{}))

(defn reload-all []
  (doseq [n (remove (comp @ignored-namespaces ns-name) (all-ns))]
    (require (ns-name n) :reload )))
Like I said, when I open a new websocket, I call (reload-all); however, the (reload-all) fn can be called on any event. When discussing this idea internally at DRW, Joe Walnes pointed out that you could also watch the file system and auto-reload on any changes. That's true, and the important take-away is that you can easily become more productive simply by finding the appropriate hook for what you're working on, and using the code above.

The ignored-namespaces are important for not reloading namespaces that don't ever need to be reloaded (user); other times you'll have a namespace that doesn't behave properly if it's reloaded (e.g. I've found a record + protocol issue in the past, so I don't dynamically reload defrecords in general).

The change-reload webpage-test loop is nice for making changes and seeing the results very quickly - and I strongly prefer it to having to stop and start servers to see new functionality.
Published at DZone with permission of Jay Fields, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Herry Johnson replied on Tue, 2012/06/12 - 12:59pm

It sounds good. I have a related question - how can find out when the setting file has been edited? I can ask every time I access the settings if there was change in lastModified time and if so I reload the setting - but it seems quite inefficient to me.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.