One of my favorite tech talks of all times is Simple Made Easy by Rich Hickey (the founder of the Clojure programming language). In this talk Rich explains the difference between the often confused terms “simple” and “easy” in the domain of software. Simple in this context means that there is no interleaving of different things. Something is simple when it address one concept or task and does not complect with other things. Easy on the other hand means that things are close at hand, something that is familiar to us and that we know how to use. This is important because we as developers often tends to take the easy way out instead of trying to build simple software that can continue to grow as time and requirements progress. Focusing more on simplicity may not get us started as quickly but in the long run we’ll get benefits of a more comprehensible and maintainable system.
Clojure and Spring
In my day job I’m mainly developing server-side Java but since we’re decomposing our system into smaller parts (microservices if you will) I’ve had the chance to use Clojure in several (smaller) projects. If you’re doing server-side Java chances are quite high that you’re using the Spring or Spring Boot framework in one way or the other. Spring is more or less the goto framework for me and many of my colleagues when it comes to building services in Java. So when creating my first real service in Clojure I really did miss the speed (easiness) that Spring Boot provided me in Java. I had to do quite a bit of research to put together a set of small libraries that would make up the infrastructure of my Clojure service. I had to do all the plumbing myself. For example find out how to get environ working smoothly with Leiningen in multiple environments, understanding Ring and Compojure, finding out whether I should use friend or buddy, how to expose our admin resources from another port in Jetty etc etc. At this time the component library had not yet seen the light of day so I also had to think quite hard on how to represent and manage the life cycle of my components (and luckily my approach was quite similar to that of component). When it finally came down to writing business code Clojure felt great but the time to get there, by myself, the first time felt long. But on the flip side it felt that I was in control of most things and there was not much magic going on. I was also forced to make thorough investigations of several libraries to compare their pros and cons before deciding to use them. It felt as though I knew my application and what it was doing, it felt.. simple! But from this day I’ve been thinking on and off about a sweet spot (intersection) between simple and easy and what that would actually look like. I’ve also discussed this with colleagues and the term we’ve been using for this is “convenient”.
Convenient Wieldy Code
So today I was happy to come across a great talk by Luke VanderHart called Simplicity in Practice from ClojuTRE 2015 that elaborates on these ideas. Luke suggests the term “wieldy” to describe the sweet spot between simple and easy (but “convenient” still sounds better to me :)). He recognized both the benefits and pitfalls of easy but more interestingly also the potential inconvenience when working with simple code. Wieldy code should be both simple and easy at the same time! In essence this means that we should write software that not only decompose the problem to its constituent parts (simple) but also builds it back up again to make it useful (easy). This is the sweet spot we’re aiming for! You can write both simple and easy code that is unwieldy and it’s very hard to come up with a perfect solution.
Another thing that Luke talks about is how “wieldy” also applies to documentation. In the context of documentation the reference manual can be seen as simple (it’s terce, complete with “no context”), a tutorial is easy (it’s task oriented, longform and concepts are doled out on demand), and a “conceptual documentation” (that targets a problem in a given context including the concepts and links to reference docs for further reading) is wieldy.
Back to Spring
When I think about a good example of “wieldy” what comes to mind is (at least parts of) the Spring framework. Let’s start with the documentation. Spring provides excellent guides to solve specific use cases using various parts of the framework. To me this almost perfectly resembles what Luke calls wieldy documentation. Spring also accompany their guides with great reference manuals and in-depth tutorials. I’ve not come across an open source framework with better documentation than Spring. When it comes to the actual framework Spring has a great deal of magic, especially when it comes to Spring Boot (but the magic is well documented). But unlike some other large frameworks, Spring is not an all or nothing solution. Spring supports and integrates with a vast number of services and libraries and you’re in control over which of these you want to use. So from an architectural point of view I do think Spring would qualify as wieldy. Spring also allows you to configure and have control over most of the nitty gritty details if required. In my experience you can never go completely wrong when building your application with Spring as the foundation. If the opinionated approach taken by Spring Boot doesn’t suit or fit your needs you’re free to use spring-core or any other spring components as you find fit.
Back to Clojure
The Clojure community is notoriously famous for its focus on simplicity but I tend to see efforts in the “wieldy space” here as well. Nowadays we have for example frameworks like Duct that takes care of much of the plumbing I had to do manually when starting out. It combines well-known libraries such as component, leiningen, compojure and environ which allows us to kick-start a new project faster with sensible defaults. It aligns with Luke’s definition of wieldy in that it combines smaller libraries and brings something to the user that is more easy to use.
Good reference documentation similar to the Spring guides is something I find lacking in many Clojure libraries/frameworks I’ve used so far though. I know first hand that documentation is very time consuming and not always something you look forward to writing as an open source developer but it really makes a difference. Some larger projects have good reference documentation and even guides (for example Monger and Langohr) but I’ve struggled with understanding some non-obvious concepts in others.
Domain Driven Design
I can’t avoid making some comments on how I think this relates to domain driven design 🙂 When designing a complex system I would argue that one of the most important things is to find (at least the obvious) subdomains of your system. By decomposing the system along these subdomains you’ll probably end up with a number of smaller services that are easier to reason about and which ultimately makes up your entire system composed of these smaller parts. By doing this right I believe it’s actually possible to build a complex yet maintainable system based on several “easy” services. It doesn’t have to be micro services, a monolith is just fine, but getting the boundaries right is what’s most important. Of course thinking of simplicity and “wieldiness” on the inside of a bounded context will improve things but even more importantly is to find these contexts in the first place.
Rich Hickey made us think about simplicity which was and still is much needed in our industry. The Clojure community has adopted this wholeheartedly but I get the feeling that the “wieldiness” aspects sometimes have been a bit neglected. More wieldy libraries and frameworks would make it easier to persuade people to pick up Clojure, or any language/community for that matter.
2 thoughts on “Reflections on Software Simplicity”