I’ve taken a few solid swings at picking up Clojure, but something just never quite clicked.
I like the idea of it. I like the pitch of it. It very much tickles my engineering fancy. But I never got to that productive, smooth place.
Then a few years ago it hit me: the thing getting in the way wasn’t Clojure. It was me.
Since then I’ve seen the same pattern pop up throughout programming. And now I’m seeing it in our use of AI.
Go is a very productive system. If you’re working in it’s preferred bailiwick1.
The language holds you back from certain approaches, and is optimised for others. If your use case fits then great. But once it doesn’t fit so well, you’re stuck.
Building a server or data product - fantastic, enjoy the productivity! If you suddenly want dynamic meta-programming — go fish, it’s not going to give you that.
This restriction is intentional. Go’s philosophy is to enable you to do what you need to do quickly, but within clear boundaries. It knows what it is and what it isn’t.
Clojure sits on the other end of the spectrum. Its philosophy is “don’t restrict me, man!” - to let you do whatever you need to do, as fast and flexibly as possible. It doesn’t impose a predetermined structure or workflow on you.
But, it expects you to set up your own workflow, application structure, and frameworks. This flexibility is powerful, but the responsibility is on you to choose and enforce how your codebase will be organized and how your team will collaborate.
That was my mistake. I jumped in. Used my meagre left-over hours from my job and tried to ‘get something working’. Disappoint was my reward.
JavaScript is awful. JavaScript is great. Until you build your app you won’t know which you get.
Love it or hate it, JavaScript is a very important language. It’s been optimised for decades, it can be quite fast, and it fits everywhere.
But it can be good and it can be terrible. Its flexibility can get you into trouble. Import a package and watch as its 1000 friends come along for the ride. You can easily mess with global namespaces if you’re not careful. I won’t even go into it’s … unique management of numbers.
I remember the days when our build scripts were basically concatenating files, and a single colon in some other file took down an entirely different part of our website. Why? Because it happened to come afterwards in the alphabet. Admin worked fine, checkout didn’t.
That was a fun one to debug.
The solution that all JavaScript projects eventually find (if they survive this phase) is to impose discipline. Linters are added. Formatters configured. Static analysis. Code review workflows. Integration tests. Patching your million+ dependencies. Removing dependencies.
The engineering teams have to choose and impose their own discipline.
That’s the thing about these flexible systems. You’re very productive—but only if you’re disciplined. If you’re not disciplined, you’re going to get stuck.
AI coding assistants are extremely flexible. That flexibility is powerful and seductive.
If you let it do whatever it wants, you’ve suddenly got files all over your file system, it’s set up Docker containers and deleted other ones. Maybe it got everything right. Maybe it made an absolute mess.
You can tell it to fix the tests and then — what just happened to me a few days ago — it can go and delete the failing tests. It’s ridiculous, but you have to have the discipline to watch out and enforce your quality bar on it.
You can click the big button to say “go build the whole thing”. But you probably shouldn’t. You should probably sit there for however long it takes and just make sure the spec is right. To figure out how to test the feature and make sure you’ve thought through how it’s going to be hosted, scaled and what domains are going to be needed and all those little things.
It’s very tantalising to hit the button and go, “Yay, AI, build, build, build. Ooh, look how fast it’s typing, typing, typing.”
But you really need to discipline all of that. And what we all have to learn is what the right point is to say, “Yep, go build”. And when it’s right to hold back.
The pattern is the same whether you’re working with Clojure, JavaScript, AI coding assistants, or any other flexible tool. The flexibility is a powerful feature, but only if you’re willing to apply the discipline required to harness it effectively.
The more flexibility you have, the more discipline you need. You have to pick your poison, and then commit to making it work.
Need help integrating AI tools into your processes? Developing the right kinds of discipline within your team? Making architectural choices to support growth and quality?
I help engineering teams with these decisions. Learn more about my software architecture consulting practice.
Feel free to mail me at barry@barryhennessy.com any time.
noun
somebody’s particular area of responsibility or interest ↩︎