Earlier quoted context omitted.
> the visual structure of callback-oriented programs doesn't reflect the order of execution. One of my bosses made this assertion about Object Oriented code that followed the Law of Demeter and other OO best practices. I don't think he's entirely the best OO person, or entirely on the right track. However, I would venture to say that all programming paradigms hit a point where visualizing the flow of control gets exh…
Callback-oriented code is different. With by-the-book OOP code you're still executing one line at a time. You might be teleporting in space, which has its own problems, but your code still reflects the order of execution. With callback-oriented code you're teleporting in space and time. They can both make it hard to trace the path of execution. At least with OOP code you have a sensible stack trace, though. ;)
Callbacks as our Generation's Goto Statement
251–260 of 287 posts
Re: Callbacks as our Generation's Goto Statement
#252The problem is simply that those languages are not Lisp. Once good patterns of use of GOTO were found, it was natural to critisize random uses, and to wrap good uses in a lisp macro. Or in a new while or for "instruction". But then the next construct is discovered, and its bad uses considered harmful, and its good uses need to be wrapped. In lisp, mere programmers will just write the next macro to abstract away this…
Ah, but the real problem is not that these languages aren't Lisp, but that they aren't Scheme. People are being forced to write continuation-passing-style code by hand, which anyone would agree is painful. To allow user-level code to abstract away the need to write CPS, you need call/cc (or something like it).
Re: Callbacks as our Generation's Goto Statement
#253As someone who only recently switched to Node.js from PHP I personally haven't had any difficulty switching over to the callback frame of mind, and I haven't experienced the "callback hell" so many people complain about. At first I was hesitant to start with Node because I saw blog posts by people bemoaning the spaghetti callback code that they ended up with. But I haven't experienced any of that, although I am a rel…
I often write synchronous methods that include control flow that nests three deep (say try/finally, if/then/else, and a for loop). Often it's easier to read this code than it would be if everything were split out into separate named methods. Why would the same not be true of asynchronous methods, assuming that the technology was there to enable it (as it is in C#)?
This might actually be a shortcoming of our code organization/reading tools.
Re: Callbacks as our Generation's Goto Statement
#254Earlier quoted context omitted.
Something like go's defer makes most uses of goto (failure handling) unnecessary. However, there is still the "code a state machine" use case for goto.
Which we are trying to eliminate with tail-call-optimized mutually recursive functions.
Re: Callbacks as our Generation's Goto Statement
#255As someone who only recently switched to Node.js from PHP I personally haven't had any difficulty switching over to the callback frame of mind, and I haven't experienced the "callback hell" so many people complain about. At first I was hesitant to start with Node because I saw blog posts by people bemoaning the spaghetti callback code that they ended up with. But I haven't experienced any of that, although I am a rel…
The simplest example of callback hell is trying to analyze workflow of some chunk of code in a debugger. If the code is linear, you place a breakpoint at the beginning of the method you're interested in and go through the code one line at a time. If there are nested statement of method calls, the debugger happily redirect you to them without fail.
With extensive use of callbacks, this becomes impossible. Since callbacks are merely registered in the original method, you need to place a breakpoint at the beginning of every callback function you might encounter in advance. Named callbacks actually make this worse by physically separating the place where a function is registered from its body. Did I mention that you're loosing ability to do any kinds of static reasoning, since callbacks are inherently a runtime concept? And the fact that you loose ability to look at the stack trace to "reverse engineer" why something was called?
Which reminds me of something. Have you ever seen code that reads a global variable, and you have no clue where the value came from? Callbacks create the exact same problem, except they aren't just data, they are code, so the problem can be nested multiple times.
Re: Callbacks as our Generation's Goto Statement
#256Earlier quoted context omitted.
Which we are trying to eliminate with tail-call-optimized mutually recursive functions.
Which are semantically less clear than goto, when you are working with something that is semantically a state machine.
Re: Callbacks as our Generation's Goto Statement
#257"Await" is fantastic, and having using it for JavaScript (via TameJS and then IcedCoffeeScript), it makes things a lot easier and clearer. That being said, I don't think the comparison between callbacks and goto is valid. "Goto" allows you to create horrible spaghetti-code programs, and getting rid of it forces you to structure your programs better. "Await", fundamentally, isn't really anything more than syntactic su…
I don't feel any respect for the article because it's written on the premise that goto is bad, and that it is anything like a callback.
Callbacks have been, and will continue to be an incredibly useful way to handle events.
Re: Callbacks as our Generation's Goto Statement
#258Earlier quoted context omitted.
If you're doing everything sequentially anyway, why bother with the awaiting part? As far as I can see your example would be functionally unchanged if you wrote the same code except without the await keyword.
Because it doesn't block the thread. The idea is that this code is executed inside of a thread that, if it blocks, will cause the application to hang. For example, in a GUI or a server. So, if its a thread driving a GUI, and it's blocked on user input, then the entire application interface will be unresponsive until it receives that input.
Re: Callbacks as our Generation's Goto Statement
#259As someone who only recently switched to Node.js from PHP I personally haven't had any difficulty switching over to the callback frame of mind, and I haven't experienced the "callback hell" so many people complain about. At first I was hesitant to start with Node because I saw blog posts by people bemoaning the spaghetti callback code that they ended up with. But I haven't experienced any of that, although I am a rel…
I'm tired to the utmost degree of all these posts about people (supposedly) coming from PHP/C#/Ruby/Python background and seeing "absolutely no problems" with JS syntax, object model and programming paradigms. There are problems. They are objectively there. If you don't see them, you have to check your critical thinking skills, rather than imply that everyone outside of elite JS circles are simply too ignorant to und…
As I said I like to write unit tests with my named callbacks. This allows me to test the callbacks as well as the root level functions that make use of these callbacks to ensure that everything is working perfectly.
When I follow this model it is extremely rare that I ever encounter any issues that would need a debugger, and if a problem does arise somewhere the relevant unit test can quickly expose which callback is having a trouble, and precisely what is wrong.
I'm not saying callbacks are perfect. My goal is just to share my technique for organizing my code in Node which I feel has led to some very well organized, testable, and maintainable code.
Re: Callbacks as our Generation's Goto Statement
#260At least for java, when your software library exists in the cloud, I don't see how you could avoid using callbacks.
Personally, I think raw callbacks are the right thing 95% of the time. yield/async/coroutines are needed for branching async logic where otherwise you'd be forced to make a new function for each branch and deal with the spaghetti at the end.