Earlier this week I went back to work after a refreshing (and very much needed) vacation. During this past week I participated in some interesting discussions that made me think about software engineering and our craft in general. I want to share some of my thoughts, so here goes ...
Design == Code
In my latest book review of Agile Principles, Patterns and Practices in C#, I mentioned an article that is included as an appendix named What is Software?. This article, that originally appeared in C++ Journal somewhere in 1992 (!), really got me thinking. Some discussions about software design earlier this week added to my thoughts and made me come to realize that the source code of a software system is also the design.
Software design is not about drawing UML diagrams. UML diagrams may represent a part of the design, but it is definitely NOT the design itself. Sure, we can all draw nice looking UML diagrams and pat ourselves on the back for being smart. Does it actually work what we have drawn? We can stare at UML diagrams for months, discuss them with our co-workers for ages and change them forever.
The only way to find out if what we have drawn actually works is to get our feet wet and start implementing code to back things up.
If the source code is the design of a software system, then this implies that software developers are software designers! This is why agile methodologies make sense. They encourage self-organizing teams where every team member is responsible for the quality of the software system they are building as opposed to traditional waterfall approach. I wrote about this here.
Software engineering vs manufacturing
Also during these discussions, some of the attendees made some comparisons between software engineering and manufacturing or construction. I really don't like this analogy. Besides being pointless, it doesn't apply.
Take airplane manufacturing for example. When building a new type of airplane, aerospace designers create blueprints in order to document how to build such a thing. These blueprints are used by the manufacturing department to build this new type of airplane. In order to find out if their designs make sense, models are built that can be tested in all kinds of situations like wind tunnels. They use these models to see if the airplane that they try to build will actually fly. What if it doesn't fly? What if the wings fall off on nasty weather? They want to know these kind of things before manufacturing starts building these things. But the main reason of this BDUF, is that building and testing these kinds of models is much cheaper than building an airplane right way. That's just common sense, right? When the blueprints are ready and fully tested, then the manufacturing department is put to action and starts building new airplanes.
As even my youngest daughter already knows by now is that waterfall and a BDUF like this has failed miserably in the software industry. Is a BDUF, drawing massive amounts of UML diagrams that much cheaper than creating and testing the code for the software that it represents? Don't think so.
This doesn't mean that we should start coding right away. As mentioned earlier, developers are also designers. Thinking about the design of the software system that we are building before writing the source code is common sense, but as an ongoing process.
I just don't buy it. Something like this got mentioned in a discussion and I don't think its a good idea. I do believe that there are universal design principles to adhere to like SRP, OCP, etc. ... . However, I just don't like the idea that every application has the same architectural needs. Sometimes a data-driven approach is justified. Most of the times, a domain-driven approach is needed. There are lots of differences between these two approaches, so I don't like the idea of choosing one or the other and sticking to this decision regardless of the requirements.
I've been a software engineer for about 8 years now. During this time, I've seen a lot of decision making based on fear. Fear of making refactorings to existing code, fear of adding new features to an application with an unmaintainable code base, fear of not meeting deadlines, fear of changing requirements, etc. ... I could go on like this.
We've all done it, postponing some refactoring because of some deadline. Writing some quick and dirty code instead of doing the right thing.
I must admit, the first few years as a software developer I was also like this, but didn't liked it that much. A decision made by fear is almost always the wrong one. Fear prevents us from seeing the things in a clear, objective way. So I tried to get out of the habit. If I see a refactoring one week before a deadline, then I just do it if it adds to the maintainability of the system. If I have an epiphany about our implementation of the domain while doing the dishes, then this is something that needs to be done in order to suit the domain model.
When it comes to software engineering, I have just one fear left: fear of not delivering quality software. Building quality software means doing the right thing, even if it means you were not entirely right the first time you entered the code.
Still here? I'm done now.
Till next time,
Jan, the unburdened.