On my last blog, one of the commenters very correctly pointed out that I hadn’t actually told you what I meant by “software design.” And, in fact, looking around the web a bit, I’m finding that what I mean by “software design” isn’t fully covered by most current definitions.
For the sake of this definition, let’s say that the process of making software is composed of three parts: administrative decision-making, technical decision-making, and actual coding. Of course, there’s also testing, releasing–there’s lots of parts to software in the real world. I’m just making an artificial division here to help define one part of the three I mentioned.
By “administrative decision-making” I mean the sorts of decisions that would be made primarily by managers in a software organization. These are scheduling, cost estimates, what programmer to assign to what task, etc. There are a lot of theories and study in this area–I think that it’s actually fairly well-covered (even if not completely made scientific yet) by lots of people. That is not the area I’m talking about when I say “software design.”
The other side of those three parts is “coding”. That’s where you sit down and actually write the program, typing strange words onto a screen in the hope that the computer will do something. This process is partially covered by the study of computer science, which gives us mathematical ways of modeling code and information. It’s also covered by the manual of whatever language we’re writing in. Coding is what you do after you’ve already made decisions–it’s just the actual process of telling the computer what to do, or figuring out how to make the computer perform the actions you want.
The last piece, in the middle, is what I’m loosely calling “technical decision-making.” Often, the process of technical decision-making and coding happen so fast that they are mentally indistinguishable, particularly if you are an experienced programmer. You just “know” what to do and type it in. However, the decision-making and the coding are actually separate processes. Technical decisions would be things like: “Do we go with a functional programming language or a procedural programming language?”, “Should we have unit tests?”, “How should we style our code?”, “Should we optimize for speed?”, and even-less-high-level decisions, until you get down to the actual coding. Basically, anything that happens in your mind, on a piece of paper, on the whiteboard, etc. before you start programming, that’s software design as I mean it. Anything that involves the overall design of the system or the technical decisions you make while creating the system would fall under this category.
It could just as easily be called “software creation”, but I think that would get too confused with coding and computer science. Similarly, I started out calling it the subject of “software”, but that has the same problems. “Software architecture” is too limiting, as it’s often thought of in terms of classes and objects, and might not include things like unit tests, code style, or other technical decisions you have to make in the process of creating software.
I suspect that in time I will come up with an even-more-precise definition, but this should at least give you some idea of what I mean, for now.
What I think we primarily lack in the field of software design is a series of fundamental truths on which we can base our technical decisions. Experienced software developers “know” what “the right thing to do” is, but why is that the right thing? What makes that “right?” Many Perl developers, for example, would claim that Perl is “the right way”, in direct conflict with the way other languages work. There are definite warring camps in this field–how can we figure out which way we should go?
Well, that’s one of my goals with this science (or subject) of software design–to help us be able to figure out where we should go in any given situation.
So, in my view, any science of software design would have to consist of:
- An explanation of the purpose of software.
- An explanation of the goals of the science.
- A series of fundamental truths on which to base decisions.
And this would allow us to achieve:
- The ability to make decisions that achieve the stated purpose of software.
- Some way of understanding what causes errors (decisions that do not achieve the purpose) in software design.
- A method (or methods) of preventing future errors.
- A method (or methods) of fixing errors that already exist.
In my view, a science is only as useful as it can be applied. Physics is very useful because we can use it to build things, fix things, design new things, etc. I would like the science of software design to be directly applicable to the practical process of writing software, and the kinds of decisions that real programmers have to make every day. I can’t promise that the study will be perfect, but I can promise you that it will be useful.