4 ms·
Here's some criticism. Taken from 'convincing the boss': ''' Another great aspect of node.js is the ease at which you can develop soft real time systems. By
by mononcqc 16y ago
Here's some criticism.
Taken from 'convincing the boss':
'''
Another great aspect of node.js is the ease at which you can develop soft real time systems. By that I mean stuff like twitter, chat software, sport bets or interfaces to instant messaging networks.
'''
Those are not all 'soft real time' applications, especially not twitter. Soft real time here might mean that the usefulness of a result degrades if it misses its deadline. This might be the case of some chat software, but in the case of twitter, I receive very little degradation of service if I just go tomorrow.
The key point here is that you have to be able to have a metric of a deadline and what to do when you fail it. "If we do not get an acknowledgement by 30 ms, we assume the current node is too busy for our needs and retry on a different one" could be an example of this.
'''
So don't try to build hard realtime systems in node, that require consistent response times. Erlang is probably a better choice for these kinds of applications.
'''
Erlang is made specifically for soft real time applications, not hard real time. You do not want to use Erlang to build things like life or death systems when you need to be precise to the microsecond. It is pretty good when you can miss a deadline, handle that, work your way around it, but it can not offer any guarantee about never missing a deadline. Not only does this section give bad advice about node.js, it also gives bad advice on other languages.
It just feels as if the author meant to say "It is good for interfaces with live updates, which could be slow or lack constancy of response times", not much more.
Later in the same section:
'''
Combining this with node's radical model of non-blocking I/O, you have to try very hard to create a sluggish application.
'''
My understanding was that you actually have to be careful not to write code that runs for too long, in order to avoid messing up your request times by ruining the cooperative scheduling scheme used in the language.
===
In general, the previous guides seem to be nicer, although I have to question the reason behind advice like 'do not extend the prototypes'. I figure it has to do with the difficulty of keeping things compatible, but if you're giving me advice, tell me why. Do not expect me to blindly follow your standards just because you said so.
In the deployment part, it is shown how to use screen to start and detach the server. Is there any reason why nohup or disown won't do it? it is advised not to use the shown setup for a production system -- it would be nice to know where to look for that.
I'd also generally be interested in knowing how you'd avoid spaghetti callback hell from the approach used in node.js, but that doesn't seem to be part of the guide. This is a work in progress, and I am not holding this against the author.
- isntitvacant 16y agore: cutting down on callback nesting / spaghetti code. It can be hard to avoid; and having the community put together a PEP-8 style "best practices" to avoid creating nested code is one of my fondest dreams. That said, I've written my fair share of [spaghetti code](https://github.com/chrisdickinson/tempisfugit/blob/master/lib/repository.js#L41 https://github.com/chrisdickinson/tempisfugit/blob/master/li...) in Node, mostly because JavaScript seems to lend itself to slapping together nested callbacks without slapping you on the wrist for writing unreadable code. In my experience, the best way to cut down on spaghetti code is to design your API around the [EventEmitter](http://nodejs.org/api/events.html#events.EventEmitter http://nodejs.org/api/events.html#events.EventEmitter) object. Consider this adaptation of the linked spaghetti code: https://gist.github.com/f8533ff57844b1e54558 https://gist.github.com/f8533ff57844b1e54558 Note that in the application code, there are no nested callbacks -- they're merely concerned with validating the incoming data and passing the baton on to the next responder. Bonus points: the methods are in the order of their ideal execution. Clients using the code can just do the following: var validator = new RepoPathValidator(path); validator.on('data', function(repoData) { // do whatever needs to be done with the repo. }); // redirect all errors to console.error validator.on('error', console.error.bind(console)); I'm very fond of using this method to destroy nested code -- I'm not sure how it's thought of in the community at large, though (part of the reason I'm so eager for the community to put together the aforementioned PEP-8 style "best practices" guide!)
- ehsanul 16y agoI must be missing something, but how is EventEmitter helping you get rid of the nested code in your examples? It looks like changing all the anonymous callbacks to named functions, and then using the function names as the callbacks is what made the code more readable. EventEmitter wasn't necessary to do that, right?
- isntitvacant 16y agoYes and no -- it's not absolutely necessary; I could've written it similarly without turning the callback-accepting functions into emitter-returning functions. It would have felt gross to do so, though. The downside I see with using straight callbacks that accept error and data arguments is that they conflate the logic of what that callback is actually attempting to do with the error-checking of the calling function. For example, my `baseDirOkay` method shouldn't care whether or not the calling `fs.stat` function succeeded or failed -- it should only care that the data it was passed is or isn't a directory. It shouldn't be called at all if the path was not valid. With an EventEmitter api, I can rely on the emitter itself to tell me whether or not to even call my `baseDirOkay` function, instead of having to conflate that logic with my method. This seems like a tiny gain in readability, but it means that I don't have to make a decision between putting the error/success logic of `fs.readFile` in my method (where it does not go) and my calling function (where it probably does not go, and where it would incur unnecessary nesting -- and the finagling of the `this` variable that that incurs). This may just be my taste -- but I find designing around (and reasoning about) EventEmitter-type API's much easier.