This is a good point. Strictly adhering to just one style, either OO or FP, seems very limiting. Instead, this blog suggests guidelines. My favorite line from the post:
"Those that are unlikely to change but are subject to being operated upon by a changing cast of entities should be written in a more functional style, while those things that change relatively often can be written in an OO style"
That's the expression problem. But you can have the best of both worlds with various approaches. One nice one is called tagless final encodings in fp and object algebras in oop.
In haskell this is called mtl-style classes and quite common. Here is a blog post that describes how to split applications into an imperative, oop and functional layer. The oop layer uses mtl-style classes: https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_c...
I can understand that line of thinking, but I don't know that I agree with it. At least not fully. The biggest problem with OOP from a data perspective is that it shleps state around and that state can change in goofy ways, especially when you introduce threads. I think this is where immutable functional programming really shines. I do realize there's a lot more to consider though when architecting a particular solution.
Totally agree, I would introduce immutability in OO to address Concurrency issues. In short, picking the best of both worlds.
Where the conflicts arise is when we have stateless functions. It's a bad practice from OO perspective to have stateless (or static) functions. I am yet to have a good solution to this problem.
Objects shine when they encapsulate complex state in ways that disallow illegal states to arise. The trouble starts once you try to add complex transformation processes (e.g. business processes) to objects. When they work on complex graphs of objects, you can't really put them into a single one of them as none of them is the obvious place.
What I found to work best is to build an OO data model and a (not necessarily functional) business logic layer on top. In pure OO languages like Java and C# this layer takes on singleton characteristics, which is a clear sign that this code should be simply procedural. The individual functions are often not very interdependent and easy to work on and test.
"Those that are unlikely to change but are subject to being operated upon by a changing cast of entities should be written in a more functional style, while those things that change relatively often can be written in an OO style"