programming is terriblelessons learned from a life wasted

How I design software

I am not foolish enough to say that the way I write software is the only way, but I am foolish enough to believe how I approach software design might be helpful. This isn’t about project management, or algorithmic strategies, but how I fumble around until something works, guided by the scars of past mistakes.


Research

For every good idea, there are probably three implementations out there already. If you’re lucky, one of them might work, and might even be documented. There could be some academic work too, that isn’t buried in a paywall. Search engines are your friends.

Being able to work out the right name for a problem will help you greatly in your search. This is the one advantage of a grounding in computer science — rich technical jargon to find existing work easily. This is opposed to the “which pokemon would I name this library after” school of thought.


Readmes

Sometimes it’s best to start with human language. Write a readme, it should explain what problem the software solves, what sort of features it will have, and the interface planned. Avoid the trap of writing a heavy specification, skip the implementation details. The job of the readme is to set expectations.


Implementation Strawmen

Come up with a number of vague ideas, roughly sketched out, and list their positive and negative features. Take these positive and negative lists and distill them into a small number of constraints.

Start again, but hopefully you’ll have less options to choose from. Once your constraints are settled, it’s a good time to move onto trying things out in practice.


Prototype

It is often cheaper to experiment and see what fails, rather than trying to work this out ahead of time. Prototypes are a great place to make lots of mistakes, and an opportunity to play around with rough ideas.

Beware: the only difference between production code and a prototype is deployment — it’s hard to justify rewriting things that work. Putting prototypes into production is the software equivalent of being hoisted by your own petard.


Get feedback as quickly as possible

Write the smallest program that runs to begin with, often just a skeleton or a framework stub. Get other people to write code that uses yours. Let them hack away at your library, and change it to match how they use it. Mistakes cost less to fix when you find them shortly after making them.

Don’t spend an hour writing code without checking it at least once. For the more strict among us, you may choose to test, type check, formally verify, or prove code regularly. The rest of us plebs should remember to avoid binge writing code without any feedback from the computer. It’s much easier to come back to coding a program if it still runs or compiles.


Make incremental changes

Small code changes are the easiest to recover from, but it’s often hard to break new features into small edits. People will use the term “legacy code” refer to code that is hard to change or maintain in this way (Apart from legacy code, the only other type of software is code no-one uses).

Small changes can include rewrites, if you can slowly migrate users from the old to the new component. You’ll still need to maintain the old code though.


Work alone

Sometimes it’s good to hole up and get yourself up to speed on the problem. For me this involves covering my desk in scraps of paper with diagrams and scribbles. Other times it’s clawing away at an interactive session, trying things out.


Take a bath, get some sleep

Although it’s good to be immersed in a problem, it’s easy to get lost or overwhelmed in it. Go outside, stay inside, read a book, play a game, socialise, or retreat. Inspiration will come from distraction. I highly recommend naps.


Work with a friend

The code i’m most proud is the code i’ve worked on with other people. It’s easier to keep to your goals if someone else will hold you to them, and you’re not attached to your ideas.

Humans will often talk about problems in terms of the solution they have in mind, so be patient and try and extract the rationale behind it, even if the idea doesn’t sound so good (This often surfaces as the X-Y problem).

You don’t have to agree on the solutions but it’s good to agree on what makes a solution good. You can compromise on the former, but the latter usually ends up making everyone miserable.


All of the above

I approach design as a process of refining a question until the answer is obvious, and I see the above as ways of doing it. I don’t always do them in a strict order, i’ll skip some bits, repeat others, and some i’ve missed out or forgotten.

Everyone will approach design differently, which is why it’s so much fun to work with other people.