All of us have been taught that software is “a series of instructions given to the computer,” and this is true. However, there is no field in which a set of instructions and the result of those instructions are so closely linked as they are in the field of software development. In other fields, people write instructions and then hand them off to others, often waiting a long time to see them carried out. But when we write code, there is nobody between us and the computer. The result is exactly what the instructions said to do, without question. The quality of the end result is dependent entirely upon the quality of the machine, the quality of our ideas, and the quality of our code.
Of these three factors, the quality of the code is the largest problem faced by software projects today. As a result, most of this book is focuses on improving code quality. I do touch on ideas and machines as well in a few places, but mostly the focus is on improving the structure and quality of the instructions that we are giving to the machine.
However, it’s important to remember that we are doing so purely because we desire a better result. Nothing in this book forgives a poor result—the entire reason that we focus on improving code is because improving the code is the most important problem we must solve in order to improve the result.
If any appliance in my house malfunctioned as often as my computer does, I would return it. Users (and sometimes even programmers) have become used the idea that “software just has bugs.” People seem to just accept that systems will bloat over time, becoming unmaintainable and unstable monstrosities that eventually have to be thrown away and re-written.
But none of this is inevitable. Instability, bloat, and various other code problems don’t arise out of some natural law of the universe that requires all software to suck.
Instead, they arise almost entirely out of complexity.
When we start off, our software systems are small and easy to maintain. But they all grow, in time. The average software system becomes large enough that no human being could hope to hold all of its code in their mind at once. This isn’t good or bad, it’s just a fact. Effective software systems are, as a whole, inherently complex. The only hope we have for working with these systems is to keep the individual pieces simple, so that when we look at those pieces, we can comprehend them. Programming, in essence, must become the act of reducing complexity to simplicity.
If individual developers don’t simplify the pieces of the code they work on, then those pieces become hard to understand. That makes them hard to debug, hard to modify, and hard to add features to. If too many pieces of the system become complex, the system as a whole can no longer be maintained. This is where nearly all the problems of modern software development arise from—individual developers adding complexity to the system instead of taking it away.
A good programmer should do everything in his power to make what he writes simple for other programmers to use and comprehend.
A lot of this book is about software design, the process of planning out the structure of your code.
Whenever you see the word “design” in this book, it refers to software design, not visual design, user interface design, or some other sort of design.
There’s always some amount of design involved in software, even if it’s just a quick decision before your fingers hit the keyboard. On a team of programmers, every person is involved in design. The lead developer is in charge of designing the overall architecture of the entire program. The senior programmers are in charge of designing their own large areas. And the junior programmers are in charge of designing their parts of the program, even if they’re as simple as one part of one file. There is even a certain amount of design involved in writing a single line of code.
Everybody who writes software is a designer.
Every single person on a software team is responsible for making sure that their own code is well designed. Nobody who is writing code for a software project can ignore software design, at any level.
However, this does not mean that design is a democracy. You must not design by committee. The result will be an actively bad design—one which makes things more complex instead of simpler. Instead, all developers should have the authority to make good design decisions in their own areas. If they make poor or mediocre decisions, these should be overridden by a senior developer or the lead programmer, who should have veto power over the designers below them. But otherwise, responsibility for the design of code should rest with the people who are actually working on it.
A designer should always be willing to listen to suggestions and feedback, because programmers are usually smart people who have good ideas. But after considering all the data, any given decision must be made by an individual, not by a group of people.
 If you are the one overriding a decision, attempt to educate the other programmer when you do it. Show how or why your decision is better than hers. If you do this, over time you will have to override that programmer less and less. Some programmers never learn, though—if after several months or years of such education a programmer continues to make numerous bad decisions, he should be removed from your team. However, most programmers are very clever people who pick things up rapidly, so this is rarely a concern.