DEV Community

Ryan Carniato for This is Learning

Posted on

What the hell is Reactive Programming anyway?

My recent article How React is not reactive, and why you shouldn't care opened up a much larger debate on the definition of reactive programming in general. And in hindsight, I don't even really like the definition I presented much at all myself.

I fell once again into the trap of defining it by the implementation. I read a number of different definitions, in my search but they all weren't right. Wikipedia, Stack Overflow, Reactive Manifesto, etc...

The one that spoke to me the most was Andre Staltz's from The introduction to Reactive Programming you've been missing, but it was still so ReactiveX focused:

Reactive programming is programming with asynchronous data streams.

Asynchronous? Not necessarily. Streams? Not always. So I generalized it to:

Reactive Programming is a declarative programming paradigm built on data-centric event emitters.

Not great. Who cares about the event emitters? It's still too mechanical.

So let's give this another shot.

Take Two

So if we aren't going to focus on the mechanism, the events, what makes programming reactive? I found my answer a bit further down that Wikipedia entry. How about the ability to describe a system like:

a = b + c
Enter fullscreen mode Exit fullscreen mode

And have that relationship represent a rule rather than an assignment. To ensure a always equals the sum of b and c were b or c to ever change. And that relationship never changes.

That is the core of every reactive system whether we are applying operators to transform streams or doing some sort of auto-tracking signal. We are dealing with a declarative expression of the relationship between values that change over time.

So is that what reactive programming is?

The declarative expression of the relationship between values that change over time.

This isn't a new concept. Dates back as far as 1969 when Rene Pardo and Remy Landau co-invented "LANPAR" (LANguage for Programming Arrays at Random), more or less the blueprint for the modern spreadsheet. And is a similar problem space to Hardware Description Languages(HDLs) that were being developed around the same time.

And it isn't surprising this desire traces back to early research in computing. After all how to best save work but through automation. In setting the rules around how data elements behave in relation to each other we can abstract the complexity of execution.

Simple in concept but not without its own complexity in implementation. Starting with the fact that software isn't inherently declarative. Whether that involves the fixed relationship between variables or observably "glitch-free" synchronization. So I'm sure we will debate how to best achieve this for years to come.

Conclusion

Unsurprisingly, perhaps, even now that I feel more content with my definition it doesn't provide any further distinction. In a sense, reactive programming is just another name for declarative programming. It's everywhere.

Sure there are specific flavors with their own models and we can differentiate on them. But in the same way, RxJS isn't strictly FRP or should I say DCTP, these distinctions only serve to differentiate implementations/models but not a paradigm.

It isn't about push vs pull, signals(behaviors) vs streams, async vs sync. When fully pull-based systems still fall under this umbrella it is clear that update semantics is not a defining criterion for inclusion. To quote the 1989 paper which first used the term reactive programming:

Real-time programs are usually reactive.

What are modern browser UIs but a form of real-time programs?


EDIT: Like most things, apparently someone already wrote this article in 2010. https://paulstovell.com/reactive-programming/. Thanks to Pawel Kozlowski for sharing. I wish I had found articles like that years ago. Would have saved a lot of time.

Top comments (14)

Collapse
 
devagr profile image
Dev Agrawal

The "should I say DCTP" sent me down a crazy rabbit hole

Collapse
 
hulkaroyjouraboeva profile image
Hulkaroy Jouraboeva • Edited

Hi Ryan, could you elaborate on what you meant by:

Asynchronous? Not necessarily. Streams? Not always.

Have no idea about the streams statement, but isn't reactivity in general always about responding to asynchronous events, and updating data based on that async event?

Collapse
 
ryansolid profile image
Ryan Carniato

Yes but some reactive systems are async in nature and others are not. Like RxJS/Observable streams view everything a sequence of values over time that go through transforms. An Observable is not defined by its value but rather is an event emitter, something that passes values through. They even have a notion of being done or completed.

Whereas like the Signals you find in Solid or Vue's Ref are a different sort of thing. They are the value. Their value might change over time but their identity is associated with that value and it is always accessible. There is always a current value. These systems aren't really concerned with time and only with everything being perfectly in sync, glitch-free. Ie.. when you update this Signal everything downstream immediately reflects that. These systems propagate change synchronously generally. They are never "done" because they aren't a sequence, they are the thing.

To be fair RxJS has a concept similar called BehaviorSubject. But I just wanted to point out that the Rx definition doesn't cover the whole landscape.

Collapse
 
taikedz profile image
Tai Kedzierski • Edited

I've never had to delve into "reactive programming" or any such higher paradigms to describe a style or principle.... but the title caught my eye as to how I could understand this. I feel none-the-wiser alas, but here's what I'm getting out of it...

If I borrow clumisly a notation from logic/mathematics, I am seeing your statement as

f(b,c) => a
Enter fullscreen mode Exit fullscreen mode

That is, whatever b and c, their processing engenders a. We could even claim them to be states. And then, the question is, what to do with a, how to respond, or react to it, when either component changes the value, or state a. Which dovetails neatly into the assertion, "(Real-time) programs are usually reactive", since we depend on knowing what happened to a to further proceed...

But then, I recently discovered the existence of "real time operating systems" and am confused as to the nature of those as opposed to more "usual" operating systems. What is meant by "real-time"?

I feel to a certain extent there is a problem of terminology - in the desire to re-use words for the benefit of succinctness (or marketability), the fast breakdown of analogy seems to just muddy the ability to understand what was actually meant.

So... what is reactive programming? I am still confused.

Collapse
 
ryansolid profile image
Ryan Carniato

Sorry I was trying to end on an ambiguous note because even if I am fairly content where I landed it feels not like it is a worthwhile distinction. This started in the article I mentioned in the introduction where it has become common to call the JS Framework React not reactive. And from every encompassing definition, I could find it was in fact reactive.

I was looking for some sort of commonality for why these things are called reactive programming. And while there is a lot of reactivity around especially in UX design, monitoring real-time systems, etc..., I wanted to focus on the programming paradigm. Unfortunately, it ended up being that the commonality still boiled down to something very generic. So much that even the first paper that coined the term wasn't any clearer.

I realize throwing that at the end only serves to muddle everything. I'm content enough with my definitions up to that point. It was just that it is likely some other definition exists that loosely fits. That paper considered reactive programming to be about a program that ran at the pace of the outside inputs rather than its internal environment. By that definition pretty much any browser UI programming driven off DOM events fits this.

I still like my definitions and differentiate reactive programming the paradigm, from reactive programs, or systems. But arguably a pretty arbitrary position to be taking.

Collapse
 
guitarino profile image
Kirill Shestakov

I read somewhere that what distinguishes imperative and declarative programming is that imperative programming expresses relative truth, while declarative programming expresses the absolute truth, and that's what makes declarative programming much easier to reason about (for declarative use-cases).

Collapse
 
mustapha profile image
Mustapha Aouas

Great article, thanks for sharing 👍🏻

Collapse
 
uminer profile image
Moshe Uminer

Perhaps the distinction between Reactive Programming and Declarative is about rules for transformations to data, Reactive is about rules for transformations to state.

Collapse
 
ryansolid profile image
Ryan Carniato

Yeah, I called out the relationship between values because that represents the potential for transformation. As soon as you derive a value or establish a data-driven side effect it's reactive. A declarative identity declaration is very much like a tree falling in the woods when no one is around.

I think the transformation often gets instantly pointed at the Rx meaning like operator transforms. But Signal based systems do transformations too they just aren't as in your face explicit. Back to my example.

a = b + c
Enter fullscreen mode Exit fullscreen mode

a represents the combining transformation of inputs b and c. So it still holds.

Collapse
 
uminer profile image
Moshe Uminer

Of course. I only mean to say that reactive programming extends declarative programming inasmuch that declarative programming doesn't necessarily deal with state.

Collapse
 
johnkazer profile image
John Kazer

How would you fit state charts/machines into this? On the basis that libraries like XState allow you to use transitions to regulate UI app states.

Collapse
 
ryansolid profile image
Ryan Carniato

It's interesting. Because state machines/charts represent potential states, moments in time. They represent discrete snapshots (I realize charts can represent a range but it still holds as a specific moment in time). And then on event dispatch we transfer from one state to the next through a defined transformation.

So stepping back with a given sequence of state changes from inputs isn't unlike a coarse grain stream. You transform data through a series of inputs. The representation might differ but you are essentially driving defined paths through your state logic.

Each one feels like it could be seen as a reactive atom/primitive. It's the driving event system + the declarative representation that aligns. I can picture imperative systems with state machines I wouldn't call reactive, but I can also picture reactive systems living inside an otherwise non-reactive system and have the same categorization.

So it's more by the definition that when one calls a Promise a state machine. Reactive streams are similarly state machines. I'm not sure that signals are in that while they hold different values they generally only have a single observable state.

But this is my current thinking.

Collapse
 
beeplin profile image
Beep LIN

state machines by themselves have nothing to do with reactivity. They defines how a group of pure states (as plain objects) would change under different function calls.

Only after plugging in with things like xstate-react or xstate-vue etc. then they have ability of "change propagation". Changes of these states automatically causing outer things to run (effect functions, or the whole render function). Now they become the starting point of a reactive system as a whole.

Collapse
 
alrunner4 profile image
Alexander Carter

that relationship represent[s] a rule rather than an assignment

Such are pure functions. Then a reactive system is one that given a user-specified pure function from model to view automatically handles translating changes in the model into changes in the view.