In big programs the programmer has to make many decisions. Decisions become constrains. Constrains become assumptions. Next, writing with many assumptions is tricky. A genius programmer can keep many assumptions in his head at the same time, but the human abilities are still limited. Code decomposition organized in a way that separate parts require less number of assumptions is a solution. However, it leads to inefficiency of the code, because knowing more internal details of separate modules allows more efficient interaction but causes tighter interconnections between them.
Hence, there is a dilemma for big program: either having more assumptions and risking introducing bugs by human mistakes breaking some of the assumptions, or, having greater decomposition introducing inefficiency in memory and execution. For small programs, neither is a problem. For medium programs, a balance between the two can be achieved. But for big programs, both sides impact hard: the program is inefficient due to decomposition and has many assumptions allowing introducing bugs.
Hence, there is a dilemma for big program: either having more assumptions and risking introducing bugs by human mistakes breaking some of the assumptions, or, having greater decomposition introducing inefficiency in memory and execution. For small programs, neither is a problem. For medium programs, a balance between the two can be achieved. But for big programs, both sides impact hard: the program is inefficient due to decomposition and has many assumptions allowing introducing bugs.