

Designing APIs for Asynchrony - iambot
http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony

======
gruseom
I have code that calls back synchronously if a value is in memory and
asynchronously if it has to make a network call to get it. It's simple, and
I'm not persuaded by this post (or the one it recommends) to make it more
complicated. In this particular use case it seems enough to know that the
callback _may_ occur asynchronously, so you can't assume that anything will
still be in scope.

~~~
aegiso
This is not really about scope. In the particular case of JS scope is not an
issue at all; the engine handles the closures and scopes for you.

The issue is that once you start doing serious work with asynchrony --
filtering streams, handling disconnects, backing out of parse errors, and
dealing with parallelism all at the same time -- then being able to reason
clearly about the control flow is paramount to getting anything done.

If sometimes code below the callback registration will be executed first, and
sometimes not, depending on unpredictable runtime state, it's game over. Even
if you understand the code and it works now, good luck when a dependency
update introduces a new corner case and your app's control flow has been
radically changed and you're stuck midnight-debugging the mess.

I guess this is one of the things you learn in the trenches, along with
avoiding global variables and not optimizing prematurely.

~~~
gruseom
You're right that "scope" isn't the right word to use there, but I still can't
think of a better one.

Trying to accommodate the complexity you describe ahead of time could well be
its own mistake. One thing I've learned in the trenches is to wait for most
things to prove to be a problem before adding complexity to address them. I
believe you that there are cases like you and the OP describe, where "all sync
or all async" is a good invariant to have. But I don't believe it's a general
rule, the alternative to which is doing it wrong (or even the devil, as in the
OP).

Another thing one learns in the trenches is that almost all general rules
about software are bogus and end up distorting one's thinking. It's better to
choose invariants on a system-by-system basis.

~~~
aegiso
Isaacs is writing from a node context, where apps are basically collections of
third party modules glued together. In that kind of world, it's expected that
things will work a certain way and not deviate, or your code ends up being
crusted up by the glue and exception handling.

The issue with "wait until it's a problem" in node is that dependency updates
can and will ruin your assumptions if you haven't been diligent about doing
things the standard nodeish way. For better or worse, the node community
pushes this pretty hard.

So the way I see it, this isn't about blind application of general rules. It's
about having a standard API in your framework. And I firmly believe that the
reason npm ecosystem works so well is because of people following these
standards.

Though I do agree izs appears to be overgeneralizing his conclusions.

