All about the stratified design lens
In this episode, I introduce the stratified design lens, which talks about how and why we split things into layers.
[00:00:00] All about the stratified design lens.
[00:00:03] Hello, my name is Eric Normand, and this is my podcast. Welcome.
[00:00:10] So I'm writing a book about executable specifications as a means of data modeling. And data modeling is a subset of software design. And software design, like all design, is about making good design decisions. To make good decisions, we need good information. So I'm organizing the content in the book as a collection of perspectives where each perspective I'm calling a lens. It gives you a way of looking at your software, some questions to ask, ways to see what's in there a little bit better so that you can gather more information so that you can make better design decisions.
[00:01:03] Most of software design is about the context and having a rich understanding of the context. Can't be done with a bunch of rules of thumb and things like that. So I'm trying to avoid all that and just give you more information.
[00:01:21] Today we're talking about the lens of stratified design. And when you're looking at your code from this perspective, and your domain from this perspective, you have to start thinking about what belongs in each layer. It's very hard at first to see that different concerns are really concerned about different things. Let me give an example in our coffee shop domain.
[00:01:56] Our business says, listen, we don't want to sell coffee with more than five add ins. So, if you put too many add ins in, there's no room in the cups. It starts creating a lot of issues. For practical reasons, we don't want to sell a coffee with five soy milk shots in it. Because then it's mostly milk.
[00:02:29] We have to implement that. That's part of our job. We don't want people to be able to order this coffee. But the question is, is that part of the coffee domain?
[00:02:40] Now, you could argue that, well, we don't care about that. What we're modeling is this business and its requirements, and we'll just lump it all in. And you could do that. That's a perfectly valid decision, and I think a lot of companies might do that.
[00:02:58] But, you could also say, now wait a second, this is not part of making coffee. This is part of the business's rules. It's not coffee's rules, it's business's rules. We can imagine a different coffee shop making a different rule. Maybe their rule is they draw the line at three. Or maybe another coffee shop doesn't have a restriction on how many add ins to put in.
[00:03:31] We could still use the rest of the model though. They still have this model of add ins and sizes and roasts. They just don't use this one little piece, which is this arbitrary number of add ins as a maximum.
[00:03:51] The add ins themselves are pretty arbitrary, right? Like, some shops are going to have soy milk, some are going to have cream, but not all of them are going to have those things. Some are going to have hazelnut and some aren't, and that's okay because we've deferred that to later. I mean, one thing we've talked about is making those runtime values that get stored in the database. What add ins are available so they could be anything and they could be added and removed later at the whim of the business.
[00:04:28] This arbitrary maximum number of add-ins is also at the whim of the business. Another way to look at it is that you can imagine a coffee shop that allows 10 add-ins and that's their maximum. It's not out of the realm of imagination. The solution in the stratified design lens is to build these things in layers. You have one layer, that's your coffee domain, that models coffee as a size, a roast, and an arbitrary number of add ins. And you have another layer, that's your business layer, that has other rules like a validation rule that says this coffee is invalid because it has too many add ins. And then you tie them together in the UI. The UI and maybe the API also calls it to validate it because you don't trust the front end. But it's a separate layer.
[00:05:36] The business layer is built on top of the coffee layer. Coffee layer defines those concepts already. And then the business layer simply defines some other rules to follow that validate whether that coffee is correct. Now this might seem arbitrary, not that important, not giving you much. But it's actually giving you quite a lot.
[00:06:05] One thing it's giving you, if you look at it from the composition point of view, it lets you define properties, like, if I add an add in, and then remove it, I'm back where I started.
[00:06:22] Okay? If you had a maximum, that might not be true. So let's say you had a maximum of five add ins. And you had five soy milks in there. You add one, a new soy milk. But of course you have a limit, so you just don't add it. It's a no op. That's how you decided to implement trying to add more than, than five. So it has five still, and now you're going to remove a soy milk and you remove it. Now you're down to four. So you're not going back to where you started. You added a soy milk and you removed the soy milk, and now you're at one fewer soy milks than when you started.
[00:07:07] That is not what we want. This property of adding and removing gives you a lot of leverage. Because you can write arbitrary tests that test this property. You can randomly generate tests. Given any coffee, if I add a thing and then remove it, it should be back to where it started.
[00:07:34] By deferring the business rule of a maximum number of add ins to a different layer, you're able to get a more coherent and more algebraically manipulable layer in there. The skill is to see these possibilities as you're working through your operations and what use cases you're going to implement.
[00:08:03] You could see this one is really messing up my properties. This one is not playing well with the composition that I want to be able to have. And then you look for an excuse, and you say, Ah, yeah, because it's not actually about coffee, it's about the business. And so I'm going to create a separate business layer.
[00:08:31] Part of the art of stratified design is learning how to include the stuff that's going to make your model more coherent and algebraically expressive and exclude the things that are going to break that.
[00:08:52] And only exclude them to the extent that they're just being deferred to another layer. Another layer can easily handle this. So it's not like you're taking easy work and making it harder. You're actually making the implementation easier by moving it to another layer.
[00:09:14] Imagine what you'd have to do. Every operation that might add an add in has to check, am I at the maximum number now? If I am, then it's a no op, or you have to decide, what is it going to do? Is it going to replace one? Who knows what it does? And probably a no op is the best, or throw an error. That's terrible. Now you got to model these errors in, in your domain.
[00:09:40] That's no good.
[00:09:41] But by deferring it, you get to turn it into something else. You get to turn turn it into a validation function. This validation function is easy to implement, and it can just have a bunch of rules in it. And, you know, you might have some random rules like you can't have hazelnut in a medium coffee, right? Something weird like that. That's the kind of rules that businesses have. It's just an if statement that evaluates to false.
[00:10:14] In general, we need to distinguish between the domain and the business a lot more. The domain is whatever your software is about and the business is the arbitrary rules that your business has chosen for whatever reason. It could be because of the way it's selling its stuff. It could be some practical decision. It could be some limitation of the equipment that they're running.
[00:10:48] Whatever it is, this has nothing to do with the domain. If you can imagine a coffee with a hundred shots of hazelnut in it, maybe it should be valid at that layer, but invalid at the business layer. And I think that that domain-business distinction is an important one.
[00:11:13] There's more layers in there that you could find. This is a very simple domain, so it's got one layer plus the business layer. But in your domain, whatever you're doing, you're probably going to have multiple layers and you want them to be algebraically coherent.
[00:11:32] For instance, in any business, you might have a money domain where you talk about money and all the concepts around money and how they compose and how taxes might work . And then you might have, built on top of that, a discount domain, coupons and sales and arbitrary rules of like how if you buy three on this day, you get one free. Has nothing to do with coffee, but it has a lot to do with your business and how your business runs.
[00:12:12] All right. My name is Eric Normand. This has been another episode of my podcast. Thank you for listening. And as always rock on!