>Worked with that in .NET a bit, specifically this one: https://github.com/reactiveui/ReactiveUI Not a big fan. For example, when I wanted to fix a bug, put a breakpoint to the code that failed, and reproduced, there was no way to tell who or why sent that event, the original context was already lost. For this reason I prefer simpler ways with interfaces or lambdas. Not sure if that’s a problem of the approach or the implementation I used. But generally speaking marshalling contexts is complicated and is a common source of bugs, YMMV.

The tooling is irrelevant to the paradigm itself as tooling can improve over time. Either way it's the dominant pattern right now for UI. I'm not an expert in it but I do know that the tooling for react/redux right now is quite good.

>I can see how it can be the case on servers (one reason is economy, for many companies it makes more sense to rent more EC2 instances instead of writing better software), but I’m not sure same applies to client. In the browser, you have the same 16.6ms performance budget for optimal usability. The fact that JavaScript is generally slower than compiled languages makes things worse.

In servers it's not a priority because the database is the bottleneck. Servers need to just be faster than the database and that can easily be achieved with something slow like ruby or horizontal scalability. The pattern in web development on the backend is highly similar to functional programming. Web servers are mostly stateless and state is stored in a database, so you can basically increase the amount of servers that access the database for basically an unlimited amount of capacity for parallelism. Of course all of this is bottlenecked by the speed of your database.

For the front end it's actually less critical, believe it or not. Even the shittiest phone is already plenty powerful. Most of the slowness in this area is still in IO or data transfer. All those loading screens you're waiting on is mostly data transfer and database bottlenecks. The reason why UIs are so slow nowadays is because literally half of most UIs live on the cloud and are downloaded by your browser/mobile device. We are well past the time when UIs take 16.6ms to load. 1s is actually quite good nowadays.

>Every design pattern can be abused, and none of them is a silver bullet

Except I didn't abuse a design pattern. I used an incredibly general example. Basically a single method in a class will likely not be utilizing all members in that class yet at the same time you cannot use a method without instantiating ALL members. it's a pointless restriction that is solved by changing the method into a function that operates only on its input parameters.

When something is wrong with the most trivial of all examples... then something is wrong with the entire paradigm.

>If you want to reuse that code, make it a global function, all OO languages have them or equivalents (static classes in C#).

Which is another of saying "use functions in namespaces instead of objects." I recommend that if you're doing C# or JAVA you should write all your functions this way. There is no reason why you shouldn't have this level of re-usability on ALL your code. There's no point in making things methods tied to random state.

>See the example linked in my previous comment (I hope C# is readable enough even for non-users), the iReadStream object returned from setupConnection can potentially hold quite a lot of referenced things, GZIP compressor, AES implementation, yet for the user of that object it’s just a trivially simple interface with a single read() method.

I looked at it, the use of static keyword makes it basically plain old functions rather then methods. I wouldn't call it OOP. But whatever it's just words. Basically I'm saying: "shared mutable state in classes offers no benefits and makes your program less modular" You can still call it OOP if you want but if you agree with my statement then overall we're in agreement.

>Due to polymorphism, OOP allows to write functions operating on data types unknown to either compiler or the programmer writing that code, as long as the types implement the expected functionality.

This is just a type class or an interface or whatever you want to call it. It exists in other languages as differently named concepts. I would say it's not an OOP thing. An untyped language like python basically every single variable type in that language is Polymorphic to each other.

>Microsoft replaces both data types and code of their IOutputStream.WriteAsync method with windows updates. Their changes don’t break my code, they don’t even require me to recompile it.

That's because you already bent your code to fit their interface. They maintain that interface and you don't have to change anything. This is universal to all types of programming paradigms FP included.

>These things are orthogonal. No one forces you to return half-initialized objects, you can throw an exception instead.

In an FP language you are forced to never even be allowed to have half-initialized objects exist. The concept doesn't exist in FP. This eliminates a whole class of potential errors from your program.

In procedural languages a common pattern I see is this:

var x = A();
x.a = 1
x.b = 2
....

Basically if the procedures are written out like that it leaves room for a potential error/mistake/bug to occur. What if you miss instantiating something?

In a functional language it must be done only like this:

var x = A{1, 2, ...}

And most FP languages do not allow nulls or future modification. Meaning you have to figure out the true value of every variable and shove it into the object during instantiation. These are essentially procedural or temporal errors that functional programming gets rid of by eliminating the concept of time. It asks you to define the correct piece of data rather than treat it like a container that you fill with data over time.

The language Elm that I recommended earlier is an FP language that takes concepts to the extreme. In ELM you can absolutely never have a runtime error (other then blowing up memory). It is impossible because the language doesn't allow you to do stupid things that would otherwise trigger runtime errors in other languages like C# or C++. It eliminates a whole class of errors you find in C, C++ or C#. The only thing you have to deal with is logic errors.

>1. Why not? We have objects, they have methods which mutate their internal state. Looks OOP enough in my book?

You referring to your example? I dunno it looks to me like they're static meaning they don't mutate internal state. Do those functions in your example modify variables that aren't part of the parameters? I think I'm being liberal with my use of "mutate internal state." In this case I mean a member variable of the class. You labeled it static and therefore the function is basically just a procedural function. I wouldn't call it OOP anymore then I would call a function in C OOP.

>2. If I would have actually implemented these objects instead of writing // TODO comments, these implementations all would have a fair bit of internal mutable vars, due to buffering, AES blocks, and other shenanigans.

Well they aren't mutating global vars are they? If it's just mutating scoped variables within the function then it's still not OOP in my book. It has to modify a variable outside of it's scope that's part of the instantiated class. I wouldn't call this function FP either. It's definitely procedural programming similar to C or golang.

To make it clear I'm saying Procedural programming > OOP and FP > OOP and it's still up in the air for procedural programming vs. FP.

Also the in the banana gorrila example I compared a class to a function.

def addOneFunc(x):
x += 1

Just so you know the above example is not an example of FP. That is a procedural function that mutates state. I was using it to show you how even Procedural programming is better than OOP.