A plague of metaphors, which actually amount to fraudulent use of terminology, overwhelmed computer "science" in the early 1990s. As a result, engineering discipline can no longer be applied to standard computing paradigms.
First of all, metaphoric constructs induce design uncertainty. A call construct appropriate to a math calculation is applied to a driver operation with side effects. "Infinite" stacks and "sequential" peripheral calls aren’t really. A decision was made to "encapsulate" (hide) these difficulties, to pretend they are not there and ignore them in "abstract" programming layers.
Secondly, the misuse of terminology has made progress impossible, because it stymies discussion. An "object" is really a non-object, a "component" is really a non-component, API "specifications" fail to specify, and "tested code" isn’t. The theft of a term like "component" is really damaging, because it means you can’t even discuss the real solution without inheriting the object/method/side-effect baggage of years of voluminous anti-design.
A clean break has to be made, right back down to interrupts, DMA, real memory, and flat von Neumann programming on the assembly or microcode level.