The overall fraction might be small, however vast majority of software still contain substantial amount of code that does. Most serialization and DB access libraries do. For C#, this includes all framework-provided serializers (XML, data contract, etc.), the ubiquitous Json.NET, and my own one: https://github.com/Const-me/EsentSerialize
> OOP doesn't allow people to reason about complex systems
Respectfully disagree, ‘coz I have never saw complex systems that aren’t OOP. Even most compilers are OOP, take a look: https://github.com/llvm-mirror/llvm https://github.com/gcc-mirror/gcc/tree/master/gcc https://github.com/dotnet/roslyn
> An object can contain references to any other object held by the process
This is true for very small class of objects, like GUI controls with loosely typed event handlers, or objects that hold lambdas/functions that may capture anything at all (but the latter is not strictly OOP).
An object can only reference other objects of types that can be stored in its properties/fields. For many objects especially simple lower-level ones, this means objects can reference no other objects at all.
> have never seen an OOP code base less than 10x the complexity of the business problem it was built to solve
My guess is, you’re systematically underestimating complexity of the business problems solved by the code you look at.
In every case, codebase complexity was dominated by administrative overhead. My passing experience with apps written in C#, ASP, and PHP, tell me that it is the same story there, too.
This is my subjective view. One way you might understand my perspective (and perhaps even share it, to some degree) is to consider the act of adding a column to a database table, and how a typical OOP/RDB webapp codebase must change to incorporate a new DB value. (And this is only the tip of the iceberg, since usually adding a feature requires a view, an index or two, plus column and table changes.)
As you see, almost nothing common with your background.
For the kind of software I work on, if the code is 10x more complex than necessary, the software might fail the performance targets. Complex code is also prohibitively harder to maintain and debug. And esp.in embedded, quality requirements are just higher: web requests come and go, but embedded software needs to reliably work for days without restarts.
I think the reason why I’m generally OK with other people’s OOP-style code I see in the projects I work on, is that code is just better then what’s in an average web.app. Especially if the web app ain’t Google or Facebook, AFAIK for these guys, software quality translates to substantial saving on electric bills.
Unfortunately, OOP doesn't allow people to reason about complex systems, primarily because call-chains are totally unconstrained. An object can contain references to any other object held by the process, and this reference list is dynamic at runtime. In the presence of instantiation indirection it's even worse, even the concrete type of those references is unknown except at runtime.
There are code smells, and then there are architecture smells. One big architecture smell is when the incidental complexity of a solution vastly outstrips the intrinsic complexity of the problem. I have never (and I've been doing this a very long time) seen an OOP code base less than 10x the complexity of the business problem it was built to solve. It's sad to me that instead of asking why, they keep blaming the programmer/architect and inventing new complexity to mitigate old complexity.