WorryFree Computers   »   [go: up one dir, main page]

On Building Software

How I Build Software (Like a Musician)

Ka Wai Cheung
On Building Software
5 min readFeb 28, 2024

--

I don’t build software the conventional way. Not like an architect would build a house. With engineers, developers, project managers, guidelines, detailed specs, excessive planning, every detail scrutinized, and approval after approval.

Not like that.

The most popular methods of building software have their roots in traditional architecture for no good reason. There is no significant relationship between building a house and building a piece of software.

Software is two-dimensional. You can move large pieces of code around anywhere in a codebase with your fingertips, not flatbed trucks.

Then move it back just as easily.

Code doesn’t wear.
It has no weight.
No cost of transport.
No dimension.
No proximity.

The traditional methods of building software are often roadblocks — they get in the way of the chaotic madness of a creator’s mind. The kind of mind I’ve come to recognize as my own.

Think about songwriting. Musicians don’t start songs by drawing notes on a sheet of paper. They start by playing. Fumbling a bit. Then finding it — however small it is — that magical turning point that drives the song all the way home.

There is no order to songwriting. The bridge might come into shape first. Melody before lyrics. Lyrics before melody. Half of everything before any of something. Change the chords, change a word, speed up, slow down, add on, or strip down to get to a final destination not quite planned but always someplace better.

All songs have melody, lyrics, tempo, and structure. While there is formula and science to a good song, there is no singular formula for how a song should be written.

I build software more like a songwriter writes a song.

Every feature I build has the following arc.

At the beginning, I think I understand most of the feature. What the thing should do. How it should generally look. How it should generally behave. How you can access it. That kind of stuff. I rarely build something so new that it lacks any precedence.

But I’ve done this ride many times. I know I’m driving into fog — the beginning a mirage. There will be things unforeseen that inevitably take me off-course (both obstacles and opportunities). But I don’t build a map. I don’t plan too much. I just start.

The way to overcome the fog is to get close to the obstacles. See the detail of the terrain so you know how to overcome them. You get close to them by starting the work. Very few times is an obstacle so large it requires me to turn back. I usually can find some way around it — and if I can’t, this is where concessions can be made. This is how the feature begins to reveal itself.

Somewhere in the vast middle I run into my first surprise.

The only thing unsurprising about this is that it arrived. A small crack in the road. A giant hill to climb. A pothole. A detour sign around a rocky cliff. Who knows. It could live anywhere on the stack of the application. Sometimes caused by some previous assumption — however safe it felt at the time — that now must leave the room. And with it, many of its dear friends.

After I get by the first obstacle, I run into the second.

Same exact feeling as the first. Only a different place, a different context. Then the third. The fourth. The twelfth. At some point, I will see home. I might arrive later than planned (though this has become increasingly rare) but the path eventually solidifies. The fog lifts. I am driving, finally, gently downhill.

Common wisdom says to do as much up-front work as you can. Plan the trip from beginning to end to develop the confidence that you know exactly how it will go. The confidence, supposedly, is not a blind one. It’s backed by estimates, wireframes, briefs, user stories, and dependency timelines. By the end of the trip those artifacts become the evidence held against you during your post-mortem trial review.

Managers demand to know what went wrong.

Why did it take so long?
Why didn’t we foresee that obstacle?
Why wasn’t that edge-case considered?
How do we fix this so it doesn’t happen next time?
What other rituals can we add to prevent this?

The team must figure this out because that is what good teams do.

But, these are the wrong questions — because there is nothing to fix. Things will always veer off course either by intention or by the human limitations of foresight. The nature of creating anything.

I’ve spent years training myself to adapt to the wrongness, not to fix it. Scrapping the ceremony. Opening a path that leads toward those things normally not allowed in software development.

Embracing ambiguity.
Starting without over-planning.
Designing in code.
Improvisation.
Discovering things mid-flight.
Taking detours.

Faith.

I just used the word faith. Belief without evidence. Not an idea you normally want associated with building anything. Especially coming from someone who isn’t even particularly religious.

But what I might’ve interpreted as faith may be the result of a simple fact: I spend a lot of time working on the same product. Probably ten to twelve hours a day. Five days a week. But not spent in the way you might think.

Two to three hours in front of the screen, the rest not. I do some of my best work by just thinking — mentally gnawing on the problem at-hand. Maybe gnawing on one of those dozen obstacles I routinely hit during a feature build.

If nothing big is in progress it may just be some code I want to clean up. Something to optimize. Something to tidy. Something to refactor. Something to improve. Perhaps the beginnings of the next big feature. It’s always something.

The thoughts aren’t always continuous — they float in and out during conversation, a long bus ride, a treadmill run, eating lunch, folding laundry, while my kids are arguing over something again. I have become very good at looking like I’m present when I am not.

I admit this is not an entirely healthy approach to everyday living, but I find being immersed in these thoughts has kept me away from boredom for years. And boredom without an escape plan is also not healthy.

This consistent (if not continuous) mental noodling makes me able to build things end-to-end at a good pace. There is no division between design, development, testing, QA, front-end or back-end. My mind weaves through all the crevices of the product, not just some angle of it as one might on a larger team. And because of that, I’ve come to realize that the luxury of time spent thinking about the whole product is the real reason I have faith.

Faith that the feature will be discovered completely. Designed completely. Built completely. Tested completely. I am not wasting the time I have to work on anything else but to work on the product.

A single mind on a single thing for a long time is a powerful force.

--

--

Ka Wai Cheung
On Building Software

I write about software, design, fatherhood, and nostalgia usually. Dad to a boy and a girl. Creator of donedone.com. More at kawaicheung.io.