Software design is an art. It’s the product of spirit, not the fruit of deductive analysts. There isn’t an algorithm, method, pattern, technique, or artificial machination that can craft good software.
Software is a creative art form led by a muse. The muse is tapped into by concentrated diligence, focus, thought, and years of preparation. It leads to moments of insight, followed by hours and hours of thinking, coding, and thinking some more. This is where great design comes from.
But don’t get me wrong, I don’t sit around and wait for my muse to come. Muses work like an excellent meal—with high-quality ingredients.
The raw materials of design might be notation, a clean workbench, studio, easels, paints, skill, and knowledge. A musician needs to know scales. A painter needs to understand hues. A sculptor needs a keen eye for negative space. A writer must have a sense of style.
For the highest ingredients, an artist needs to study all the works that came before, both good and bad. A good software designer studies how things work in their field.
This is so the designer isn’t hobbled by ignorance or polluted by preconceived notions. Wide exposure to the craft puts things in contrast more clearly.
Knowledge alone, though, doesn’t translate into skill. We build on the foundation with hours and hours of practice.
It doesn’t matter if the practice happens at the easel, writing desk, or workbench. Creatives throughout history have drawn from paintings of the masters, and written bad song after bad song until they got to the good ones.
Designers practice to the point that the craft becomes second nature. It’s like touch typing on the keyboard. When the muse strikes, we create without a second thought.
A good musician can listen to a song and reverse engineer its structure. A good coder can see a user interface and instantly picture the underlying code’s structure. Sometimes the mental picture is better than the original.
A good coder can look at code they haven’t seen before and start talking about how it works. Keywords emerge from letters. Ideas spring from symbols and white space. Visions of registers and sequences appear along with mental drawings of boxes, lines, and arrows.
Code is the design in the same way writing is. Once the words are on paper, the writer doesn’t need to be involved in the publication processes. There are plenty of people who can print books and deliver them to stores. The art is in the words.
For the coder, the “publishing staff” is the compiler and loader. This software turns design into something of service.
The first program I ever wrote, as simple as it was, taught me this. Coding was magical in that I could sketch something on paper, pick it up, and go. It was as if I could draw an engine and it would just work. Or not work, but I could redraw it. There was no long process of making each part and fabricating them out of metal or assembling the oily mess before testing. I just compiled my design.
This high art isn’t really so high. It’s what should be expected of everyone who makes a living programming for the public. It’s a skilled profession, that begs for inspiration and strives for higher and higher professionalism.
Sure, you can hack code together like you can quickly finish a paint by numbers. It’s like these blogs I see with mountains of short, content-free posts regurgitating oxymoronic “conventional wisdom.” They’re often written by people who read 500-word digital marketing posts about how to put equally flimsy “content offers” behind email walls. It’s like answering a newspaper ad on how to make money in the classifieds, spending $9.99 only to find it’s to run ads about how to make money in the classifieds.
Sure, you can use Grady-Booch’s method and force a bunch of programmers into a rigid and religious agile formation. They’ll plod on forever and create more and more code that does less and less. The bloat and bugs will grow into a slow, uninspired, self-serving mess all thanks to a misguided management team on a mission to get rich quick either by IPO or acquisition by a larger company. Everyone will abandon the code for the next startup in a never-ending biannual march to oblivion.
Sure, you can do that. And you can inflict pain and suffering on the user, the poor person who is unaware of security breaches, design methodologies, agile organizations, and massive software repositories scattered over hundreds of laptops.
All that those poor users see are bugs and confusing interfaces that slow with each release. Never in the history of the world has so much incredible hardware done so little for so many.
Knowledge of the User
Software design, like all design, must center on the user. They are the reason for the software in the first place. A good thing about modern approaches to software development, at least in their original manifestos, is their recognition of this fact.
They demand that the user is involved. They must be incorporated into the process, sharing ideas about what works, what doesn’t, and why.
But somehow this mission gets lost in management’s implementation of these approaches. They sprint along without a user in sight. It’s to the point where agile companies bear no resemblance to agile development. It’s easy to see why the user is lost when people work 18 hour days to add every half-functioning feature management demands.
Even if the software design includes the user, it’s not enough because it’s rare that a user understands data structures. Consulting users is good, assuming they can help the designer reflect on the design, but a programmer must know the user’s experience intimately. Designers need to do the user’s job for a while and feel the user’s pain.
This process doesn’t only last a day. It takes as long as it must for the programmer to instinctively see solutions to the user’s problems. I’ve known designers to ride in an ambulance each night for a couple of months. The system to help ambulance drivers that they created was fantastic. There is no replacement for understanding.
After building knowledge, practicing hard, and learning to see the world through the user’s eyes, it’s time to get quiet. Stop. Think. Sketch. Wait. Wait some more and eventually the ideas will start flowing.
Sometimes it takes a while. Sometimes the thoughts you had during the research part of the development spring to life quickly, but usually not. Once it starts, though, it floods. Keep a notebook, a stack of paper, or an app on hand. Whatever you use, keep jotting down the ideas as they come.
Language is a mysterious thing. Verbalization creates thoughts. Thoughts create words which in turn improve thoughts. This is the process before design. A narrative is always useful.
Now start coding. Compile soon and compile often. Think. Compile. Test. If you don’t like the word “test,” call it “running,” but do the loop many times an hour. Coders are deceiving themselves with claims that they can imagine all the bits and pieces and then just write. You must code. Code is the design!
Where to start is as much an inspiration as the overall plan of attack. Depend on the muse for that as well. Often the place to start is where the data enters the system. Or it might be the part of the system that grabs your attention most. Other times it’s best to attack the most daunting parts. Like dragons, they must be turned into windmills.
However you start, code. Code like the wind. Throw stuff out and code again. Fred Brooks said you can’t really write a requirement document because so many of the requirements are embedded in the design itself. You can’t define the interfaces first, but you must end with good interfaces. The only way to do that is to create, throw bits out, and attempt again.
None of this is possible unless you get quiet and let the wind blow in ideas. Listen for the muse. If it’s slow in coming, write little bits and pieces and wait. If you wait, assuming you have the knowledge, practice, and love for your users, the muse will come. It’s as sure and natural as a nurtured seed sprouting.
When it finally does come, start. Code will emerge and grow in layers. Code will be tossed. Edit, compile, test, repeat. You’ll have brilliant ideas and not know where they came from. It’s all from the muse. Who knows where the wind blows?
Some folks create more effectively on a fixed schedule. John Cheever went to a basement office for eight hours every day. Others of us have to strike while the iron is hot, no matter the hour.
Listen to your own creativity, and learn what works best for you. Ken Thompson’s hours rotate on a greater than 24-hour schedule. Dennis Ritchie would show up for lunch, spend the afternoon at Murray Hill, go home, watch TV, and then work until the wee hours of the morning. We all have to learn how we work best.
Creativity and design are innate in all of us. Just read more widely and you’ll see that I’m not saying anything new. Writers, painters, and composers have learned this. Our makeup is just young and getting younger all the time. The average programmer is still in their twenties. Youth, especially those that focus on technology, often forget to explore the best parts of the humanities. As a result, there are waves of programmers that have to learn these human aspects of their profession over and over again, realizing why Donald Knuth titled his book The Art of Computer Programming.
Why do we forget to wait for the muse? Why does it take a mere seven years for the software world to regress back into thinking it can schedule design?
I suspect it is a need to be in control. In an age of two-day shipping, we expect to create on demand. This need bleeds into all aspects of life. We are the instant society, and we must have everything fast. And it has got to be under budget.
Wisdom oscillates with the regularity of the planets. We see we’re not in control and it’s humbling. Then we refuse to admit our humanity and blame the programmer or the user. We’ll blame anything other than face the fact we’re not in control of much.
So be in control of the little you can. Do the hard work of building knowledge. Practice by copying the masters. Ride in the ambulance every night for a month. Then wait for the muse.