Keeping functional code organized

This is an episode of Thoughts on Functional Programming, a podcast by Eric Normand.

Subscribe: RSSApple PodcastsGoogle PlayOvercast

People ask me how to keep functional code organized. It's a good question but my answer is so simple, it feels kind of silly saying it: I keep everything in one file, and split it up as it grows.

Transcript

Eric Normand: How do you keep functional code organized? Hi, my name is Eric Normand, and these are my thoughts on functional programming. I've heard this question before quite a number of times. It's how do you organize your functional code?

It's a valid question. As you start getting more code, you want it to stay clean and organized. You want to have a place for everything and know where to find it. The question is a good one. What I struggle with is why it seems to be such a problem in general that you would think to ask the question.

Here's what I mean. This is what I do. I usually keep my code in one module until it gets too big. I split it into two, or sometimes three, or more. Usually it's just, split it in half. What's the stuff that's most related that coheres the best? Put that in one place. Stuff that coheres with other stuff, put that in another place.

Just make sure that there's no circular dependencies. Usually, the dependencies and the coherence go together. Meaning, if function A depends on B and B depends on C and C depends on D, those look like they're related.

If you have something that doesn't depend on that, that chain of dependencies, it's probably something to go somewhere else. Look at the dependencies, also look at the semantics of it. These functions all have to do with users, and these functions all have to do with HTTP requests, whatever domain you're dealing with.

Usually, I don't even start organizing until it gets big. I think one thing that makes people ask this question is that, in object-oriented programming, there is a default file that something goes in, which is usually about one class per file.

Some languages require that, but it's a convention that a class gets its own file. You know where a method goes. It goes in the file for that class. Of course, what that means is you have a big mess of classes. You move the mess from the function level, like methods, to the class level.

What you should be doing is thinking of your organizational unit. Now, your organizational unit is the class. In something like Clojure or Haskell, it's the modules.

In Clojure, we call them namespaces, or libes if you like to be precise. A libe is just a file that has a namespace declaration at the top. No one calls them that but that's technically what they're called.

In Haskell, we've modules. Other languages have similar units. You just start breaking stuff up. It doesn't have to be more complex than that. Maybe because the answer seems so simple and straightforward, people think there must be something more to it.

To me, it's like drawers. It's like junk drawers. This drawer I put my utensils, and this drawer I put my towels, and this drawer...this is my sock drawer. I have something like a miscellaneous tools drawer. Usually happens in a project, you have a utilities library. I don't have some magic formula except things that go together should stay together.

I hope that helps. It's a common enough question that I wanted to address it, even though I don't feel like I have a super amazing answer to it.

Just don't sweat it until you need to start organizing. Usually around 100, maybe 200 lines, I start to think, "This thing, I can't find anything or I can't figure out what this namespace is all about." Maybe it's about a couple things. Maybe it's about five things. That's when I start breaking it up.

That's it. If you follow that...if it never becomes enough of a problem that you have to do real hard thinking, that's the goal. In theory, if you're publishing this library, and it's going to be used by a lot of people, you want to save them time, make it easy to find things, you're going to put in a lot of hard work thinking, "What is the purpose of this namespace?"

Just like if you're designing a supermarket, you want to put stuff that goes together, together. You put the pasta sauce next to the pasta. You put all the meats together and you put all the fruits and veggies together. It's just so that someone who walks in for the first time can figure out where to go.

That's what we do, except think about it more like for a personal project or a project that your company where the general cases...that's it's not new people coming to your software, to your code. It's people who can invest time and learning about the thing.

It's not so important that it is immediately obvious where things are. It's not. Just like when you're at home, you don't organize stuff by category as much as you organize it by...With your food, if we're going to stick with that metaphor, you put the cold stuff in the fridge, and you put the non-perishable stuff in a cabinet.

It's a different way of organizing. You don't mind so much if the milk is next to the mayonnaise, even though they're not...you wouldn't find the milk next to the mayonnaise in the supermarket.

OK, let me know your thoughts. Am I over simplifying this thing? Is there anything I'm missing? Is this question something that you think about as a functional programmer? What do you do? I'd love to hear all these things.

You can reach me on Twitter. I'm @ericnormand. You can also email me eric@lispcast.com. Recently, I've been much better at email than Twitter. [laughs] I'm getting lots of tweets recently. If I don't respond to you on Twitter, try my email. All right, see you later. Bye.