Build an interface around data

Опубликовано: 28 Апрель 2026
на канале: Eric Normand
505
17

►► Audio, Video, and Transcript available: https://lispcast.com/build-an-interfa...

►► Subscribe on iTunes: https://itunes.apple.com/us/podcast/t...

Clojure programmers often complain about data structures getting unwieldy and hard to understand. How can we prevent this?

Transcript

In #Clojure and in other #functionallanguages we often have this problem of unwieldy data structures. They're deeply nested. They've got tons of keys. It's just a big mess. It's hard to understand what's in them. What is the solution? What do we do about this? Hi, my name is Eric Normand. These are my thoughts on functional programming.

I've been doing Clojure programming since 2008. I first started doing Common Lisp. Then I moved to Clojure. I loved the data orientation in Clojure. The fact that there were so many different data types, #datastructures in it. Compared to #CommonLisp it was great.

I already had this idea of data orientation. I found that in Clojure it was much easier to do. It was much stronger. I would say that Clojure is a more functional language than Common Lisp.

Since the beginning, people have been complaining about having these data structures where they...especially, working on a team. You know it's a map. You don't know what's in it. You forget what keys you should be using to get stuff out of the map.

People have typos in their work. They type the wrong keywords all the time. They are getting mills back. They're not sure where the mills come from. Then they eventually find that they forgot an S somewhere in their keyword. That was why it was breaking.

I hear these complaints all the time. I've worked at companies where we had this problem. I believe that this is one of the big reasons why Spec# was created. People want some kind of checks that their data structures make sense. They want documentation for what's supposed to be in the maps that they're passing around.

It's definitely a problem since people are complaining about it. I've never had this problem, not seriously. Of course I've made typos and stuff. I never had this problem where the data structures feel like they're out of control. I've been thinking about why it is, and looking at people's code who are complaining to see what's going on here.

It comes down to one thing, and that is that people are not designing their data. They're not thinking about what things should go together, and what makes sense to put together into maps. They're just cramming stuff in there.

This is a problem. I've heard in Ruby, people get into this. Where they have these classes that have hundreds of methods, and all this state, because it seems to make sense. Everyone talks about the user class getting all these methods. It's like a code's mail called the God Class or something. It just has everything. It can do everything.

What you should be doing is starting to pull those things out and having smaller classes. That's what happens with Clojure maps. It's you just think, "Oh, I'll just throw this in a map, you know. I'll pull it out in another place."

What happens is you couple your code all over the place, because this thing is producing a map, this part of the code. Part A is producing this map with a certain structure. To get the values out of the map, this other part of the code has to pull the values out with that known structure. You're duplicating the structure in two places.

In my first solution, the first cut is to just build an interface. Build a smaller interface instead of saying the data is its own interface. That's true. It's still true. The data is still its own interface. If you wanted to iterate through the keys and do all that stuff, you can.

As an entity, you should be thinking about all the things that you can do with this. You should be thinking about the meaning of this map. By meaning, I mean all the things you can do with it.

How do you make one? How do you access the values in it? How do you modify the values? Usually, of course, you create a copy with a modified copy. Then, also importantly, how do these things combine with other things? How do they compose?

We don't just throw them into a map. We might throw them into a map. We don't throw it into a map willy-nilly. We define how they combine with other things. By define, I mean, you write a function that does it. You write some code that is called change name. If you have a person and you want to change the person's name, it takes a person and the new name.

That's getting very granular. If you're treating it like a person, meaning, a person entity, not an actual person. You're treating it as a person entity. Person is an important concept in your domain. That should be a first-class operation. I would hate to see some assoc-in somewhere else that is digging down into the person and changing the first name, because that's not first class anymore.