Code Reloading in Clojure
I like quick feed back while I’m coding. Instead of ‘playing’ computer in my head, let the code code run and see if it does what I expect it to do. It’s one of the reasons enjoy working in a test first workflow and having a test friendly code base.
Anyway, some things are just easier to ‘tweak’ visually and experiment. For example when working on a GUI code or some REST output. So, I want that changes are immediately available. In Clojure there are different, ready to use solutions to do code reloading. Like Figweel for Clojurescript and web front-ends.
Here I am not going into Figweel and many other solutions. Instead I’m using Clojure facilities, without any special tools. I also take a look at on code reloader: test-referesh
Basics: Reload with use
Assuming we have some piece Clojure code. Like this:
Now, we want to ‘tune’ the email and make it actually a friendly email. So you include it into your REPL and evaluate the result:
Now you did some changes. But when you use the `create-emails` function again, it still prints out the old result. You don’t want to restart, but just reload it and keep going. Well, the ‘use’ macro already has reloading built in. Load the namespace of the file with the :reload
flag:
That’s it. Clojure will reload the code in the namespace for you. Nothing else to do.
Reload more, :reload-all
Maybe the change you made is actually in some dependency. Assume we have this function in another namespace, which refers the the friendly email code:
When you use the ‘preview-email-examples’ function, you might notice that reloading with `(use ‘uses-emails :reload)`, it will not include changes made to the my-friendly-emailer.clj file. Use the :reload-all flag. It also reloads any dependencies:
Automate Reloading, Example REST Server
You can use the ‘use’ primitive easily to create your own reload mechanism. This is useful, when you use Clojure in some embedded scenario or existing of the shelf reloaders do not work.. Let’s extend the given email example to a web service:
This web server is pretty annoying. If we change anything in the email template code, we have to restart it. Wouldn’t it be nice if changes are visible on the next browser refresh. Well, we can hack that our self. We add a developer flag. When that is set, we just go and reload our app’s main namespace.
Then we enable it. In this example just in via the REPL. In a real app the toggle mechanism can be more advanced
Of course, for Ring there is already a reload library (probably even more than one). For example the reload wrapper from ring-devel library.
Using test-refresh
So far we used core Clojure functionality. Based on that you certainly can go deeper and create more elaborate reloading schemes. One of such is test-refresh, a Leiningen plugin. I just add it to my ~/.lein/profiles.clj, so that it is available in any project I touch:
This gives the `lein test-refresh` command. That command will run the test suite. The cool thing now is, that it will rerun tests which are affected by a change. So you get immediate feed back if your edit just broke something. Even better, you just can experiment around, while test-refresh reloads the code, giving you always feed back.
Here a screen series to illustrate that. Or if you have time, checkout this video: Don`t settle for a REPL.
When started, the tests are executed first:
When editing, as soon as you save a file, all tests which depend on that change are executed again
Now, you also just can try code out right there. The results are shown immediatly. Like a free edit REPL:
That also allows you to monitor some high level end result, while changing the lower level functions:
Use test-refresh or your Test Server
Well, you can also use test refresh to reload your server when files change. What I usually do put the server in a separate namespace, with no dependency to my core app. When the file and its dependencies does not change, test-refresh won`t reload it. This means that test refresh does not reload the actual server. Note that the test server exposes an atom for the actual request handler:
Then we add a ‘test setup’ file. That one depends on our application. Since our application changes, and this file depends on it, it will be reloaded as soon as we change anything in our applicaiton. When reloaded, it will swap out the handler of the test server. So, if the app changes, test-reload will do it`s reload logic and we also will have the latest code running in the web server:
This can be done for other server types and setups. Is neat for places where there no pre made plugin or you need a very specific setup.
Keep on reloading
That`s it for today =). Happy reloading. ^.^
- Joyent’s Triton : /native, our friend!
- Fun with Clojure & AWS: A windows box in a Minute