What is software design?

I've never been satisfied with the standard definition of 'software design'. Is the term useful? What could it mean that is useful? In this episode, I talk about some definitions that I don't agree with and explain my definition.

Transcript

What is software design? This is one of those terms that I hear a lot. We throw it around a lot. And when I was writing my book I had to really think about what the definition was. Because I don't think there's a very good clear definition out there. So that's what we're talking about today. My name is Eric Normand and I help people thrive with functional programming. So I think just the fact that this term has used a lot makes it an important topic. Software design, I've had my issues with the term itself for a long time. There's the real problem is that people use it unthinkingly just to talk about things that are kind of related to programming, but not exactly part of the functionality of the programming. So I came across a pretty good definition. It doesn't mean I agree with it. I mean the definition is something you can start disagreeing with. So the definition was all of the non, all the choices you make to deal with non-functional requirements. So the functional requirements are all the things that the software needs to run. It's your features. If it runs correctly that's a functional requirement. Sometimes you have requirements that something happens quickly in a certain amount of time. That could be a functional requirement. You have to run on this kind of server. That's a functional requirement. But then there's a bunch of non-functional requirements. And these often have to do with the development process itself. So one non-functional requirement is that your variables have good names. It's non-functional because the compiler doesn't care if your names are good. But the other programmers certainly will. So even though it doesn't change the behavior of your code, it will change this non-functional requirement. So you could have a bunch of these. And you can see how this starts to get into the realm of where people talk about software design. Good names, clear code style, good module layout, those kinds of things are not part of the functional requirements. They are done for the benefits of the programming process itself. They make it easier to read and write code and so in change code and hopefully make it faster to develop new features and things like that. So Sandy Metz had an even stronger definition. It's the same definition but it's stronger. Which was that it's all about making code that's easier to change. Software design is about making your code easier to change. So she's picked one non-functional requirement and created it to the purpose of design. Now this might be within the context of her book or the way she's going to use the term she's not trying to define the term for everyone but this was her reason for writing the book was to make your code easier to change. So what I don't like this definition and the reason is that if you use the term design in any other context besides software design, it is not really what people are talking about. When you design a chair it is not about the non-functional requirements. The functional requirements do come into play there. If I designed a chair, let's say you could say the functional requirement of a chair is that it's comfortable. That could be one of your functional requirements. Making it comfortable, making the choices of what material, what shape, how high it's going to be, all that stuff. I think you would consider that part of design. You would call that, all those decisions you're making, part of the design. Even though it is directly related to one of the functional requirements. The same with the weight of the chair. That might be part of the functional requirements. The chair has to be within this weight. This, you know, can't be taller than this. You know, has to fit in this space, this volume. All of that is going to go into what materials you choose, the shape of the chair, maybe something about the building process that makes it lighter. All of this stuff is part of the functional requirements and it's part of design. I just never liked this separation between a model. Like, let's get the code working and let's then design the code as two separate activities. One for the compiler and one for the human. So I had to think a lot. Like what do I, you know, do I think that the term is even a valid term? And I did wrestle with that quite a lot. You know, my first inclination is no. We don't have a good idea of what this even means. But I started to read more widely about software design and really introspect into what it could possibly mean. And there's an aspect of design that is, let's call it different from engineering. If I'm going to say I'm going to engineer a chair, they're very closely relate. I'm going to engineer a chair versus I'm going to design a chair. What is the main difference there? And you know, design comes, the term design comes from the root of the word is drawing. It's about drawing it. And so there's a little bit of like, well it's not building the chair. Engineering might be building the chair. But then design is about drawing the chair. But that's not really what we mean either. We don't mean draw it when we talk about design. But there's an aspect, the difference between engineering and design is this aspect of aesthetics. Right? There's an aspect of not only choosing the functional aspects of the chair, but that it has some kind of aesthetic to it. It has some kind of style or visual appearance or something like that. Some kind of aesthetic. Maybe it's minimalist. Maybe it's a cube. You make a chair and it's a cube. And that's part of the aesthetic. It's part of the design. So, taking this, I started to see a term or a possible definition that would be useful. That would still take all this stuff into account. And I'll share it now. So, what I came up with and in all humility I am just one person like armchair philosophizing this. But it's something I had to do for the book to give a working definition of software design. So when you're working on a piece of software, very often it is way bigger than you can keep in your head at once. You cannot do a complete analysis of the whole thing while you're acting on one line of code at a time. So, you're making some change. You're adding something. You're changing some functionality of the system. Maybe you're rearranging it. But you cannot act locally and have the complete bigger picture. But what you can do is use the local clues to see how the system might be structured in the large. So, for instance, you can look at the clues and say, hey, this is actually a very modular piece. There are defined inputs and defined outputs. So, I don't have to be so concerned with the distant structure of the system at the distant part of the code. I can be concerned very much locally. So, that is a way that you can proceed without having to think, how does this fit into the whole thing. And what you can do then is use your intuition, your aesthetic, for how the system is structured globally, for how to address this small local problem. Right? So, that is bringing in the aesthetic sense that, yes, this small piece fits in with the aesthetic of the whole, which the aesthetic might be, it's built out of these small modules. Right? And I am matching that aesthetic. I don't have to see how all the modules fit together. I just have to know that we're doing modules. So, to summarize that, I'd say that software design is using your design aesthetic as a sense of the whole, the whole of the system and how your small part of the code matches that design aesthetic. Okay, so software design is matching, is using your intuition, your aesthetic to guide you in those choices, those one line, you know, who knows what scale you're working at, but the local small changes, do those have the aesthetic that allow it to fit into the aesthetic of the whole. And that brings into it all the notions that we think are important in design that you're using your intuition, that you're contributing to the whole even though you're working on a small part and that there could be some sense of style, which is often part of what people talk about in software design. When they talk about good code, good variable names, or good function names, they're talking about a certain style, a certain amount of clarity and a way of expressing the variable names that is consistent so that once you learn the style you can participate in it. You can read it, you can write it. So, there you go. Not so exciting. It was exciting when I found it, but I don't think it's so exciting now that I'm saying it out loud. I don't know if it is practically different from the other versions of the definition of software design, but I think that it's a different perspective. Perspectives are always good. Multiple perspectives are always good. And also, I think that this is important. It allows for design choices that are functional requirements. There's nothing saying like, oh, the design is stuff for the humans. The design is stuff that's not about how it works. I don't agree with that. I think that design is the whole, right? Design is a holistic approach. Functional requirements and non-functional requirements are important. And you have to choose which ones are priorities. You know, what's your priority stack on those? And the design and the aesthetic are what help guide you because you can't have the whole thing in your head. You can't name a variable thinking about comparing it to every single other variable that has ever been written in the system. You can't do that. You have to use your intuition, which has been trained by seeing lots of examples. And maybe having at some point sketched out the global view of the system and, you know, all of these things contribute to your intuition. And so in the book, the idea is you train your intuition. You see a bunch of examples of in particular doing stratified design. So this is chapters 8 and 9. They've already been released if you would like to read them. But we're doing stratified design and so the software design aspect is training your intuition to determine where the levels should go. Where should you split your code into different levels and layers so that layers are built on top of other layers. And given the name of the function you should be able to have a good idea of what layer it fits in based on the generality of the name. So this is all intuition. There's no hard and fast rules about it. Like you don't call it you know you don't put a one on the name of the function because it's in layer one. Like that doesn't make sense. But you can read it and say oh this is definitely relatively more general than what I'm doing so it must be in a lower layer etc. This is all intuition. It's all stuff that you can train by getting these holistic views, getting snapshot views, seeing how those snapshots fit into the hole. And then when you are working in your particular window one line at a time of code that you're writing you can use that intuition without having to keep the whole picture in your head. Okay. I hope you've enjoyed this rant on the definition of software design. My name is Eric Normand. You can find other episodes of this podcast at lispcast.com/podcast. There are links to subscribe. Whichever way you'd like to subscribe and you can also get in touch with me. You know if you have a question about this I get a lot of good questions and I often will address them here on the show. You can also disagree with me. That's great too. That often is good show material as well. I love to have long discussions. I'll have 10 or 12 emails going back and forth. Someone has a you know gets excited by one of the topics. I love doing that. So please get in touch with me. Just go to lispcast.com/podcast. You'll see everything there. Tell your friends if you like it then they'll probably like it too. So I'll sign out. My name is Eric Normand. This has been my thought on functional programming. Thank you for listening and I hope you're there next time. Bye.