A Pattern Language for developing software
Inspired by Urbit Precepts and the Design Principles Behind Smalltalk
- Local first. Decentralized/distributed systems second. Make self-hosting easy
- There is a latent cost to new features: maintenance
- Heuristics should only be used where determinism is infeasible
- Apps should embrace gradual enrichment, composing smaller features to form more complex ones when necessary
- Dump the parts bucket onto the floor. Make it obvious what tools the user has at their disposal to make the most out of the software (constructionist learning)
- If a system is to serve the creative spirit, it must be entirely comprehensible to a single individual
- Any system should provide a uniform means for referring to the things in its universe. In fact, an even stronger statement is that systems should be designed around a powerful metaphor that can be uniformly applied in all areas. Only from this can complex systems emerge
See also: programming models
On programming advice
Jamie Brandon’s Reflections on a Decade of Coding
Programming practices are mostly tacit knowledge. Tacit knowledge isn’t easy to share. An expert will relate some simple-sounding rule of thumb, but then grilling them on specific cases will quickly uncover a huge collection of exceptions and caveats that vary depending on the specific details of the situation.
It’s so easy to think that simple solutions exist. But if you look at the history of ideas that actually worked, they tend to only be simple from a distance. The closer you get, the more you notice that the working idea is surrounding by a huge number of almost identical ideas that don’t work. Take bicycles, for example. They seem simple and obvious, but it took two centuries to figure out all the details and most people today can’t actually locate the working idea amongst its neighbours. Even when old niche ideas make a comeback (eg neural networks) it’s not because they were right all along but because someone recognized the limitations and found a new variation on the idea that overcame them (eg deep learning). Finding the idea that actually works amidst the sea of very similar ideas that don’t work requires staying curious long enough to encounter the fine-grained detail of reality and humble enough to recognize and learn from each failure.
Mainstream is mainstream for a reason. The frontier is the place to go mining for new ideas, but it’s 1% gold and 99% mud.
For playful software
- Extremely easy to use. “The prime directive. The program should be extremely easy to use. No manual should be needed and program features should ‘explain themselves’ through use. All tasks should be able to be performed in the simplest, most straightforward way. The program should go out of its way to meet the user.”
- Surprising and satisfying. “As long as The Prime Directive is not violated, every opportunity should be taken to make the program surprising and satisfying to use. No opportunity should be missed. The process of making a picture should be as important as the picture produced.” This can be haptics, sound effects, satisfying animations, intermediary feedback, etc.
- Low floor, high ceiling. The program should be extremely accessible by default, but allow for very complex functionality. Toward this, I’ve been trying an expert mode toggle, like taking off the training wheels. (see also cognitive dimensions of notation)
- Encourage messing around. Make actions undo-able, and permanent destruction near impossible. Make it easy and quick to iterate. Unstick people – even random color pickers help.
- Real-world “interoperability.” The more people can bring in their existing knowledge – artistic abilities, drawing, writing styles – and integrate the outputs of the software into their lives – send a friend a link, transferable skills, show a printed poster at home – the better. The “less segregated from ordinary life,” the more natural and frequent its use.
Above all, people need agency. They need to feel in control. Sometimes, that means designing for subversive behavior. I mean, isn’t the most fun often had when you’re breaking rules? But this is enormously difficult in software, where you must design almost everything from scratch. Unlike life, you don’t get a common repertoire of actions for free – burning, tearing, bringing friends in, etc. How do we design for baseline functionality and unexpected, emergent play?