What is missing from Stratified Design?

In this episode, I explore the notion of fit and how it is missing from the Stratified Design paper.

Transcript

What's missing from stratified design? Hello, my name is Eric Normand, and this is my podcast, Welcome. Today, we're going to be revisiting a paper that I read and commented on in January of 2020, it was episode 162, the paper was called LISP, a language for stratified design. A really great paper, and I want to revisit it and really ask some poignant questions about design as it defines it. But first, before we get to that, I want to talk about my book Grocking Simplicity. It is now out, it is on Amazon, you can also get it on the Manning website, I'm sure you can get it on Barnes & Noble, anywhere that you buy your books. Grocking Simplicity is a book that is trying to teach the fundamentals of functional programming for someone who has not been introduced to functional programming in a sufficiently good way yet. Maybe they've been introduced, but they never really got the idea. I think a lot of functional programming books will focus too much on what I call Lambda Calculus gymnastics, they're just like, "Oh, look at all the cool stuff we can do with currying and partials and stuff like that." They don't get to the heart of the matter, which is understanding the difference between pure functions and impure functions, how to work with immutable data, and then how to build higher order abstractions that are actually useful and save you code. That's what the book is about, and well, please buy it, please read it, and recommend it to your friends if you like it. I would also appreciate five-star reviews on Amazon if you like the book that really helps, especially other people who want to know if the book is for them. It helps to have some reviews up there. It helps me, helps them, and thank you. Okay, so on to our topic. I really like this idea of stratified design, and it's an excellent paper. You should go listen to episode 162 or read the paper. I think that there's a ton of stuff in it, and I've reread it since I've done that episode and found even more cool stuff in it. I spend two and a half chapters on stratified design in grokking simplicity, because I feel like it's one of the principal ways that functional programmers do build their code. It's a perspective of making stuff out of layers and how each layer builds on the layer underneath it. It's really cool, but I have an issue I want to bring up with the notion of design as presented in that paper. They talk about, there's just something missing, and okay, so they talk about how design helps you with flexibility. The different layers can be each, you can decide for yourself where a change needs to be made. You have some function that the example they gave is building MC Escher style pictures. You have some repeated pattern that can tile and shrink as it gets more to the right. They have this recursive way of building these images out of a single tile, and how do you tile it and mirror it and stuff like that. It's a really cool system, and they credit a lot of the power, the sort of design power, the flexibility of it, is from the stratified design. By making different layers, you're essentially building up a nicer and nicer language for expressing the picture that you want to draw, and then if you need to change something, you could say, "Well, I actually need to change how mirroring works," or you could say, "Well, I need to change how I choose to mirror," which is at a higher layer. If you're building layers up, you could talk about how mirroring works in general for every picture or how I am calling the function that mirrors what arguments I pass it at a higher layer. You're able to choose whatever layer that you need to make the change at, and that's very flexible. It adds to the flexibility. On top of that, they've got a thing that they're talking about called the closure property, which basically means that the functions at some layer, there's some layer above which all the functions take a picture and return a new picture. What that lets you do is recursively nest them, and that gives you basically another dimension of expressivity that you're not just linearly sequencing some set of calls. You can actually nest the call so that the result of one expression is passed to another expression, which is passed to another expression, and that lets you be flexible as well. Without changing any of the layers, you can rework the expression of your picture and make a new picture, and that gives you a lot of flexibility as well. The pieces compose well, and they recompose well. Okay, all of that is really cool. I think that that is, you know, it's something that we should all strive to be able to do in our code, and I've talked a lot about that. But the thing that's missing, I think, is that it's really separating out the... Okay, let me back up. You know how people will say design is not just about how it looks. It's also how it works. So, this, to me, looks much more like they're just talking about how it looks, how expressive is the code, how easy is it to change? It's not about how it works, right? So what would it look like to talk about how it works? Well, I think what they're missing is that the functions that they chose, regardless of whether they're built in layers or not, right? But the functions that they build, that they chose to build, are really good for expressing that kind of MC Escher image. They're not good for different kinds of images, right? They're good for expressing MC Escher style images, and that was their problem, was, you know, they wanted to express these MC Escher style images. So the fact that it works well is like that they figured out what functions they need and carved the problem up in a certain way so that they can express these MC Escher problems. That is completely ignored in the paper. There's nothing in there that said, well, we could have just talked about plotting pixels and then had no leverage for building this kind of image. But instead we chose, you start with an image and then you can put two images next to each other and you can put them on top of the other and you can mirror it and flip it and, you know, all sorts of, you know, scale it, that kind of thing. And by doing that, you can build these testillations of the tile and make patterns with it. But if you were dealing with just like drawing pixels and, you know, other very primitive graphics constructs, you wouldn't have, it wouldn't be a good language for expressing the MC Escher image. So what I'm trying to get at is they're completely ignoring what I think might even be a more fundamental design concept, this concept of fit that the abstractions, the concepts that you're encoding in your software need to correspond to a useful, you know, useful functionality for for solving the problem that you're trying to solve. And that is part of design. They could have solved it with pixels. I mean, with a Turing complete language and a way to draw pixels, you can draw any picture. Like that's, that's well understood. But then it might be really hard, it might, it's a hard problem to start with those tools. But by starting with these other tools, they made the problem easier and it's not about flexibility, it's not about being able to change it or express, you know, an infinitude of different images in a recursive way. It's about choosing the concept, it's about modeling and I've never seen someone talk about that when they talk about design. They act like it comes out of nowhere that it's just some a priori thing that now we can, you know, apply design to in scare quotes, is not design is all about structuring your code and choosing good names and that's what they talk about when they talk about design. But this is much more about finding a good concept. And that is what I'm really trying to explore here in in this podcast is how do you do that? How do you look at an MCS or picture or a set of them and think, Hmm, this is there's something interesting about repetition and scaling and putting two versions of the same tile next to each other and mirroring and you start to break down what is in fact going on in that image to, you know, basically find you could call it the style, but it's it's maybe the building blocks of how those images can put together be put together, right? Now, you might look at something else like different kind of painter, you know, like a Monet something like that and try to think, what are the building blocks of a Monet picture? Maybe maybe you can't find it, maybe every Monet is unique or there's just something about how his eye worked or whatever that that let him do those strokes that he chose. But notice that's a that's a hard problem and they didn't attempt to solve that problem. So what I'm trying to get at is we need to find a method or a set of methods for breaking down the domain that we would like to to to model. And then coming up, so now we have a model might just be in our heads or it's on white board and pieces of paper. We take that model and we encode it into software and of course that's where functions come in and stratified design and stuff like that. But how do you find that model? That is the thing that that I would I'm trying to explore I'm trying to figure out here and I don't like I said before I don't see anyone else doing this. I've talked about this before in trying to, you know, pinpoint what I'm talking about that I see that other people aren't talking about talked about like style versus content. You know, if you go to a writing workshop, there you could you could divide advice between style and content. Oh, your word choices are that this is style, you know, this is unclear word choice. Maybe you should go faster, go slower, you know, lengthier sentences, simpler sentences. Things like that are style, right? Word choice style. But there's also, oh, you're writing a novel, you need a good plot, you need good characters, you need an interesting setting, right? There's all these other aspects that are not really about what words you choose and how you put your sentences together. It's something it's much more mental and about the meaning of the thing and so there's these two aspects and what I see in software is we're talking much more about style. We're talking much more about how long your methods should be, how you name your functions, you know, how, what directory structure to make it clear what, you know, where to start and things like that. That's all style, right? That's this, you know, non functional requirement stuff. Oh, we want to make it easy to change. Oh, we want to, you know, make sure that it's readable so that someone who can figure out what's going on or maybe it makes it easier to debug or to get started at your company, right? That's all style stuff. The fact that there are better and worse representations of the domain is totally not talked about. They act like that's kind of fixed and this is the meat. This is the, this is the substance, the content, right? This is the, we have a function that will take an image and flip it, you know, on the X axis or on the Y axis and so we have these, this function is an important piece of making M.C. Escher drawings and someone discovered that. Someone discovered that this is useful regardless of how it's implemented or, you know, how it's structured as a stratified design. That is a useful construct. Okay, so I said no one is working on it. I think that the person who comes the closest, although I think he does, he does, okay, the person who comes the closest is Connell Elliot and I've been following his work a lot. I do think that he has, he has demonstrated the ability to do this and has tried to talk about it and the, the real problem is then when his, when he's talking about his method, it goes into stuff like category theory pretty quickly and so people get, I think the people when they listen to it, they get a lot, they hung up on that like oh category theory is where all the useful stuff happens and I think that that's similar to the problem of stratified design, which is that now you're talking about the structure of the code and you're not talking about what the code is doing and what it's representing, which is the, the meat of it again, like you've forgotten about the content. And so, you know, Connell Elliot is doing it, but the way it's presented, I feel like it's like, okay, so I come up, you know, it would be like a, a writing teacher saying, all right, so I sit down, I come up with a very interesting plot with good characters and so they talks about the plot and the characters for five minutes and then for 45 minutes, he'll talk about how he breaks it down into chapters and how he, you know, makes sure that every chapter ends with a cliffhanger so you want to read the next chapter and like all that is now like, oh wait, you're talking about style now, like what about that, how do I make the great characters with the interesting plot? So I'm exploring that here and I've been trying to poke at it in different ways looking, reading about like design work in general and so, you know, stay tuned because that's the kind of stuff that I'll be talking about here. In addition to all my other content, all the stuff about, you know, the Turing Award winners and interesting papers and all right, thank you for listening. My name is Eric Normand and as always rock on.