Always Be Debugging
Here’s what one of the most influential people in computer scientist has to say about debugging:
If debugging is the process of removing bugs, then programming must be the process of putting them in. — Edsger W. Dijkstra
I’m not sure if he actually said that, but we’ll pretend that he did. What if instead of just programming we were constantly debugging at the same time? That’s the promise of static types with static analysis, but what about nasty runtime things like nulls or I/O? How can we still maintain that everything is working correctly in the program? Monads? Maybe? What about just constantly running code and constantly debugging it, seems like a lot less work and simpler than any contravariant functors.
Immutable everything, homoiconic syntax, yuge core library, a repl… clojure has it all and it helps you write less code with less bugs.
So the first thing you do when you’re programming clojure is you open up a repl, a read-eval-print-loop, right when you start. In fact you don’t even change any text until the repl is open, you can but that defeats the purpose of always be debugging. The clojure workflow is insanely productive compared to everything else I’ve programmed in. Write a function, test it in the repl, write a real test or a test.check test and move on to the next function. The idea of going from text you just typed to testing it out as fast as you can move your cursor to the repl window feels like the future, but it’s here in the present.
Here’s a quick, one minute screencast of me showing off the always be debugging workflow just in case you weren’t convinced. It’s a very quick demo of what the clojure workflow is like, write a function, send the function to the repl, test the function with some input, see it working, move on. It works for any size function with any input and any output, even if the input is a file or an http request and the output is bytes or something, you can still test all of it at the repl.