It's "bad" because of three factors: (1) complexity, (2) inadequate motivation, (3) lack of understanding.

First, complexity. Bridges aren't doing several million operations per second. They either bear the weight or they don't. They handle a known temperature range. If it can function at -50 F and 120 F, then it can handle the typical 65 F day. With a bridge, people put a lot of work into solving a simple problem extremely well and reliably. Software can be developed this way (Unix philosophy) but most software isn't. Small programs are written to solve problems well, but often invisibly; large-program methodologies exist to get promotions for higher-ups.

There are few things in the world like software, which is pure logic. We don't have the tools to understand the complexity, and what tools we do have are often used to write more complex software, not understand the software we have (see: IDEs and their "four wheel drive problem" of getting people stuck in more inaccessible places.)

Second, a lot of "software engineers" aren't very good and don't have the incentives and leeway to get better. That requires lifelong learning and professionalism in the true sense of the word. We're not a profession. Many things define a profession, but some salient traits of professions are: (1) an ethical ruleset that supersedes managerial authority-- not only are you allowed to refuse your manager on ethical grounds, but you have to do so; "I was just following orders" is not an excuse-- and (2) an expectation and allowance that the professional will dedicate half (~20 hours per week) her working time to continuing education, networking, and other varieties of "off-meter" work that will never occur in a typical manager/subordinate context because they benefit the professional's long-term development rather than the manager's parochial goals, (3) a very high degree of autonomy in work regarding social-bullshit protocols, but with very strong restrictions on the things that matter (i.e. no one sets working hours or vacation limits over a research professor, but if he steals another's work or publishes results he knows to be false, it's career-ending). None of these apply to software engineering. (1) If you disagree with your boss about how things should be done on ethical grounds related to software quality or intellectual honesty, you don't have an appeal process. You just get fired. (2) Most software engineers, if they want to keep learning, have to do it on their own time; hence, the stagnation that sets in for all but the most energetic and ambitious. (3) Nope. Here, the software industry looks more like middle-middle class white-collar culture (show up at certain times, take orders) than upper-middle-class professionalism. The salaries are often professional level, but work conditions are merely white-collar.

In a truly professional environment, manager-as-SPOF is avoided like the plague and people have genuine incentives to do good work, not just enough work to appease the manager. The manager still has some power and influence, but the role is more like a graduate advisor than an overseer. Also, professionals are encouraged to build lifelong reputations and seek visibility. (In a typical software company, trying to do this gets you the smear of a careerist and a "socialite".) Professional environments motivate people to do their best work. Merely white-collar environments don't.

The third issue is that we simply don't have a good understanding of software. This may be derived from the two above: complexity and lack of professionalism. Or it may result from something else entirely.

We know that, theoretically speaking, "it's impossible to reason about code" (cf. Halting Problem). Well, my response invariably is that that's correct: it's impossible to reason about arbitrary code. But we shouldn't be writing arbitrary code. Ever. We should write simple code that doesn't rely on extremely high-level mathematical or conceptual insight (which we model as non-computational "genius", though I have no interest in getting sidetracked into the debate of whether we are or are not computers) to understand.

I think individual people are good at writing software. People don't usually set out to write "arbitrary code". There are many individual software engineers who (1) use only as much complexity as they can handle, and (2) act professionally in spite of the lack of incentives or requirements ensuring it. Which means that small software can be good. What I like about the Unix philosophy and small-program philosophy is that it enables islands of quality to exist, and eventually bridges between those islands, which can lead to generally decent systems even though it's GRAI (generally recognized as impossible) to have high quality in an entire codebase. Systems design is all about accepting the possibility of failure amid complexity. It's about using small components that do one thing really well and interchangeable parts, not single-program mudballs. Engineers get this. Managers, who conflate bigness (cf. interview questions like "what's the largest team you've ever managed?" and metrics like kLoC) with success, generally don't.

The problem is that, once a program has a certain number of hands pass over it, it turns to shit. Even if the original code was good, entropy sets in at some point. One bad apple spoils the barrel, and a "bad apple" doesn't have to be a bad programmer. It could be a skilled programmer who hasn't had a promotion in 4 years and no longer gives a shit. The reason why big-program methodologies generally produce legacy mudballs is that it's just impossible to prevent the "one bad apple" problem from corrupting the whole program.