|
|
|
|
|
by pmoleri
1103 days ago
|
|
> How does "func EatADonut() async {}" aka "eating a donut is an inherently async action" even make sense to people? Of course it does, read it as "beware, something blocking down the road". If you can EatADonout without blocking, please do, but want it or not that's a different implementation, one that doesn't block and the signature it's telling you so. We're so used to sync and having hidden blocking operations. I wonder if in an alternate universe the first languages considered the blocking/async nature of operations and then some newer languages considered hiding this information into seemingly sync functions would produce similar but opposite outrage against it. |
|
Implementation is the same. In both cases it's the same set of CPU instructions, but async/await languages create artifical division, forcing developer to think othervise.
So, let me explian my reasoning. Code starts with a developer's mental model of a problem and behavior of the system and then translating it into the code. The more straightforward this translation, the more readable the code. Code is a second degree map of problem domain so to speak ("real" world -> mental model -> code).
Like if you want to add two values, the simplest form of code would be "add(2,2)" which is pretty straightforward. If the code forces you to do some mental gymnastics (i.e. "2 2 addOnlyEvenNumbers") - that's less straightforward, less clear and less readable.
In the same vein, if you want to execute some function ("EatADonut" or "MakeHTTPCall") – you may care or not care about blocking and waiting for results. But it's your call. So it makes sense to give you two options to run this function. Go has simplest possible solution – "eatADonut()" vs "go eatADonut()". It doesn't matter what is a "default" here – it could be "eatADonut()" (go to background) vs "sync eatADount()". What matters that "eating a donut" is just a set of instructions to the CPU, and it's up to caller to decide how you want to execute it in terms of concurrency.
Now, "async/await" approach turned this ownership of "synchronicity" around. Now function is deciding how it should be called. Mental model of "actions" now needs to be translated into "actions being async or sync for the purpose of fitting into this language concept". Which is cognitively expensive for no added benefit.
Sure you can rationalize it, and get used to it as to any other absurd design, but it still adds unneeded complexity to the code, makes it less readable and less clear.