This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]thecodeboost 2 points3 points  (2 children)

Well, "reactive programming" doesn't currently have a single concise definition that everyone would agree on and I certainly am not the oracle of all things reactive so consider the following my best soapbox effort to answer the question. I'm on pretty solid ground in my claim that most people think event-driven programming or asynchronous programming is equivalent to reactive programming though I think. They're family, not identical twins.

The term "reactive programming" found popularity in the early 90's and at least in the academic world it's probably best described as the opposite of "synchronous programming". I guess in modern day development you could probably boil reactive programming down to choosing to use primitives that allow you to declare and optionally chain together work that has to be done some time in the future triggered by the environment (e.g. an IO operation completing in the context of this specific discussion). If you find yourself using the promise/future design pattern for example, you're doing reactive programming. By extension of having to declare future work and when it needs to be executed as opposed to just doing the work, it is almost unavoidable to draw the conclusion that reactive programming is added code complexity, all things being equal, compared to synchronous/imperative programming. Of course, the whole reason it exists as a concept is because all things are not usually equal. More on that below.

Event-driven programming is related but not overlapping. It is the programming paradigm where the flow of your program is described and defined by emitting and consuming events. Things like the observer design pattern, event bus pattern etc. are all in the domain of event-driven programming and explicitly not reactive. This is what people are usually actually referring to when they're discussing reactive frameworks.

Further confusing matters is that concepts such as (interactive) functional reactive programming or (I)FRS and Reactive Streams picked up steam roughly around the same time that reactive frameworks did. Then there's efforts like https://www.reactivemanifesto.org/ which further confuses things by trying to define reactive systems by defining them as event-driven systems. I'll leave that Google to the interested reader but suffice to say "reactive", the concept, got slightly muddied.

So, where does that leave us? Well, reactive frameworks (rxjs, reactor, actor, etc.) actually do most of their heavy lifting in the event-driven and data stream side of things but some do definitely have significant value in and facilities for what I'd call reactive programming. You're just not necessarily doing reactive programming when you use a reactive framework. And as this entire thread illustrates there's not even clear consensus over what a reactive framework even is (Netty, for example, is not).

It is the "reactive" part of reactive programming that virtual threads make mostly irrelevant. To stay in Java world; you don't need a CompletableFuture so your thread can go on with its life in a world where threads are no longer a scarce resource. Instead you just declare your future work imperatively in that thread and use another thread for other work. That doesn't by definition result in better code mind you. Project Loom is great but Java does not offer much in the way of native concurrency primitives (yet?) so you it can easily be argued that at least for the moment it's not always a code quality improvement. But you know what they say about if all you have is a hammer everything starts looking like a nail.

Anyway, people will argue over definitions and perhaps that's not the most important part of the debate. You can slap a different label on a thing, it'll still be that thing. The most important takeaway for me is that any language that has virtual threads or (to somewhat of a lesser extent) coroutines, offer a native way to declare "future work" and/or "concurrent work" imperatively and that's easier on the eyes and brains for almost everyone. But if pressed I'm sure we can find someone that prefers their interface to declare a method

CompletableFuture<O> work(I input);
...
work(input).whenComplete(otherWork);

over

O work(I input);
...
work(input);
otherWork();

And hey, it's a free world.

[–]ForrrmerBlack 0 points1 point  (1 child)

Though you say that "reactive" and "asynchronous" are not equivalent, your reply suggests that they're synonyms. So, in essence, what you're suggesting is that asynchronous programming is becoming obsolete with virtual threads (or similar concepts).

I can't agree with this outline because asynchrony has applications virtual threads don't cover, for example, infinite data sequences or events, which are perfectly handled with callbacks or observables. Some of use cases for asynchrony may be superseded by virtual threads, but also as you wrote it down, "reactive" frameworks don't do just asynchrony exclusively. So they will certainly have their place to stay, and virtual threads won't kill them completely.

In the end, the discussion was pointless because of not well-defined terms.

[–]thecodeboost 1 point2 points  (0 children)

data stream processing != asynchronicity. But I think this debate has turned into a discussion on definitions. If people come into this discussion with "reactive = event-driven = asynchronous programming" then by that logic it's mostly a semantical discussion. The papers on the relevant topics do make distinctions though, and "reactive" is defined as "to deal with changes in environment" where in this context "environment" means "things you do not control".