So I was talking to a friend of mine (I dunno if he minds his name being on the internet, so for now he is Friend) about the Dijkstra talk I linked in my last post, and he pointed out something interesting. Basically, Dijkstra spends 15 pages or so talking about how useless it is to try and use analogy to understand "radical novelties". Then, he talks about how useless current software methods are, since they basically try to apply to software analogies which are a poor fit. Then... he suggests applying mathematical methods to software. Way to deal with radical novelty, Edsger!
Somehow I didn't notice that inconsistency, so props to Friend for that. What I did notice, at least in my mind, was how much weaker the second part of the talk was compared to the first half. If I were to take a wild stab at why, I would say that perhaps Dijkstra himself realized that formal mathematical techniques weren't a perfect fit either for software. It's too much of a reactive step; it solves the problems of the current paradigm but replaces them with plenty of new ones.
What, then, should we do instead? It will surprise approximately none of you that I have an opinion on this. :) I haven't quite worked out how it would look (yet), but I think an ideal solution to managing the complexity of software would be to manage as little of it as possible; or, in other words, to get the computer to do the work for you. Computers are astonishingly good at doing regular, repetitive tasks. We need to find those tasks, find some way to make the computer take care of them, and then look at what's left over and repeat.
In other words, rather than logic and proofs, I would teach automation as the fundamental building block of programming. This works in two directions - programs should be designed not only looking down, at the task they immediately perform, but also up at future programs which may want to use this program as a building block. (This is why GUIs are no good - there is as yet no good way to use a GUI from another program.) This method also instills the correct frame of mind in the programmer, by making a clear split between things that computers are good at, and things that people are good at, and assigning responsibilities properly. These days, this split is all but ignored, which is how we end up with absurdities like people happily doing repetitive, automatable tasks, and then turning around and asking computer programs for (admittedly artificial) intelligence.