Jonathan Blow: Programming Aesthetics

This is a really great talk by Jonathan Blow, the creator of Braid. It may be titled "How to Program Independent Games" but it should really be called "How to Get Shit Done as a Programmer". 99% of his talk has nothing to do with games at all, and is generally applicable to anyone developing a large quantity of code. He discusses his notion of programming aesthetics (what is "good code") and how that notion has evolved from when he was a student to today.

The real force behind his evolution was the decision to go from having a pile of half-finished projects to finally releasing a game: to "be effective at getting things done". He recognized that shipping a game is a monumental task, and that you must be brutally effective to achieve it.

A few of his points:

Impulses to Optimize are Usually Premature. Optimizations demand assumptions, assumptions constrain you in the future. They typically result in code that is trickier and harder to understand later.

Most code is not performance sensitive. If only 5,000 lines out of 100K were really performance sensitive and you made sure all the code was fast, you've wasted at least 95% of your time, almost certainly at the cost of maintainability. This is true for Jonathan Blow's case where he's thinking about frame-rates and whatnot, obviously. For other applications, like UIs, performance is measured in user performance, and I would state a corollary: most UI elements are not performance sensitive either. Let's say I introduce some speedup or shortcut in the number of gestures needed to achieve X, whittling it from 5 clicks to 4 clicks. But if X is a rare operation (once a day) rather than frequent (once a minute), then I've really wasted my time adding complexity to the code, making the assumptions, and adding the logic to eliminate that 5th click.

And yet someone will point out, "but it's not PERFECT!" Perfect in what sense? Getting down to 4 clicks is potentially flawed in EVERY OTHER dimension of reality that actually matters: time spent & opportunity cost, code complexity, inflexibility in the future, stuffing the UI with busy panels full of random shit, etc. Again, use your judgment and settle priorities definitively. And keep in mind, there are different ways to assess the value of reduction; there are absolutely situations where something occurs rarely but is extremely important to optimize. For example: the initial signup. 

A generalized system is usually worse than a specific/hardcoded one. Typically you think, "oh yes if I make this generalized then it can be useful for all sorts of inputs and do so many things." But if you only actually used two cases out of 20 then you've not only wasted your time but also made your work harder to understand... 

Generalized systems are usually less self-documenting than specific ones. (Such a good point, at 26:00m) In fact, they are downright, literally, obfuscated. When confronting a generalized system, perhaps you initially think it's fine to delete something; but as it turns out, that something affects something else that affects something else and then you have a mess. With specific systems, you can look at them, understand totally what they do, and delete or refactor with confidence.

For example: an endpoint that takes ten optional parameters, yielding twenty  different results depending not only on what inputs you provide but also their values. Is this really better than five endpoints that each do something very straightforward? Is some marginal amount of "code reuse" really worthwhile? Think about it next time: this basic idea about code. Is this function intended to be generally usable or is it intended to be a one-off thing? It's really not helpful to obfuscate that.

Adding additional state is usually more bug-prone than a functional style. Generally, the less state you keep track of, the better. Keeping state is often associated with minor optimizations (to reduce fetches or requests) but often adds far more complexity than it's worth.