In Software, Good Design is Everything

Designing is one of the most important and overlooked areas of a programming project. After all, how important it is creating a UML diagram if it will not be used during the coding of the system? On the other hand, stop and think about the good software that you have used, such as vim or UNIX. What do they have in common? The unsurprising answer is: they have good design.

Designing software is not the same as creating nice UML diagrams. I know a lot of programs that have beautiful UML diagrams but are terribly bad designed. On the other hand, some of the most interesting architectures were not created from an UML diagram. From a pragmatic perspective, having a good design means that the resulting architecture provides the basic mechanisms for extending the original program without the need to rewrite its basic components.

In a well design program, developers can feel confident to extend the system, without thinking that they need to understand something very subtle about its internals. For example, very few people need to know how UNIX is internally implemented in order to write a new application. You also don’t need to know the internal architecture of Emacs to create a new package. These are examples where a system possess a strong technical foundation to which additional functionality can be easily added.

On the other hand, a badly designed piece of software can have growing costs that will continue forever as long as changes are necessary. If there is any need for extension in such a system, then one has to understand how each piece works together. Working in this way is like playing with a house of cards: for lack of a foundation, any change in the system can bring the whole thing down.

Moreover, even if no further extension is required, think about the costs of maintaining a low quality system like this. In general, what this means is removing bugs that will inevitably appear from time to time. In a badly designed software, high attention to detail is necessary to avoid a mess that may be eventually caused by the addition of a single instruction.

This kind of flakiness in software is what costs so much time and money on common projects. Many such projects start with the explicit (and misplaced) goal to create a program quickly. However, not spending the time on design may have bad consequences for the future of a project. If the basic architecture is not in place, it becomes increasingly difficult to make changes, and huge amounts of time are lost during the main parts of the project.

The lesson from these observations is that everything starts with good design. If your software doesn’t have a good design, it is doomed. Even though there is a huge pressure to create software quickly, the initial design is the most important part of the process. Skipping this step can hinder the whole effort and turn your project into another nightmare, that is sadly so common on software shops.

Further Reading

The mythical man-month is the classic book on design issues on software engineering. I highly recommend it for anyone interested in software design.

How to Avoid the Second System Syndrome

The second system syndrome is a phenomenon that happens every time a person or company tries to rewrite a successful software for a revamped second version.

The syndrome is characterized by lots of promises (the next version will be the best ever…), long release cycles, and usually failure from the part of the developers to create something that is even close to the expected.

The same set of events have been observed throughout the industry in several occasions. A company that goes through this kind of cycle either has to go back to a previous version and stop development of the much awaited new incarnation of the product, or in the worst case becomes completely irrelevant.

Of course, this kind of syndrome doesn’t happen only in the second version of a software (the 2.0), it can happen in any stage of the lifetime of a software product. For example, Netscape rewrote their browser between the versions 3 and 4, and almost killed it. Microsoft tried to rewrite Windows several times in the last 20 years. With the only exception of the launching of Windows NT, which was a completely different product at the time, all planed rewrites took longer than expected and resulted in an inferior version being released.

From the experience accumulated by companies of all sizes, there are a few recommendations that can help avoiding many of the mistakes mentioned above.

Don’t try to make everything better at the same time: one of the reasons for defeat by the second system syndrome is having no clear goals. If you just setup to create a new version of your software that is better in any way, this is mostly a recipe for failure. There is an infinite number of improvements you can make to a program. You won’t have time to make them all work.

To avoid this danger, start by clearly defining an area of the system that will be improved in the next version. Maybe you can add a second area, but the more focused you are, the better your results will be.

Another helpful suggestion is to concentrate on specific features, not on the general feeling of the application. Features can be implemented, abstract ideas cannot.

Internal Changes

Another reason people feel the need to rewrite a program is the idea that its source code is ugly, and should be changed. While this may be a good reason for making internal improvements, it is rarely a reason for rewriting a program.

Remember, users don’t see your code. They are not attracted to your program because of the clarity of the source code. All they see is the implemented features of your application. While you have to strive to write maintainable, clean code, such an advantage is not worthy the price of a complete rewrite.

Conclusion: instead of being too ambitious and disappoint your users, it is much better to provide great new features in each version of your software. Avoid the second system syndrome: users will be happier and you, as a developer, will have a much better time.

How to Decide if you Should Write a Program

As a developer, have you ever wondered if a program needs to be written? With the library of existing programs growing larger than ever, it is sometimes difficult to justify the need to write still another one. Especially when the need for a program may not be well understood in principle.
Like anyone that need to prioritize activities, I had to come up with a few guidelines to decide in which to spend time. Here are some of them:
Is anyone paying me to do this? Like it or not, this is the number one reason if you have to work for a company and you are not a decision maker. With luck, however, you can have a say on how the company will spend its efforts and the next reasons will apply. Also, you may be working on your own company or open source project.
Does it provide a feature that doesn’t yet exist? While it is tempting to write “yet another” program to do something that is well known, the benefits of doing this are small. This is a situation where you need to create something really better just not to be perceived as another copycat. While this might work if you have a lot of experience on the subject domain, why take an unnecessary risk? If I don’t have any really good idea to improve something, I just let it alone.
If the functionality exists, would it be much better than current options in some way like time, easy of use? This is the test you need to do whenever you are tempted to rewrite something. If you cannot convince yourself that it would be better for your users, don’t spend the time.
Rewrites of a program are dangerous. Keep in mind the second version syndrome, whereby developers try to improve the existing system in every conceivable way, just to learn that users don’t want it anymore. This is a particular case of trying to do too a perfect job: and you know, perfect jobs don’t exist.
Can you learn something from it? If I cannot convince myself that the program will be new or much better than the existing, then I ask if it will teach me something new. This is something that works particularly well for personal or open source projects: no wonder there are thousands of open source versions of every application. Most of them start as a vehicle for someone to learn about an application domain. Such projects frequently gain their own life and become something useful for others.
Has any commercial value? If you cannot learn anything new, it might still have commercial value. For example, it can complement a major product your company might have. This is the common case when a major product adds functionality that exists somewhere else, but that would still be useful to complement the original program. Be aware of the proliferation of features that can make your product harder to use and slower/buggier.
Is it fun to write? Some programs begin their life just as a way to have fun. Lots of developers have fun writing new compilers, editors, and similar system software. That’s why there are so many of them around. This is something that usually goes together with learning something new: developers having fun can be a very powerful force.
Will it help anyone? There are times when you don’t have any other reason to write a program other than helping someone to solve a problem (that someone can even be yourself). Sometimes you may be trying to help your wife, your brother, or your neighbor, with some functionality that would be easy to write yourself. My first suggestion is trying to find similar functionality somewhere else. But if you can’t, and it is easy, why not do it? This is one of the advantages of understanding how computers work, right?