All software comes with a version, some sequence of digits, periods and characters that seems to march ever upward. Rarely are the optimistically increasing versions accompanied by a commensurate increase in robustness. Instead, upgrading to new versions often causes regressions, and the stream of versions ends up spawning an extensive grapevine to disseminate information about the best version to use. Unsatisfying as this state of affairs is to everyone, I didn't think that the problem lay with these version numbers themselves. They're just names, right? However, over the past year I've finally had my attention focused on them, thanks to two people:
(Or why goto is worth keeping around in modern languages.)
A cool thing happened during a lesson today, and I wanted to try to capture the magic before it slipped through my fingers. It happened while I was trying to teach recursion (without ever using that word) using my side project, Mu. The experience got me thinking about the quote above, and wondering if there was a way to bridge the summits of C and Lisp without having to go through the “swampy lowlands” between them.
It's a common trope among programmers that a single computer contains enough bits that the number of states it can be in far exceeds the number of atoms in the universe. See, for example, this 3-minute segment from a very entertaining talk by Joe Armstrong, the creator of the Erlang programming language. Even if you focus on a single tiny program, say one that compiles down to a 1KB binary, it's one of 21024 possible programs of the same length. And 1KB is nothing these days; larger programs get exponentially larger spaces of possibility.
The conventional response to this explosion of possibilities is to observe that the possibilities stem from a lack of structure. 10 bits encode 210 possibilities, but if you divide them up into two sub-systems with 5 bits each and test each independently, you then only have to deal with twice 25 possibilities — a far smaller number. From here stem our conventional dictums to manage complexity by dividing systems up into modules, encapsulating internal details so modules can't poke inside each other, designing their interfaces to minimize the number of interactions between modules, avoiding state within modules, etc. Unfortunately, it's devilishly difficult to entirely hide state within an encapsulated module so that other modules can be truly oblivious to it. There seems the very definite possibility that the sorts of programs we humans need to help with our lives on this planet intrinsically require state.
So much for the conventional worldview. I'd like to jump off in a different direction from the phenomenon of state-space explosion in my first paragraph. Read more →
I've been teaching programming using my new UI for just about six weeks now, and it's been miraculous and endlessly fascinating to watch a young mind up close. I'm still processing many of my observations and lessons, but I want to describe how one of my students learned something I never meant to teach: consistent indentation.
The only thing I did to help him learn indentation was this: I never ever brought it up. Mostly because I just don't consider it very important, especially at such an early stage. When I wrote programs to demonstrate features I indented as I normally would, then I'd hand over the keyboard, and ignore the fact that my student was abutting each line of code with the left margin.
Six months ago I fell into a little gig to teach two students programming, and it's been an eye-opening experience. Where I was earlier focused on conveying codebases to programmers, I've lately been thinking a lot harder about conveying programming to non-programmers. I think the two might be special-cases of a grand unifying theory of software representation, but that's another story. For now I don't have a grand unifying theory. What I have is a screenshot:
Let me describe the tool and the problems that it tries to address. When I started out teaching I picked an existing platform that I'd always liked. But quickly I started noticing many limitations. Today's platforms are great for experienced programmers and one can do great things with them, but they are very alien to noobs, who suddenly have to learn many different things at once.
Literate programming advocates this: Order your code for others to read, not for the compiler. Beautifully typeset your code so one can curl up in bed to read it like a novel. Keep documentation in sync with code. What's not to like about this vision? I have two beefs with it: the ends are insufficiently ambitious by focusing on a passive representation; and the means were insufficiently polished, by over-emphasizing typesetting at the cost of prose quality. Elaboration, in reverse order:
My third guest post at ribbonfarm.com.
My second guest post has just been published over at ribbonfarm.com, on the subject of building capture-resistant organizations. Tl;dr - constrain individual discretion at the top, and empower it on the fringes. But the direct ways to do that won't work. What will? Read on →
I've just published the first of a series of guests posts over at ribbonfarm.com. Check it out.
If you're a programmer this has happened to you. You've built or known a
project that starts out with a well-defined purpose and a straightforward
mapping from purpose to structure in a few sub-systems.
But it can't stand still; changes continue to roll in.
Some of the changes touch multiple sub-systems.
Each change is coherent in the mind of its maker. But once it's made, it diffuses into the system as a whole.
Soon the once-elegant design has turned into a patchwork-quilt of changes. Requirements shift, parts get repurposed. Connections proliferate.
Veterans who watched this evolution can keep it mostly straight in their heads. But newcomers see only the patchwork quilt. They can't tell where one feature begins and another ends.
What if features could stay separate as they're added, so that newcomers could
see a cleaned-up history of the
Solution Read more →