I’ve been doing some radically different design after creating Dire a couple of months ago. My stance on local exception handling departs from what almost anyone else is doing right now - and there’s been some interesting repercussions because of it.
The style of design that I’ve been pushing is one of airtight separation of concerns. Clojure’s runtime capabilities have allowed me to transparently alter control flow for exception handlers, assertions, and hooks. The beauty is that all the machinery to perform the aforementioned logic can be grouped into their own files - and loaded only when you want them. It’s like dependency injection at a far more flexible level.
After a few weeks of applying these concepts to a larger code base, I’m noticing an interesting phenomena at the code level. Rich Hickey noted that design is about taking the problem apart as much as possible. My conjecture is that when you’re aggressive about dismantling the problem space, the code in each module will display similar visual characteristics.
Here are excerpts of some files in the (closed source) project I’m working on. I unimaginatively changed the functions to be about cows and chickens - but you get the point. We’re concerned about structural appearance - not what the code actually does.
This first one is a file whose only concern in the world is logging. Notice how all the forms pretty much look the same.
Here’s a bit of a file whose only concern is reacting to thrown exceptions. They all look pretty similar!
Yet another instance - a file whose only job is to strip information off incoming API requests and pass them along for further destructuring:
Last example. All of the Datomic queries get their own file:
All of the functions in each file are participating at the same level of abstraction, and hence look roughly the same. There’s no surprise conditionals or loops any of them. They all flow together, and can be reasoned about with ease. This is a serious reduction in cognitive complexity.
If I could make an analogy, it’s a bit like a pipe organ. All of the pipes have roughly the same shape, but some of them are of different length and width. The groups of pipes correspond to the Clojure files. Each pipe represents a function. Very similar to those around it, but just a little different to make it useful.
Keep in mind, these were excerpts from a few files in a much larger project. I’m having a blast with this code base, and I think what I’ve pointed out is a green light that the design is solid.
To summarize, my conjecture is this: Thoughtful abstractions in design will lead to code that is visually similar in each module. If you notice this in your code base, you’re probably doing a great job with the design.
Hit me up at @MichaelDrogalis with your thoughts. (It’s a conjecture - I could be totally wrong!)
Also, give Dire a try for logging in your system. I’m a little biased since I’m the author!