Zen and the Art of Computer Programming

Today’s Chautauqua is about software quality, and how it relates to the developer habits.

Programming as an Art

Let’s start by discussing why programming is an art and not a science.

It should be clear that programming is not a pure science, simply because quality is such an important aspect of programming. The pure sciences, logic and mathematics, are only interested in the truth or falsehood of statements; quality is not a factor.

So, perhaps programming is an applied science? People often use the term “software engineer” for someone who develops software in a “systematic” fashion. To me, that is giving the software industry too much credit. Calling software development “engineering” implies that it is possible to define the requirements of a program in an exact way, and then use some well-defined way or algorithm to create a program that meets those requirements.

There are cases where formal methods can be used to prove a program correct with respect to some definition. This has been used for proving the correctness of compilers and the soundness of type systems, for example. In most cases, however, there is no formal definition of what the program should do, only vaguely expressed requirements that change as the stakeholders learn more about the problem. This, combined with the fact that the tools used for formal correctness proofs are as yet far from mainstream, means that most of us will be writing computer programs in an ad hoc way for the foreseeable future.

The fact that we do not have a scientific method to produce programs with certain properties means that it is up to you produce programs of high quality that satisfy all the stakeholders. Luckily, there are best practices, in the form om the developer habits, that will help you in this quest. And it also gives you the freedom to create programs that are not only useful but also beautiful.

Software Quality

When we talk about the quality of a program, what do we actually mean? Quality is a notoriously difficult term to pin down, and software quality perhaps even more so than other types of quality.

A computer program has no romantic quality: it is normally not possible to look at a program and immediately decide that it is “beautiful” or “ugly”. A program may have a beautiful user interface, but that says very little about the quality of the program itself. The quality of a program is classic quality: the underlying form of the program may be “beautiful” or “ugly”. For example, the domain model may be particularly well adapted to the problem at hand, or the algorithms used may be extraordinarily simple and efficient.

The quality of a program depends on the observer, or to put it slightly differently, different people are interested in different aspects of the program’s quality. Some examples:

  • A developer is interested in how easy it is to access and build the program, and how easy it is to make changes to it. Automating the build process, providing plenty of tests, and following a coherent architecture helps in this regard.
  • Someone working in operations is interested in how stable the program is, how easy it is to find instructions for starting and stopping the program, and how easy it is to find solutions to common problems. Automation, testing and good application logging can help with this.
  • The end-user wants the program to be easy to use, and to solve a real problem in a predictable way. Agile methods with recurring demos, and specification by example for clarifying the requirements, help make a program that solves the right problem in a useful way.
  • Managers want the system to be secure and cheap to maintain. Automation, testing and clean code created in a test-driven manner make this possible.

Quality and the Habits

Creating a program with certain quality aspects is difficult because these aspects are not obvious from the program’s external form. Recognizing, and being able to create, a program with specific quality attributes requires training and experience. The habits describe procedures you can use to help you create quality programs, but if you do not understand the reasons for the habits, for the procedures, you will still create mediocre programs.

When it comes to their effect on program quality, the habits form a hierarchy. At the top is Everybody, All Together, From Early On. It is necessary to talk to the right people to find out what to do, and to keep talking to get all the details right. This helps you do the right thing.

When you know what to do, it is time to Write a Test First. This can be a FitNesse test that documents part of the acceptance criteria for a user story, in a way that is understood by all stake holders, and with a clarity that is indisputable since it is automated. It can be a unit or integration test that helps guide the design and shows that the code does what you believe it to do. This helps you do the thing right.

With the basics in place — you are doing the right thing, and you are doing it right — it is time to think about Publishing Your Results so that other people and other systems are made aware of what is going on in your system and can react accordingly. This is also a good time to Automate, Don’t Document, everything you find tedious to give you more time to do interesting work, and also make it possible to easily hand over what you have built just by saying “push this button to get started”.

You may wonder where the habit When in Doubt, Do Something fits in. All the habits have static components as well as a dynamic component. The static components are specific patterns, tools and techniques that you have learned and that you use regularly. Some of these static components are discussed in this blog.

The dynamic component is the drive to constantly improve by adapting the way you work to increase the quality of what you are doing. The Scrum sprint review is an example of this; an attempt to continuously improve the development process. You have to do the same to try to find better ways to write tests, to automate, to publish results and so on. Even to find better habits. The habit When in Doubt, Do Something is a reminder to not only use the patterns that you already know, but to adapt and improve, and find new ways to work.

So, the question is, is it hard to create programs of high quality?

“Not if you have the right attitudes. It’s having the right attitudes that’s hard.”


  1. As most of you have already understood, this post was inspired by Zen and the Art of Motorcycle Maintenance: An Inquiry Into Values by Robert M. Pirsig. The ending quote is taken directly from that book. Some of you may also find traces of the follow-up book by the same author, Lila: An Inquiry Into Morals. Both books are highly recommended reading for anyone interested in the nature of quality, or just looking for a good read.
  2. The quality that we discuss here is not identical to the quality attributes that are often called non-functional requirements. However, some non-functional requirements, such as maintainability, testability and reliability, are affected by what we call quality.

Habits Useful for Practising Software Developers

I sincerely believe that the micro decisions we make every day when developing software can have a huge impact on the quality of the systems that we build. This means that if we learn to make better decisions when faced with options, probably several times a day, the end result is a much better system.

In the book The 7 Habits of Highly Effective People, the author Stephen R. Covey defines a habit as the intersection of knowledge, skill and desire. Knowledge is what to do and why to do it. Skill is how to do something. Desire is the want to do it. Hopefully, this blog can provide the knowledge and skill necessary to adopt some new habits. The desire must obviously come from yourself.

The habits I believe to be useful for software developers are described here. Some are specific to software development while others are more general. None of the habits should come as any surprise; this does not mean they are easy to adopt on a day-to-day basis. Remember that knowledge alone is not enough to form a habit.

Write a Test First

Anytime you want to change the behavior of something, you should always try to first write a test that describes the expected new behavior, and then make the changes until the test passes.

Test-Driven Development (TDD) is an obvious example of using this habit when coding. Specification by Example is another example, where you specify functional or non-functional requirements as concrete examples using a tool such as FitNesse.

Don’t Document, Automate

Documentation is great for describing why you do something, and for giving the big picture of how something works. However, if you find yourself writing a to-do list, your first reaction should be to automate the procedure instead of documenting it.

This has the benefits of being testable and repeatable. And you do get written documentation as well; the automation script is a concise description of what is being done. The difference is that the script is a correct description while written documentation may start out as being fairly correct, but usually soon deteriorates.

An obvious example of this habit is using Puppet to automate provisioning of machines.

Publish Your Results

Very few systems are islands, most need to communicate with other systems and with people. In order to do so, it is important that the systems provide information about what is going on. Whenever you make a substantial change in the state of a system, try to think of others that may be interested in this change.

Examples of this habit are publishing domain events when a state change occurs in a system, and making sure to use proper application logging to make it easier to find problems.

When In Doubt, Do Something

If you are not sure what to do next, for example because there are multiple possible solutions to a problem, it is important to not just sit still and wait. By doing something you learn more, and move closer to a good solution.

Examples of this habit include spike solutions to try out a new technology, and reading a book while between assignments.

Everybody, All Together, From Early On

Make a habit of trying to communicate what you are doing to everyone who might be interested in the result. During a project, constantly try to identify new stakeholders.

Examples of this habit are having a brainstorming session at the start of the project to identify stakeholders, and to invite everyone interested to the sprint demos.