My own list of (some of the many) reasons not to use an object oriented approach that come to mind in my daily work. Started after writing this comment
I've seen quite a few good projects written in an "OOP" language, but not in an OOP style - mostly misuse classes for namespacing (which I don't think is a good idea either since it makes usages of namespaced things hard to find).
I've never seen a "true" OOP project that wasn't quite a mess and couldn't have been written much cleaner in a plain old procedural style:
Use freestanding functions, the most successful abstraction to date.
Stop the singleton BS. Most things that need to be managed exist precisely once in a program (talk to the sound card, to the printer, to the network, to the graphics card, to the file system, allocate memory...). Making classes first and instanciating once (or how many times, how can I know by looking at that handle?) is just plain silly, overly verbose, and confusing to the consumer of the API.
Don't couple allocation and initialization. It's a stupid idea. It leads to pointless, inefficient, and (in some languages) error-prone one-by-one allocations.
Flat fixed structs for data organization. By default expose struct size for massive decrease in memory allocation. Expose almost all fields (except for truly platform / implementation-defined ones) and stop with that silly getter/setter boilerplate.
Mostly use data tables (with direct integer indexing mostly) like in a relational database, for data-driven architectures. (CS/programming technology TODO: How can we switch between AOS/SOA more seamlessly? Maybe we can get inspiration from Graphics APIs?)
Don't use silly flexible-schema XML/object hierarchies to "compensate" for having no idea what's in the data. It doesn't help.
Make interfaces ("vtables" if you will) only sometimes where they are needed, not by default. Don't call this inheritance. Bullshit. It's an interface, not more, not less. If you think interface descriptions must typically be bundled with each data item, think harder. They are independent data.
We don't need no friggin "doer" objects for every simple thing. It doesn't help a bit, but only makes things less readable and more complex. Just do what needs to be done!
Update: Some more rants I left somewhere. Not coherent arguments, and lacking context, but nevertheless all true :-). I just feel like putting them here
(I feel a little bit cynical today and will say it's typical to C++'s attitude (as opposed to e.g. C): Let users make overcomplex programs more easily, by papering over all the insanity, instead of forcing them to make a clean design).
(And as usual with OOP, you end up with terrible inefficiencies (too much allocation in this case), since the program is split into needlessly isolated parts in a futile attempt to make them "self-contained". In the end, what that does is also make everything less efficient and more complicated. And redundant, if you care to look at what actually happens as opposed to what the programmer writes).
Another important aspect: Being required to "bless" functions to operate on datastructures by making them official "member" methods leads to really intertwingled dependencies. This is totally counter to the ideal of reduced coupling that OOP promises. In reality it leads to much *more* coupling, which is one of the worst aspects of many OOP languages. The better solution is to just put free-standing functions in optional modules so as to not increase dependencies by default. In the same way, declaring private members and methods in the interface (as it is required with most OOP languages) is really bad dependency hygiene.
Created: 2017-12-17. Last updated: 2018-03-12