DEV Community

Discussion on: Redux is half of a pattern (1/2)

Collapse
 
rodocite profile image
Rodolfo Yabut • Edited

For such a long analysis, the article completely misses the point about Redux being an event store that implicitly leverages several good patterns that are seen in highly-available distributed systems.

  • it forces you to separate your write model (dispatch) from your read model (props). this is known as CQRS.

  • the reducers are actually referred to as projections in event sourcing. reducers/projections are just aggregate data accumulated from events and are considered part of the read model. the strategy of doing the reduction on each event allows you to present aggregated data in "realtime". the alternative would be to iterate through large sets per read or write. it's a per-event, "realtime" .reduce()

  • Redux + Thunks was terrible. But Redux + Sagas more closely represent event sourcing as you see it in distributed systems. with events thought of as streams (or aggregates in the Domain-driven Design world). Sagas are actually referred to in the event sourcing world as either process handlers or sagas and are responsible for complex stream handling.

  • event stores and blockchains use roughly the same structure conceptually: Append only File

except with blockchains, each new insertion is hashed with the previous hash in order to keep the log cryptographically verifiable and immutable-- and is needed for Byzantine Fault Tolerance (so each node can be verified very quickly as a good actor or not).

smart contracts -- the reader contracts have similar logic to reducers. write contracts all look like event dispatch.

consensus algorithms do exist outside of blockchain tech. and with data structures that are considered high availability (they cluster and replicate), you will see that they are all AoF or KV stores or a combination of both.

  • most databases under the hood actually have a very similar event sourcing structure referred to as WAL -- write-ahead logging.

  • the typical event payload is the same in all these systems {eventType, metadata}

Just take a look at Redux w/ Sagas, Greg Young's Event Store, any blockchain, and even Kafka. They are all fundamentally similar. And since they all source from a log file, they can all replay state.

Also, Redux is an opt-in and can be as specific as you want based on how you tag your events. Your entire app doesn't need to respond if you slice your state right. And the structure itself has proven to be efficient. Event sourcing systems can handle millions of concurrent streams. Sure, people might argue there are optimizations in infrastructure that are NOT in Redux, but the structure itself is pretty ideal for streams if you write good handlers and partition your aggregates in a sensible way. The people who wrote Redux Saga totally see it.

I'm actually surprised that Abramov doesn't know the source inspiration for the thing that made him famous in the community.

Collapse
 
luiz0x29a profile image
Real AI • Edited

After studying more about virtual finite state machines I would say that these patterns that are "good"(citation needed) for distributed systems are just specific instances of something more generic.
I mean, they do work, but they are not as general as they could be, they are specific cases of a more general pattern.
I don't think the author missed "point about Redux being an event store", that point is actually irrelevant for understanding FSMs as they are the more general case, which was the entire point of the article, and I don't think the poster is wrong.

This is what's causing the clash, you are doing something like bottom-up, when the reasoning was top-down.

Collapse
 
davidkpiano profile image
David K. ๐ŸŽน

There's two parts to this article, Rodolfo. Be patient.

Collapse
 
rodocite profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Rodolfo Yabut

Excuse me? I'm sure you think I'm rude, but this article is unnecessarily long and didn't touch on much other than how confused people are (which surprisingly include people on the React team). My 1 comment has far more insight into the implementation than your entire article. Why don't you just take the criticism? It's obvious you're not crystal clear on this either and you went down a rabbit hole and will probably end up using a lot of the insight I just gave you (and I'm sure what other commenters have given you).

In fact the only reason I signed up was to comment at how bad the article is because I felt that it was prolific enough that it does people who want insight a disservice. Will you really make an awesome part 2 that isn't an inane, self-serving, ambiguous CS analysis of a practical pattern that will help clarify it for people and give them insight on when and how to use it? I really hope so because you have a great opportunity here to teach.

Hint: Immutability and finite state machines will probably confuse people more. Save that for part 3 or a deep dive on structures. Event sourcing is a pretty misunderstood pattern and sub patterns have emerged.

Thread Thread
 
davidkpiano profile image
David K. ๐ŸŽน

Redux is definitely not used for event sourcing, nor is event sourcing applicable for most of the applications Redux is used for.

Thanks for your comments, though!

Thread Thread
 
rodocite profile image
Rodolfo Yabut • Edited

You don't understand the pattern. Don't mislead an entire group of people.

You are storing events. There is a literal "store" prop passed into Provider. Therefore it is a "source" of events and not just ephemeral event-driven programming like you see in video games.

It is event sourcing.

Thread Thread
 
davidkpiano profile image
David K. ๐ŸŽน

You just proved to me that you don't understand event sourcing.

You don't store state with ES (except for snapshots etc). You store events. That is impractical for most apps.

Thread Thread
 
rodocite profile image
Rodolfo Yabut

I think you're just Googling event sourcing and trying to disprove me. Because you can most definitely store "state" with the pattern and it is done quite often. They're called projections. State storage is your read model, actually. For people who just need to read from streams, they don't need projections in-line with the event store. They do aggregations in another service. We just see the entire flow in Redux.

I mean you're kind of proving to me you haven't thought of this pattern much and you're about to try and teach people.

Thread Thread
 
davidkpiano profile image
David K. ๐ŸŽน

Go write a post then.

Thread Thread
 
rodocite profile image
Rodolfo Yabut • Edited

I am working on it.

But I'm not prolific and it is something I know that gets even the event sourcing community heated. Only reason why I chimed in is because you are prolific and I think you have a chance at giving a ton of people an aha moment that isn't in the wrong direction.

If you want to research for your follow up blog post, check out how similar these are to Redux and Redux sagas:

In particular, the event handlers:
github.com/commanded/commanded

Projections:
eventstore.org/docs/projections/in...

Discussion on sagas and handlers:
stackoverflow.com/questions/342846...

Can't deny how close the patterns match up. I mean the EventStore Projection API is basically what we know as a reducer. Event Store was made back in 2012.

But I will say that in infrastructure, people misunderstand and do all sorts of weird event sourcing patterns. If you had a good evented model in your infrastructure that represented state pretty well, complex stream transforms in Redux (and Redux itself) starts to disappear because the work has been done for the UI.

The only reason why we needed Redux in the first place was because we needed to model some type of complex state representation that the backend didn't give us. If the state is computed in the infrastructure and the UI as a service just receives it, where is the role in Redux other than acting as a global store or a pubsub? And even then, with GraphQL and Apollo + cache, Redux's complexity and importance starts to disappear.

Thread Thread
 
boubiyeah profile image
Alex Galays • Edited

Time to eat some much needed humble pie Rodolfo; you want to push your point of view so hard...
Redux is absolutely not event sourcing (I used both extensively)
The only thing in common is that there are "events", something extremely common and found in pretty much all codebases (and the dreaded DOM)

No frontend keep all the events from last week around for the logged user, it's slow enough as it is. If you don't keep all the events, then it's not sourcing, just event driven (like almost all UI paradigms from the last decades)
Trying to find similarities between very different architectures might help you learn new things, but there's not point pushing this tool down people's throat.

Thread Thread
 
rodocite profile image
Rodolfo Yabut • Edited

You wanna mansplain me more? Maybe you can explain how React works, too. Insult me because you think I'm using analogies as learning tools (although that is absolutely completely valid)?

Actually, I think you should eat some humble pie. I am bringing up a legitimate comparison and I have used both extensively as well.

Your argument doesn't make sense and is just a nitpick. You in fact DO keep all the events in context of the lifetime of your frontend. If you do not choose to persist them after the browser closes or refreshes, that's your choice. But the implementation itself matches event sourcing. You are using an event store, running projections off of them, and using those projections in your read model. You can even replay your events to regenerate your state. If it looks like a duck, talks like a duck?

Also, there are event streams that terminate in event sourcing, you know. You could think of a browser session as a unique event stream with a prefix "ui-1", "ui-2", etc.

But again, the main point is: in context of the UI's session lifetime, the events are not ephemeral and you are indeed keeping all the events.

As for speed, the implementation of Redux might be slow, but updating state per event is one of the reasons why people use event sourcing in infrastructure-- to do relatively complex and flexible compute "realtime" without having to iterate through large sets.

The "slowness" is due to the growing event store which is a problem in ALL event sourcing implementations. In infrastructure, you typically cold storage "really old events".

If you don't have the flexibility to see the valid comparison, I doubt you've used both as much as you say or you haven't really thought about it. The similarities go FAR beyond analogies and learning helpers.

In fact, if you took the event storage itself and persisted it, you now have a way to recover complete session state through replay. Though UI state isn't so complex or critical that you can't just persist the state itself versus doing a replay from the events. It would be useful if you wanted to track clickstream and state transitions beyond 1 session. Which some people might want to do.

As I said in a previous post, other than purely UI state, we needed Redux to model complex domain state that the infrastructure should have already given us. If the we already had that state, we wouldn't need to mirror what many scaled infrastructures use for our frontend. The reason you remove Redux is you already HAVE the state you need. But I think the pattern itself is a pretty important entry drug (although contentious because people do it in so many different ways) concept that could help launch people who know React and have only worked in React to understand how distributed systems manage state and data.

React is already very good training in SOLID. And as a result, a lot of the component patterns you see fundamentally match up closely with supervision tree models in distributed systems. Now THIS next statement is me using an analogy, but if you diagram a supervision tree and don't label it and just describe it in terms of supervision tree definitions, then tell people to label it in terms of React Components, they will surprisingly know how to.

Thread Thread
 
joeyorlando profile image
Joey Orlando

@Rodolfo youโ€™re my hero ๐Ÿค™๐Ÿผ

Thread Thread
 
luiz0x29a profile image
Real AI

" If the state is computed in the infrastructure and the UI as a service just receives it, where is the role in Redux other than acting as a global store or a pubsub? And even then, with GraphQL and Apollo + cache, Redux's complexity and importance starts to disappear. "

Well, you are not wrong about this.
That has nothing to do with the fact of things being event store or not, its just that you don't need to store collateral state if you model the data for the consumer perspective, instead of the producer, this should be obvious.

When all you have is an "EventStore", everything looks like events.

The only problem with Eventstore and CQRS is that FSM are actually the generalization, not the other way around.

With the David actually got right, and you didn't, Rodolfo.

Collapse
 
blocka profile image
Avi Block

Saying redux is like event sourcing, is like saying redux is like a state machine. It's definitely possible to model redux like a state machine, but there's no inherent constraint in redux that promotes this.

The only constraint redux has is that reducers are pure...there's no constraint on actions. Actions can be modeled as commands or events.

Then again, if they're events, where are the commands? And if they're commands, where are the events?

Also where is CQRS? Aggregates?

"Event-driven" does not mean "event sourcing".