Here are some thoughts I'd put into the mix.

1. Software that is built to deadline will decay, even if the developers are good. That doesn't mean that an occasional deadline is the end, but if a long-term "deadline culture" sets in, get out. A long-standing deadline-oriented culture means you should be looking to jump to another project or company before the maintenance phase starts, because (1) the maintainers will be underappreciated (that's typical deadline culture) and (2) once the original architects get promoted it will be politically impossible to point out the real reason maintainers are unable to deliver in a timely fashion, and the slowest one to run away will get eaten by the bear. It means that technical debt will never be paid off; management will never budget time, and engineers will be too busy to clean up the code. Software engineers generally lack both the political pull and the broad-based knowledge to push back on deadlines and tease out which ones actually matter and which don't.

2. Entropy. Good software is less stable than bad software. Think of this as akin to the "broken windows" theory. Once software reaches a certain state of degradation, each change, although it might fix a bug or add a feature, will make the state of the software worse. There are creeping kinds of badness that can't be caught in incremental code reviews, such as adding 10 lines to a long for-loop or a "necessary" boolean parameter to a method that over time ends up with 15 boolean parameters. Often the managerial solution (once it's far past too late) is to put maintenance of this bad system on the calendar and make it someone's full-time job (instead of a shared responsibility) but no one wants that job and often that work is allocated to marginally skilled junior programmers with no clout. Then you get adverse selection: the more skilled people in that set will leave the project (or company) before they put in enough time to become decent at it.

3. "Pay as you go" maintenance, which includes periodic fixit spells, is always better than after-shit-breaks maintenance. That said, existing tools don't make it easy to revert quality degradation. IDEs really don't perform this function as commonly used. (I'm sure IDEs can be really powerful if well-learned, but people who are dedicated enough to master IDEs are also dedicated enough to jump wholesale to better languages for which IDEs are unnecessary and often poorly-supported. IDEs, in large part, exist to compensate for weak languages.) Code can rot in any language, but one advantage that languages like Scala and Python have is that, because they have REPLs, which are far more useful than any IDE, people can interact with the software at a code-level and fix things while the code is in that "moderately bad" state before it is too late. In 2012, I wouldn't start anything important in a REPL-less language. (C is not "REPL-less" because Unix is the C programming environment. C++ is, not on account of language intrinsics but because it has departed from the small-program Unix philosophy and is used for large-object programming which requires interactivity at a code level.) At least some programmers will have enough of a sense of ownership and citizenry to clean up failing code as they work with it, but if you deprive them of the REPL, the one tool that any good programmer will recognize as essential, they won't put in the work.

REPL or Fail: http://michaelochurch.wordpress.com/2012/02/07/repl-or-fail/

4. The transition from being a mediocre to a good and then to a great engineer is about moving away from being an "adder" (someone who increases codebase complexity and functionality, thereby having an additive business value-- ignoring long-term costs of complexity, which may or may not offset that additive value) to a "multiplier" (someone with broad-based positive effects that make the whole team more productive). Contemporary tools and programming environments (Java, C++, IDEs, IOC, dependency injection frameworks) are about helping more mediocre engineers become solid adders at the expense of the really great engineers, whose creativity is constrained by less powerful languages and tools. One of the goals behind Microsoft's professional certifications, the design of VB (and later, the hijacking of Java), and the attempted ghettoization of the command-line (which good engineers like) was to make it possible for huge teams of "commodity" programmers to be productive as adders, with the hope that "someone" would have the patience to staple together the zillion classes they cranked out. From an MBA perspective, this is a win, because 2-4 times more people are eligible to be adders, but it also holds people back from becoming multipliers. The long-term problem is that a team without any multipliers will accumulate complexity and the emergent design (because you want a solid engineer doing your design work, and you can't get them in commodity-programmer environments, "design" coming out of a commodity shop will be ad hoc) will be disastrous.

5. With a few exceptions, the real fuckups in software don't seem to be blameable on a single person. They usually emerge either from jobs no one does (because the people who care about them being done aren't in power) or that too many people do (once code has been passed over by too many hands, it turns to shit).