How does executable specifications compare with other modeling paradigms?
This is an episode of The Eric Normand Podcast.
Subscribe: RSSApple PodcastsGoogle PlayOvercast
In this episode, I compare executable specifications to UML, DDD, and software design.
Transcript
[00:00:00] How does executable specifications compare with other modeling paradigms?
[00:00:10] Hello, my name is Eric Normand and this is my podcast. Welcome.
[00:00:15] So I know people are going to compare my book and the content and the topic of my book to other things, and I want to help them do that-- help them compare so they can understand what my thing is and how it relates.
[00:00:43] I've already had people mistakenly say, "Oh, you're into domain-driven design," because I could talk about domain modeling. Domain-driven design is not what I'm talking about. I mean, there's some overlap, but domain-driven design is this thing that Eric Evans created. It's a thing unto itself. It has a lot of overlap with domain modeling in general, but it's not what I'm talking about.
[00:01:18] I'm gonna compare to domain-driven design, and I also want to compare what I'm doing in my book to a more UML approach. And finally I want to compare it to software design in general, sort of the average book out there on software design. So let's start with UML, cause I think that's a good place.
[00:01:44] So UML is Unified Modeling Language. And it is a mostly graphical way of representing models.
[00:01:57] People do domain modeling with UML. They get some requirements from the customer and they draw pictures using UML as a language, as a visual language, and they draw that. And that is what they consider the practice of domain modeling. And then they take those pictures, you know, they use them to communicate with the customer, "is this really what you want? Shouldn't it be different? Could it be this way instead?" And so they're a communication device, a way of understanding and communicating with stakeholders. And then they translate it into, code in C++ or Java or, or what have you.
[00:02:48] That is a very simplified view of the modeling of the UML process.
[00:02:56] What I wanna do is different. It's related. There's still this modeling step, right? I, I don't want to give a process, right? But. If there is, if you are, you are gonna do a process and there's, there's a step where you write out the model, where you take these requirements that are kind of vague and not formal at all.
[00:03:19] They're written in English, and you turn them into something a lot more formal. UML is a lot more formal than English. It has a more restricted set of meaning to it. But it's not as formal as code. And people see that as a strength of UML. There have been attempts to define exactly how a UML model would run. How can you turn this into code directly, translate it directly. And the more people did that, the people who created UML and the people who really like UML found that in doing so, they lost a lot of the power, which was to have this intermediate step that's good at communicating.
[00:04:14] So they weren't trying to create a visual programming language. They were trying to create an intermediate artifact that was better than English at specifying what was gonna happen, but not as laden with complexity as code. And once you formalize it, you have to deal with all the complexity of actually it has to run.
[00:04:43] Their solution was to say, we're just gonna keep it in this medium zone of formality. Very restricted set of semantics, and standardize the semantics. But you can just make notes if you have some other information that needs to be included.
[00:05:04] Executable specifications is different in that it is formal. You're writing it in code. You're going directly into code.
[00:05:15] The difference, I think, from just starting to code is that you're not writing out the main body of the code at first. Instead of writing full functions, you're just writing the signatures. The signature captures a lot about what the function's purpose is, but more importantly, what inputs and outputs it needs. But you don't have to say how you're gonna implement it yet. Because you kind of don't know. You don't know what the data structures look like. Maybe you don't even know if you want this function yet, so why implement it?
[00:05:56] I think that's a big mistake we often make is we start coding it because we know how to do some of the easy stuff first, and then when we get to the complicated stuff, we're stuck. Is it worth rewriting everything I had, or do I try to just force it in to this model that I've got. And in executable specifications and stuff I'm trying to teach in the book, there's this intermediate, very formal format that is code. It's the signature. It's like an empty function body. Or if you have types, you might just write the types out, but it's this empty function that just says, this is the arguments, this is the return value, and the name. And we're not gonna implement it yet.
[00:06:57] So that's one difference with UML. The other is because it's in code, you can run it. Instead of writing in a separate language, that you have to translate into code, you are, one, making sure that it works in a way that you can't really do in UML. So you can build a prototype of the thing with the right function signatures, maybe a different data model, but something easier like instead of accessing the database, we're gonna do it all in memory. But it's got the same function signatures, so you're not cheating. But you can see, is this what we want it to do? I mean, I guess you are cheating, you're taking a shortcut. This isn't the final thing, but it's got the same exact semantics as the final thing.
[00:07:57] Is this what we want? You can write out little scenarios. You can say, okay, a person's gonna add these seven toppings to the pizza, remove these three, change the size four times. Does this give us the flexibility we want? Does this give us the expressivity we want? If you did that in UML, you're guessing. You're running the simulation in your head, and I want to run the simulation on the computer. That's part of the the fun, interactive thing that I'm trying to get at with executable specifications.
[00:08:39] The other thing is that you don't have a translation step. One of the things I don't like about UML is that once it's translated into code, there's a lot that's lost. Okay. You still can keep the UML around, right? But there's a lot of information that was captured because of the restricted semantics that now is lost in the code.
[00:09:17] Because in the code you have the whole language at your disposal. Why did I choose to do it this way and not that way? This translation step is wasteful. Why are you translating from one representation to another? The code is, itself, a good representation for what's going to happen and just not having that translation step gives you more direct access to the domain, meaning the model that's in your head is now more concretely expressed in the code.
[00:10:01] And so when you find a bug, or something doesn't work as you expect it, you can debug your model. Oh, the model needs to be this other way. Can't do that when there's this translation.
[00:10:16] All right, so domain driven design, also known as DDD, is basically a book that started a whole movement by Eric Evans. It's another branch of software design that also focuses on building models. They like having the models in code, which, like I've already said, I like that. But from a software design perspective, it uses this style of design that's based on principles and rules of thumb and patterns, and I don't want to do that.
[00:11:05] Executable specifications, the book, is all about practical skills that you can apply. It's not about trying to point at the ineffable, which is what I feel like patterns are trying to do. I should explain why I think that that's a problem.
[00:11:28] What I notice, and I believe others notice too with patterns, is that, a person who's really good at design can skillfully use patterns, no problem. They understand it. They've encountered the problems before, and now they're happy to have a solution that other people have come up with and formalized into the pattern.
[00:11:53] The trouble is that if you're not good at design, patterns don't help. Because you need to have all of the context and awareness and understanding to be able to use them, but if you had the context and awareness and understanding, you're already a good designer. So it's not that they're bad, it's that they're not targeted at people who need to learn the design.
[00:12:30] Rules of thumb are the same. They require a lot of discretion. You have to have a good understanding of the context. If you already have that understanding, then the rule of thumb is usually not that helpful. That's not the hard part.
[00:12:50] What I want to give is that context. I want to expand people's awareness of the choices available to them. What are the kinds of problems they're encountering, and help them make design decisions by expanding that context. So that goes into all the lenses that I've talked about in other episodes where each lens is trying to expand the amount of information you are gathering, giving you a higher resolution view of your problem.
[00:13:29] You gather all this information and you can now make better decisions. So it's both about seeing more information and then how do you use that information to make decisions. That's what the lenses are about.
[00:13:45] All right, so then D D D also has this other stuff, which I guess I'm calling like project management slash engineering management, like the people side stuff that I'm not gonna go into. I'm talking about stuff like the idea of the ubiquitous language or bounded context where it's kind of like this organizational view of how different parts of the organization use the same words in different ways. When accounting talks about a customer, they mean this. And when sales talks about a customer, they mean that. They're related, but they're talking about different things really.
[00:14:36] But then there's also this idea of ubiquitous language, which is this idea that software engineers need to use the same terms that everybody else uses. They often will have a thing in their code and they'll call it a user, but everybody else in the company is calling them a customer. Why are you using different language? It's only confusing people, and it gets worse when it gets more subtle because you have to do this translation, and it just confuses everybody.
[00:15:14] That's a problem. I'm not saying it's not a problem. I'm not saying DDD is wrong for calling that out. I'm just saying that's not what I'm talking about in the book. If you wanna learn about that, read the DDD stuff, it's very well expounded.
[00:15:28] And the other difference is the stuff I'm gonna do in my book is functional. There's not enough functional software design stuff out there. And it's the stuff I like, so I'm going to, I'm gonna talk about it.
[00:15:45] All right. Finally with software design, I've kind of touched on these ideas already. They're not really so distinct, these three branches. They overlap quite a lot. Domain modeling is an approach to software design and executable specifications is an approach to domain modeling, so this is definitely in the realm of software design.
[00:16:09] The trouble that I see with software design, the average book out there, most books in fact, is that they focus on the code. Code quality. Okay. Yes. They talk about rules of thumb and patterns and stuff, and I've already talked about why I don't like that, but the main point that I don't like about software design is that they focus on code.
[00:16:41] Code quality is a good idea. You need to have clean code that you can read. That's not up for debate really. The problem is there's this whole other side of the semantics of your code. What does your code mean? Does it actually correspond to the thing you want it to mean?
[00:17:00] It's like we have a whole field dedicated to style, but no field dedicated to substance. And software design, just like regular product design, is not just about how it looks or how readable it is. It's about what it does, how it works. And you can't really separate the two. You can find lines where, oh, that's definitely a stylistic choice.
[00:17:31] Like, you know, tabs versus spaces. That's definitely style. It doesn't change how it works.
[00:17:38] On the other side, something that's purely substance is whether you can actually represent the thing that you need to. If there's certain coffees that you can make, in this coffee shop we keep talking about, but you couldn't write down, you couldn't represent in memory for whatever reason. The way you chose to represent it, you left one out. This is substance. This isn't style. This isn't oh, you need to clean it up. No, you got it wrong. And it is not gonna work right. Someone's gonna try to order that coffee and they're not gonna be able to do it.
[00:18:22] There's also this middle ground where it's very unclear is it a stylistic choice or is it substance? And this is stuff where you're talking about expressivity and how things compose together. How easy is it to express certain coffees? Those are in the middle because you could say it's style, but it also has to do with substance because you're expressing the right thing.
[00:18:52] There's a blurry middle there where it's both. I feel like software design talks only about the style. If you look at the gang of four design patterns, and you look at the problems that they claim that these patterns solve, most of the time they are talking about code problems. This one is for when you have too many classes. This one is for when your type hierarchy doesn't allow you to extend it in this certain way. These are code problems.
[00:19:43] You have an idea for some code in your head. And you see this problem, oh, that's gonna make a hundred classes. That's too many. How can we change that? Oh, we can use decorators.
[00:19:57] A rule of thumb: your methods can have no more than five lines. They're only talking about the code. They're not talking about the substance of what is this thing trying to represent, and are we representing it well? It's simply about code organization. How big your methods can be, how many lines they can have. It's like saying, well, you can't have more than three colors in your sock drawer. It's purely organizational. It's not saying at all, what, what do you need to store in your drawers?
[00:20:38] Software design has a lot of these problems. I'm not gonna make a big enough splash to really solve that. But if I have a target, it's to fix that.
[00:20:51] Let's stop talking so much about lines of code and the naming of our functions and nesting ifs and stuff like that. All important, right? But there's this other side of are we choosing the right data structure? Are we allowing things to compose? Well, we just don't talk about that.
[00:21:18] Okay, so let me summarize cuz this has been kind of long. Executable specifications is, first of all, you do it in code, not a separate language. It's functional, not object oriented. It's very practical skills. It is not patterns and rules of thumb. There's skills for uncovering information that is available to you just by looking in different ways, different perspectives at the same thing. And finally, it's about how you represent the meaning that you're trying to capture.
[00:22:06] Often we try to solve problems in the code. We have some code, it's kind of messy and I just can't understand it. We just try to clean it up. But very often the problem is that it doesn't quite correspond to the thing that it needs to correspond. And as a new person to the code base, you might not know what it's trying to correspond to, which is very difficult to suss out from the bad code. It's bad because it doesn't say what it's supposed to say.
[00:22:43] Not that it's messy. It could be really well organized, could be really well named, but just naming the wrong things. The functions aren't the right functions that you need. There could be some state that is very difficult to represent. You have to jump through hoops to get to that state.
[00:23:09] Okay, so that's the summary. I won't rant anymore.
[00:23:14] My name is Eric Normand. This has been another episode of my podcast. Thank you for listening, and as always, rock on!