I love the quick feedback when working with Figwheel. I have my editor on the left and a browser on the right. After saving a file (which is one action which I have to do anyway) I see the result.
But when working on server code I have to do a lot more “actions” in my editor. I feel I am missing something.
Example: I have a namespace with some functions. The purpose of the namespace is to parse XML and build a map (EDN). The functions extract data, merge data and create a hierachy. To eval individual functions I need test data, so I create a comment with clojure code for laoding an XML file and calls to my functions.
Then I eval my namespace and then the functions from inside my “Rich” comments.
Now I fix a bug in my functions and would like to see the effects as soon as possible. But I have to eval the namespace (or the fixed function) and then navigate to my comments and eval the test code. Then navigate back to my function I am working on and so forth.
An alternative I tried is to put my test code to the bottom of my clojure file (not in an comment) and to eval the whole buffer after saving the file. This gets rid of jumping in code all the time, but it happened a few times, that I have commited my test code.
What workflow are you using? Is there a way to get feedback immediately after saving the file?
On the function level I’ve converged on wrapping my function definition and function call / test code in a do. In production, I want to end up with Rich comments, so that I don’t eval things I don’t want to. Especially when there are side effects involved.
I’m doing this for practically any pure function I’m developing.
On the system level, you’ll want to be able to reload parts of your system that you’ve changed. A simple way to do this is to take care that you can use “function redefinition” to refresh your system. Check out the HTTP-kit docs for an example. Principle: ensure that redefining the functions you’re using will actually change your system.
When you want to do this across your whole system, you might want to use something like Integrant . Integrant makes it simple to write you application as a reloadable system. Bonus: it understands which source files are in use, and is able to refresh only the files you’ve changed, and deduce which parts of the system must be reloaded. But you probably want to understand the basics by messing around a bit yourself before you come here.
Hope that helps! I have pondered the same question myself.
I write a (def-bindscript ...) with test code directly after my functions. The idea is that for production, the macro yields nothing while in development mode it evaluates all expressions and renders the output in the browser live via Figwheel. Therefor a simple save is enough.
I would like to make it work for server code too, by serializing the output and sending it to the browser.
But there is a lot to fix in bindscript - and I hope for a more lightweigt solution.
Hum… I normally put REPL code at the bottom of the file as the last thing, and wrapped inside a #_ and a do.
Now normally I run eval buffer followed by go to end of file and followed by eval last s-exp. Even though the prior sexp is wrapped inside a #_ cider is smart enough to eval what’s inside it. From my Spacemac in Holy mode (and some of my own bindings) it goes:
M-Enter s b M-> C-Enter
This will eval the buffer, go to the end of file, eval the last s-exp, which is a big do of all my repl only code wrapped inside a #_.
I wonder if in your case, you wouldn’t prefer to just setup a test runner that runs on save?
First I think some comment can be committed, those show case for Usage, putting in a well formatted bottom comment block of file.
Second for the testing purpose code, put them in correspond test namespace, that is foo.bar-test for foo.bar. Then CIDER have a command called cider-run-ns-tests, this will execute test code in the correspond test namespace. There’s also a command called cider-eval-last-sexp-and-replace, sometimes it’s useful for writing tests.
PS. There’s an option called clojure-toplevel-inside-comment-form, set it to t so that you can use C-c C-c to execute code in comment block.
I tend to have Rich Comment Forms directly after each function that I feel I need to test, which avoids quite a bit of back and forth navigation. I also have a hot key that takes a let binding pair (symbol/expression) and does a global def of it, so I can more easily eval code inside a function definition directly without needing an RCF (all I need is defs for sample argument vars).
Another option, which I have not yet used but I consider from time to time is to use clojure.test's with-test function which lets you do this:
Which, at least in Calva, lets me Run current test with the cursor anywhere within the defn form, so there is no moving around the cursor at all in order to test whatever change I’ve made. And when I’m done I decide if I want to leave some tests with the function. (I often decide to do that.)
Most often I will leave the tests in the code. But, the full story is that I usually experiment in a comment block quite a while before my functions take any shape that I am ready to write tests for. So when I do add the tests they are most often intended to stay there.
(I often commit code with some of the comment form experiments left there as well, btw.)
+1 on the use of do, especially if there are several forms that need to be evaluated each time. I also typically start any given function as a top level let with bindings that match what the function’s arguments will be, do all my work in that context, then change the let to a defn when I’m done.
I want to reinforce the suggestion of @bbatsov about leveraging tests for this. That’s where my example code goes and with cider-auto-test I get my test re-tried if ever I C-c C-k evaluate the buffer. There are a couple handy helps here:
C-c C-t C-p : run all project tests. Usually what I do when I get back to a project for the first time in a while. Occasionally instead use C-c C-t n to only run tests for one namespace.
C-c C-t t: Run the test at cursor, once I’ve located which test I want to run from step 1.
C-c C-t g: Re-run whichever of my previously run tests failed. Execute this while in my actual src namespace, not in a testing namespace, and keep at it until my test is passing.
These are the three I use most right now, and they work quite well. The advantages of this are several:
Tests won’t cause issues when you deploy, so you avoid the problem you mentioned with test-code getting deployed
They persist as documentation and regression tests; my “repl” code is no longer single-use and can give example to future-me or other developers on the project of how things should be used/tested
In other words, it gets rid of the major problems of accidents and extemporaneousness of normal in-buffer-REPL-code and, thanks to Cider, is not really slower (particularly in the long-run). As someone who has previously done a lot of re-writing of the very same repl code for debugging later in the week and month, this is great.
For me, the most common end point of the process: after you have written your function and verified that it does what you think it should using appropriate sample data (hopefully probing boundary conditions in the process), hoist that code out into a test. I would not start off with the verification code in a different file from the function itself (e.g. in a test namespace), as I’d rather have everything in one place (preferably on the same screen within the buffer) while working out the implementation.
What I most commonly use the comment block at the end of the file for is various interactive tools to be used from within your coding environment (e.g. emacs). Often, after things have settled down, I will factor those tools out into a group of interactive functions in a separate file/namespace called repl.
I like your method and agree with the principle. Because I fluidly use multiple buffers/frames and having them in separate (e.g. testing) namespaces actually works better with that, my process favors never putting them in the same buffer to start with (especially because having a testing ns and Cider’s testing facilities is actually easier for me than scrolling around the same buffer).
In the event that I don’t have the test suite in my last two buffers (in which case I’d just use my version of alt+tab or C-x b to get there), the fastest way I know is to open up the most recent test result report and RET on one of the failing tests. Alternatively, emacs standard C-x ` will take you to the next error (or use cider-next-compilation-error or use an emacs register for static-speed back-and-forth: set register with C-x r SPC DIGIT and jump to it by C-x r j [digit].