> See React

What about React? They say right on their front page: “Build encapsulated components that manage their own state, then compose them to make complex UIs.” That’s a textbook definition of OOP.

> it is better to deal with it without using OOP

That’s a famous example but why do you think it’s always better? Sometimes, like when dealing with graphs, holding the jungle with the banana is exactly what you want.

> If the focus of your code is reusability and modularity

My primary focus is meeting requirements and budget. All technical decisions about reusability, modularity, performance, and the rest of them, are driven by these two.

Some projects don’t need reusability at all, because that’s research, or a proof of concept, or a video game that won’t be maintained once launched.

In other cases, being too aggressive about eliminating duplicate code can harm long-term maintenance. More likely to happen in higher-level parts. You introduce an abstraction, then you need to handle just one special case where the code being reused needs to behave differently and introduce a parameter. Repeat a few times and you now have tons of parameters, flags, and other crap no one understands, not even you. This happens regardless on OOP/FP/procedural, the crap is different in these cases but its effect on maintenance cost is equally bad. Wouldn’t happen if you would be more conservative about introducing abstractions, and instead copy-pasted a few lines of code here and there.

> for most modern programming the performance cost is no longer a factor that matters

Almost everything has a performance budget. For a web app difference between 1ns and 1ms doesn’t matter at all, but difference between 100ms and 1 seconds still matters, users will complain, search engines will downrank. Desktop apps ideally need to respond within 17ms because mainstream displays render at 60Hz. Performance cost of immutability is huge, can be 1-2 orders of magnitude, for 2 reasons. (1) memory allocations are relatively expensive (2) CPUs have cache hierarchy, main memory is like 20-40 times slower than L1D cache, each time you allocating a new immutable object it’s pretty much guaranteed to be out of caches.

Still, there’re many cases when immutability is fine. C# immutable structs are awesome, unlike classes they’re free in terms of memory allocations, and they are usually on stack which guarantees they’re well cached. The upcoming C# 9.0 has a language support for immutable classes, pretty sure I’ll use it a lot once released and debugged.

> Games and Databases are two examples where FP may not be the most appropriate paradigm due to the performance critical nature of the areas.

Also CAD/CAM/CAE, realtime multimedia, some projects in embedded esp. real-time stuff. By the way, these areas are what I mostly do for a living.

> If your class does not hold mutable state then essentially it's just a class repurposed as a namespace with syntactic sugar

I like that sugar, and using that approach quite a lot in my code. For example, private methods and fields are invisible from outside, makes life easier because they don’t show in intellisense. I disagree that OOP promotes mutable state for cases when it’s not needed, it all depend on the language. JavaScript or Python don’t support immutable properties of their objects, but C# and (to lesser extent, but still) C++ do.

However, the real value of OOP is when you have to deal with complex mutable state. Every single time mutable state is essential to the problem (rich GUI is just one area where it’s the case, there’re others), OOP has no good alternatives.