I think that there is something more fundamental underneath this experience report that is worth remarking upon but that isn’t mentioned in the article.
If I were going to give you a quick summary of what our codebase is like, I’d say it’s procedural code that manipulates maps.
One thing we do use more extensively are multimethods. We use this to dispatch asynchronous jobs in our workers, to fan out to different handlers from webhook endpoints, and to make transitions in our deploy finite state machine.
… sometimes you find yourself boxed into writing non-idiomatic Clojure. A good example of such a situation is dealing with a morass of heterogenous functions that can return error codes.
Languages based on different paradigms excel in different situations. Lisp-like languages such as Clojure (and, more generally, functional languages), have abstractions perhaps most well suited to “pipeline” situations - take an input, apply transforms A, B, C, … in sequence until the output is returns, bailing out if there is an error in some stage. Multimethods, which the post mentions, are a good example of this: given input X, send it off to Y based on some conditions. In software applications which have to do this sort of work, it’s a good fit.
If there is complex state to be managed under many different conditions, however, these paradigms can be cumbersome to deal with.
It is unclear to me if the category theory would still be a win on a less experienced team. I have a long history of being skeptical of things like this, but it has improved our lives recently.
The author mentions realizing that the Either monad well embodied the nature of the algorithms being implemented. Speaking from my own experience, I would suggest that teaching a team implementing the sort of software it seems the author’s team was implementing would be a worthwhile investment - but only if it was reasonably clear beforehand that those abstractions would be well suited to the problem at hand.
Perhaps the most important skill to train a team up on, in my opinion, is the ability to recognize the type of problem at hand well enough to see what abstractions would be well suited to it and thus what language to use. In other words: it is very important to choose your tools well.
If I could offer some advice to the author (and others in similar positions) regarding the question of investing time in training a team in any set of abstractions, be it concepts in category theory for the sake of Clojure or something else, it would be this: analyze the nature of the problem at hand, make a decision on what tool (language, framework, whatever) you feel would be best suited, familiarize yourself with its world if you haven’t already, and then have a meeting with your team in which you concisely explain that analysis and the reason behind your decision. Mention why other choices would not be as well suited, but, CRUCIALLY, also give examples of situations in which the other tools you considered would have been the best solution. If you have and reservations about your choice, explicitly state them. (In fact, you may be surprised by someone on the team having had experience in the domain at hand but not having mentioned it because it hadn’t become relevant yet!)
This will not only teach the reasoning process but also give the team some information about what alternate approaches to consider when faced with a problem unlike the ones they have seen before, especially if the team is junior.
Furthermore, sometimes one discovers that the nature of the problem being worked on is, in fact, different from what it was originally understood as. It is a lot to place on one lead to always be vigilant about that, and self-doubt can creep in. If you transparently expose your thought processes to your team, you may find yourself surprised by eventually having a team member saying to you, “don’t you think that this other tool/approach you had considered may actually be better suited to now”?
It is a lead’s job to lead, but it is also to share as much of their knowledge, experience, and reasoning process as possible with the team. Sometimes we go down the wrong route at first, but everyone on a team should understand the why and what of every point along the way. As a lead, I make it my goal to train everyone under me well enough to replace me and to feel comfortable enough to voice any commentary on the decisions I have made.
I was going to go on, but I think I went off on a bit of a tangent. I’ll leave off here.