To run across a lake, you only have to do one thing: Run fast. The same is true in software development.
Two years ago, I stood on my soapbox and yelled. I told the FP community that their languages were bad, and that they should feel bad. It was a post full of vitriol and frustration, but also a little bit of truth. I believed then (and still do) that functional languages are a poor solution if what you're looking for is a way to get B grade programmers to build scalable, concurrent systems. After trying to learn Erlang, Haskell, and then Scala, I couldn't see how using those languages was easier that just using separate processes, stitched together with message passing infrastructure, to build systems at scale. And with these thoughts running through my head, I vomited on the Internet. Then Hacker News picked it up.
A lot of people I've met don't use the private function definition in Clojure -- which is
defn- if you've never seen it. They don't see the point, or they think that private functions in Clojure are dynfunctional (pun!). Based on my use of it so far this year, this confuses me, because I think private functions in Clojure are awesome. The reason I think they're awesome is because I write tests for my code, so that I can refactor. Having a clear deliniation between code the that's tested directly and indirectly means I can refactor much more quickly.
When you're looking for ways to refactor code, you can use your fingers, or you can use your eyes. Refactoring with your fingers is nice. When you have a continuous test runner, running a suite of tests on each change, you can refactor pretty quickly. But refactoring with your eyes is much, much faster. Being able to see possible refactorings and think through them in your head is a much faster way to reason about how to clean up code.
If most of your functions are private, you can refactor with your eyes before you refactor with your hands. Unless you've been doing something dumb like subverting access controls to invoke private functions, you know that all of your private functions can be changed, inlined, extracted, and generally recombobulated without fear of breaking a test or messing with another module. This frees up your mind to think about the code that's right in front of you, rather than worrying about the other code that might be calling it.
The public functions, on the other hand, are expensive to change. You will probably break some clients. You probably break tests. All of this will require a lot of work that, essentially, adds no value on it's own. That's not to say that you shouldn't refactor public functions, of course. It's just that the costs are potentially higher. And I find that too many public functions in a module create a slight reluctance to refactor. A pause in thinking, if you will, that I'd rather do without.
So I love private Clojure functions. They're just new a way to implement an old-fashioned idea: Encapsulation. Clearly dividing my clojure modules into public (more expensive to change) and private (less expensive to change) has worked out very well for me. If you haven't tried it, I suggest that you do.
Unless, of course, you're not writing tests...in which case I have nothing for you!