I Always Strive for Perfection
Writing software to meet the requirements of my business partners is my job. A lot of people do what I do, to varying degrees of success. Some people write software with the objective of getting the task done and moving on to the next task. In other words, treat it like any job where the goal is to finish all the work in the backlog.
Every day, homes are built around the world, and most of them are not examples of perfection — they are built as inexpensively as possible while maintaining a reasonable level of quality. Achieving perfection in building houses would make building them take considerably longer and since it is largely a job of manual labor, it would cost significantly more. People don’t need perfection when it comes to homes — they mostly need them to be functional and safe. Everything else is mostly aesthetics, and perfection is a hard target to hit.
Software is different. Unlike a house, where if something goes wrong it can generally be fixed while people are still living in the house, software bugs can prevent users from achieving anything. Therefore, the standards for software need to be higher. Rigorous testing needs to happen to ensure that the software doesn’t crash or have undesired behavior. Sometimes software has to be delayed until it is ready. Sometimes it never gets released at all (Imagine if leaving houses abandoned and half-constructed was a regular occurrence — in software, it often is).
When I write software, I always strive for perfection. I often return to code I have written before if I think of a better way to execute something. I am never done learning new techniques and methods of achieving the goals I have set out when writing the software. The challenges that writing software presents are much harder than most people are aware of, and even the most seasoned developers will encounter problems that they don’t immediately know how to solve. Lots of people learn to program, but far fewer really learn to engineer and architect solutions the right way.
Code Smells and Anti-Patterns
As software engineering became more of a mainstream occupation, a large number of books were written talking about patterns of development. One of the most famous of these was a book called Design Patterns: Elements of Reusable Object-Oriented Software by by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. These patterns were really informative and helped a lot of engineers build better software from the ground up.
This started a large trend of other books with the same idea, expanding the range of patterns. Soon the concept of the anti-pattern emerged (in other words, things not to do) as well as the code smell (something that is generally a sign that you are using types, patterns or frameworks for the wrong reason). It has gotten so that you can’t do a Google search without getting 20 different opinions on what is a pattern, an anti-pattern, or a code smell.
I believe it is gone way overboard. Now I see people hunting through software that works, looking for anti-patterns and code smells. While I believe the intent is noble and just, the downside is that it has started to distract us from the real purpose of writing software: delivering working software that meets the requirements of our business partners. In other words, we have over-corrected — we are striving for perfection so hard that it starts getting in the way of actually delivering software.
I think no story exemplifies this better than the story of General Magic — a company that was formed with some of the best talent that Silicon Valley had ever seen (there is a great documentary film that talks about the company in detail). They were founded with a vision of bringing computing to everyone in a form factor that was small enough to carry around in your hand. This is something we take for granted today, but at the time, it was unheard of to have a computer smaller than a briefcase.
Unfortunately, General Magic failed. Badly. After ten years of product design, coding, and endless hours of testing, the company managed to only deliver one real product, and it mostly was bought by the friends and families of the engineers who worked there. So what had gone wrong? Why had the smartest engineers in Silicon Valley failed to deliver on a vision that so closely matches the world we live in now?
I believe their vision was right on target. I believe the engineers were full of great ideas and were definitely ahead of the curve. Some of the world’s greatest companies backed General Magic, launching one of the first and most successful IPO’s in the history of computing. Sony was one of the largest backers, incredibly successful in the world of building personal electronics like the Walkman. Such a partnership should have guaranteed that General Magic would succeed.
The problem really came down to delivering working software. The engineers were given a lot of freedom to decide which directions to go and what the deliverable was going to look like. Creative and talented software engineers are often perfectionists, and this led to a lot of time spent trying to get everything just perfect. Deadlines started approaching and passing without a real product. This continued for months and months until finally it started to become clear that if they didn’t deliver something soon, their big partners like Sony would pull the plug.
They finally launched a product, and in retrospect, it wasn’t a bad product, but it also wasn’t really what people wanted and only a small number were sold. The atmosphere at the company went from being full of energy to one of sadness and defeat. The company laid off a large number of staff. Some people didn’t even come back to work for a while. Eventually the company filed for Chapter 11 and was mostly forgotten.
There is an upside to this story, however. The ideas that General Magic generated were carried forward and eventually formed the foundation of some of the products that Steve Jobs helped create at Apple. First there was the iPod, one of the most successful computing products ever created. Then came the iPhone, followed by the iPad. Some of the early drawings at General Magic closely matched the iPhone design, and the vision they had hoped to deliver was finally realized. It is a bittersweet story, but in a way, it gave those engineers at General Magic some redemption for all of the hard work they did that resulted in failure.
In the two decades following the dissolution of General Magic, software has largely gone through an incredible revolution that has made delivering software on time while still striving for perfection much more possible. Instead of writing large business requirement documents and then using waterfall processes to write software, companies have turned to Agile methodologies where teams focus on small bits of functionality that can be delivered in just a few weeks.
Imagine if the engineers at General Magic had been concentrating on one small feature at a time, presenting it to users, and then deciding the next feature to work on based on feedback from the users. The iPhone might have come five or ten years sooner than it actually did (Note: I am glossing over the fact, however, that a lot of the hardware that made the iPhone possible wasn’t really available when General Magic was in business, but who knows).
One key component of Agile is that perfection isn’t the goal in the short run — the real goal is to deliver something to the customer so that they can see it and use it and decide if the team is going in the right direction. If they are going in the wrong direction, the team can stop and change direction sooner — we call this failing fast — which saves the team from spending weeks or months building and trying to perfect something that ultimately doesn’t meet the business requirements.
It also has the side effect of forcing the business to focus on what requirements really are the most important instead of thinking of every single requirement. Businesses often dream up a lot of features that don’t really get used. One reason Apple was so successful under Steve Jobs is that he steered the company to focus on delivering a great experience rather than wowing them with tons of features. How else could a phone with only one button really have been better than a phone with a full keyboard like the Blackberry?
These features of Agile also raise the central point that I am talking about today — there is such a thing as good-enough software. Perfection isn’t so much a goal in the short run as it is a direction we strive for, even as that direction changes from day to day. Agile has allowed us to better find the balance between delivering on our promises while still building something that is well engineered.
Patterns, Anti-patterns and code smells are still useful tools, but they are more of guidelines than hard and fast rules. If the engineers at General Magic had spent all their time ensuring that they stuck to patterns and avoided the anti-patterns and code smells, they would have still failed. At the end of the day, you still have to deliver, and so good enough is often just that.
Software engineering is a field where we often strive for perfection. Software that is better engineered will generally work better and allow users to be more productive. Engineers have written books about patterns, anti-patterns, and code smells to help other engineers avoid the pitfalls that they have encountered in their efforts to build better software. These are great tools, but striving for perfection can distract us and cause us to fail to deliver a working solution.
Companies like General Magic are great examples of when striving for perfection led to complete failure to deliver and ultimately the demise of the company. Methodologies like Agile have come along to help us maintain the balance between delivery and perfection, and while we still may talk about patterns, anti-patterns and code smells, sometimes we can just move forward with something that is good-enough.