Complexity is the enemy.
When it comes to software, there's an undeniable correlation: all else being equal, a more complex piece of software will be more buggy, less secure, and less useful. (You can probably generalize this to the real world, but that's really outside the scope of what I was intending to blog about today. >_>) And yet, for some reason, people insist on creating incredibly complex applications.
It's completely possible to write 100% bug-free code. The trick is to make the program simple enough that you can keep the whole thing in your head at once. For example, here's a program I finished the other day. It's short, simple, and I can guarantee that it's completely secure and bug-free. You may legitimately argue, but what if I want a program to do more interesting things than that?
Once upon a time, a bunch of really smart people went down this same line of reasoning, and UNIX was the result. The fundamental concept of UNIX is basically an approach to managing complexity - you write programs in such a way that you can use them in other programs. (Appropriately, UNIX is itself a simplification of another operating system - people used to joke that it was "castrated Multics". XD) This ended up being such a robust approach that today, nearly four decades later, it's basically unchanged in modern UNIXes.
But something, somewhere, went horribly wrong. Today we have all these fancy graphical interfaces, and somehow they ended up being incredibly complex. The complexity gives us software that does some pretty nifty things, but it comes at a price - software in general is less reliable than it used to be. There's collateral damage too; in a GUI, you can't stitch programs together the way you can on the command line. When you hear somebody complaining that the command line was better, it's not just nostalgia, it's the bitterness that comes with seeing a fundamentally superior system discarded for one that looks prettier.
We are long overdue for a radical simplification in program design, though plenty of things have been tried. Some programs (generally UNIX) take the approach of splitting off the core functionality of a program into a separate library, or calling command-line programs from the GUI, but this is often a pain. Object-oriented design was an attempt to make code more intuitive rather than less complex, and it succeeded, but only to a certain extent. Unit testing tries to gain the benefits of the old UNIX model with respect to bugs, and it succeeds, but takes a lot of effort, and doesn't address a lot of other problems of complexity. Use of higher-level languages takes care of a lot of complexity, but carries some performance tradeoffs, and for some reason rarely occurs in practice. No, a real solution will have to be something completely new.
This isn't just a code issue, either, it also affects user interfaces. Apple understands this really well. I can't set the time on a microwave without a lot of trial and error, but I can operate an iPhone - a much more complex device - pretty much intuitively. Programmers are almost always bad interface designers, and designers are almost always bad programmers, but Apple seems to have found a good balance. Here, ironically, the shoe's on the other foot when it comes to operating systems, since Linux is host to some pretty atrocious ones - Blender and Gimp spring to mind, though the latter has improved recently.