Live data from Hacker News

Avoiding Event Chains in Single Page Applications

code-experience.com

11–20 of 64 posts

Re: Avoiding Event Chains in Single Page Applications

#11
post #7
post #4

it's amazing how JavaScript is becoming the new java. everyone thinks that adding a ton of extra complexity in the guise of a simpler api will make it more maintainable. in this example you now have 4 events under the hood and two event dispatchers. but it seem simpler because you only "see" two and one dispatcher. while it may make things just a little bit simpler to maintain you may enter debug hell when there's bu…

writer of the article here: I simply cannot follow the argument about "added complexity" The use case defines the minimum amount of links you have to make, in this case 4. Now you have two options: You just roll with it (we used to do that), or you try to abstract away a few steps (we do this now with the dispatcher). The dispatcher here is roughly 100 lines of fairly simple, unittestable code, so I really cannot see…

It seems all you've done is inverted and hidden the sequence dependency in a series of waitFor chains instead of event chains, which in some ways is worse; compare

    A:
     update;
     notify B;
    B:
     update;
     notify C;
    C:
     update;
     notify D;
    D:
     update;
with

    D:
     wait for C;
     update;
    C:
     wait for B;
     update;
    B:
     wait for A;
     update;
    A:
     update;
The former is a clear sequential path, the latter builds up and then unwinds in a stack-like fashion. It's like the difference been non-tail and tail-calls.

It's only a technical nuisance that one model needs to wait for the other to update.

I would certainly not view a sequence dependency that's critical to correct operation as a "technical nuisance" to be hidden away; it's an important fact.

Re: Avoiding Event Chains in Single Page Applications

#12
I've read this 3 times and I still can't see what the advantage of this dispatcher is.

In the event model, Events that deal with model A also have to be dealt with in models B,C, and D. Wouldn't this lead to exponential explosion?

The fact that B has to explicitly wait for A in the code also seems prone for errors. If A changes to no longer deal with that event, will B block forever?

And this still builds an event chain, because B is blocking on A. I don't see how this is different from an event chain, execpt that the dependency is non-obvious (whereas a callback chain/future chain will at least show what data is being passed into B from A)

This is maybe OT as well, but this article could really do for some concrete examples in the explanations. "Model A" and "Model B" are not examples.

Re: Avoiding Event Chains in Single Page Applications

#13
post #7
post #4

it's amazing how JavaScript is becoming the new java. everyone thinks that adding a ton of extra complexity in the guise of a simpler api will make it more maintainable. in this example you now have 4 events under the hood and two event dispatchers. but it seem simpler because you only "see" two and one dispatcher. while it may make things just a little bit simpler to maintain you may enter debug hell when there's bu…

writer of the article here: I simply cannot follow the argument about "added complexity" The use case defines the minimum amount of links you have to make, in this case 4. Now you have two options: You just roll with it (we used to do that), or you try to abstract away a few steps (we do this now with the dispatcher). The dispatcher here is roughly 100 lines of fairly simple, unittestable code, so I really cannot see…

two-way databinding does not always do the same thing. Angular's digest cycle is frame-based, where everything is recalculated until you hit a fix-point. This is more analogous to the event dispatcher (A is updated, then on refresh B will) than your dispatcher example.

Re: Avoiding Event Chains in Single Page Applications

#14
It took me a while to come round to it but this kind of madness is something that Ember's event/render loop and implicit property dependency graph makes really, really easy to solve.

People knock Ember for its complexity but in reality it's simply a complete/coherent solution for the kind of problems people like this are iterating towards - and watching their code get more complex as they do.

Re: Avoiding Event Chains in Single Page Applications

#15
post #7

Earlier quoted context omitted.

writer of the article here: I simply cannot follow the argument about "added complexity" The use case defines the minimum amount of links you have to make, in this case 4. Now you have two options: You just roll with it (we used to do that), or you try to abstract away a few steps (we do this now with the dispatcher). The dispatcher here is roughly 100 lines of fairly simple, unittestable code, so I really cannot see…

It seems all you've done is inverted and hidden the sequence dependency in a series of waitFor chains instead of event chains, which in some ways is worse; compare A: update; notify B; B: update; notify C; C: update; notify D; D: update; with D: wait for C; update; C: wait for B; update; B: wait for A; update; A: update; The former is a clear sequential path, the latter builds up and then unwinds in a stack-like fash…

yep, that's all it does. It just inverted the sequence dependency. You call it "worse". But I argue that it is a much better mental model in the specific use case of updating state given an external disruption from the user.

You see, what you call a clear sequential path is what I call evil :). We had tons of those in our app, and it was so hard to keep track of them, and everytime I didn't look at it for a while, I had to invest 10 minutes to track down the event chain.

There is one simple reason for this: If you have a sequential path, you loose the context after the first link. A updates because "user-clicked-x", and B updates because A updates. But if you're working on B, you ask yourself why the heck did A update in the first place?

You might argue that you are always aware of this, but we found that when our app grew more complex, we actually didn't always know.

I'm sure you could find a solution where you keep the sequence and don't lose context, but then you have to state the dependency in the wrong place: In model A you have to say that model B should update. But that's all wrong because A shouldn't care about models that depend on it. The models that depend on A should care!

So by inverting the whole sequence dependency, you gain the following:

1. in every model you are aware of the context, i.e. the original event that triggered the state change in the first place

2. you are also aware on what other models this model depends on (it is explicitly stated and not hidden like you said).

This means that you can work on model B and extend it without ever looking at other models, while knowing exactly the origin of your state change. In my opinion, this is decoupling at its best. It also helps unittesting greatly.

While I agree that inverting the dependency is a drawback, I've gained things that, at least in my opinion, heavily dominate that drawback.

Re: Avoiding Event Chains in Single Page Applications

#16
post #4

it's amazing how JavaScript is becoming the new java. everyone thinks that adding a ton of extra complexity in the guise of a simpler api will make it more maintainable. in this example you now have 4 events under the hood and two event dispatchers. but it seem simpler because you only "see" two and one dispatcher. while it may make things just a little bit simpler to maintain you may enter debug hell when there's bu…

mmm... as I get older and (hopefully) more experienced, I have become doubtful of this point. Apparent simplicity comes often from ignoring the subtle difficulties in a problem. Adding a layer is often the disagreable but reasonable thing to do.

Re: Avoiding Event Chains in Single Page Applications

#17
post #14

It took me a while to come round to it but this kind of madness is something that Ember's event/render loop and implicit property dependency graph makes really, really easy to solve. People knock Ember for its complexity but in reality it's simply a complete/coherent solution for the kind of problems people like this are iterating towards - and watching their code get more complex as they do.

> implicit property dependency graph

How similar is Ember's dependency tracking to Knockout's?

With Knockout I've had exactly the problem described in the article, where properties end up depending on eachother in a chain, and it is hard to keep track of what actually happens when data changes across multiple view models, particularly when inevitable special cases appear, where really I want to do something slightly different half way down the chain depending on what initiated the change, but all I have is a generic "property changed" event. How does Ember handle that?

Re: Avoiding Event Chains in Single Page Applications

#18
post #12

I've read this 3 times and I still can't see what the advantage of this dispatcher is. In the event model, Events that deal with model A also have to be dealt with in models B,C, and D. Wouldn't this lead to exponential explosion? The fact that B has to explicitly wait for A in the code also seems prone for errors. If A changes to no longer deal with that event, will B block forever? And this still builds an event ch…

> If A changes to no longer deal with that event, will B block forever?

No, A would just no-op, and control will return to B. This is all written in the context of JavaScript, with a synchronous dispatcher and no threads which can block.

Re: Avoiding Event Chains in Single Page Applications

#20
post #15

Earlier quoted context omitted.

It seems all you've done is inverted and hidden the sequence dependency in a series of waitFor chains instead of event chains, which in some ways is worse; compare A: update; notify B; B: update; notify C; C: update; notify D; D: update; with D: wait for C; update; C: wait for B; update; B: wait for A; update; A: update; The former is a clear sequential path, the latter builds up and then unwinds in a stack-like fash…

yep, that's all it does. It just inverted the sequence dependency. You call it "worse". But I argue that it is a much better mental model in the specific use case of updating state given an external disruption from the user. You see, what you call a clear sequential path is what I call evil :). We had tons of those in our app, and it was so hard to keep track of them, and everytime I didn't look at it for a while, I…

> A updates because "user-clicked-x", and B updates because A updates. But if you're working on B, you ask yourself why the heck did A update in the first place?

Stack traces are a thing. Chrome even has asynchronous stack-traces.

A updates because "user-clicked-x", but it might also update because "user-clicked-y". Or because "user-clicked-z". So now I have 3 things to add to A and to B, because B needs to refresh everytime A does. So if you forget about one of these, then suddenly B is out of sync.

A "solution" to this problem already exists in terms of event listeners. If B listens to any change on A, then A doesn't have to deal with B, but B updates properly and doesn't have to deal with all event types A has to deal with.

Post reply on HN