7 ms·
The node.js aesthetic
- koen 15y ago> A big part of what empowers node to make these kinds of interfaces possible is its asynchronous nature. No longer do you have statelessness imposed from on high by the likes of apache or rails. You can keep intermediate state around in memory just like in any ordinary program. Should that not be: A big part of what empowers node to make these kinds of interfaces possible is its "statefull" nature. ... Really, that it is asynchronous is nice for performance (but only complicates the implementation). But the fact that you keep state in memory is indeed a big win for ease of implementation, and also performance, especially if state is not global but only relates to a single session. Of course, that is usually frowned upon by the web developer community which believes that this somehow hurts scalability (while it actually helps scalability).
- nknight 15y agoIt's frowned upon by people who need high availability with minimum complexity of hardware and software configuration. There's very little state one can reasonably store on a single web server without interrupting sessions if the server fails, and there's almost none you can store if you can't guarantee user X will always connect to server X for the duration of the session. Not everyone must solve these problems, but they quickly come to the forefront for anything beyond rather low-traffic sites.
- virmundi 15y agoI think the sessions in Node/Express are helpful when pair properly. For example, Express can use Redis as its session store. This has the benefit of making the session cross-cluster populated, while still being fast. Add to this the fact that almost everything in JS is serializable as itself and you get a pretty good replication mechanism.
- gbog 15y agoHmm, seems a bit hand-waving to me, but to be fair I have never tried Node.js and would probably have hard time convincing my finger to type javascript code for server things. Javascript always seemed to me a language that you used, and tried to use correctly, because you had to. On a server I have the choice, right? So my choice is currently Python so I read this article with some bias. In the section "batteries not included": > modules in the core distribution get an unfair advantage over the libraries in userspace by virtue of availability and prominance. I would call it "unfair" if some modules had access to special backdoors and APIs, but it seem to not be the case for most modules I checked in Python. For instance, 20 mn ago, I did vim /usr/lib64/python2.6/unittest.py and could check this piece of code directly. I did see no special magic that could not be provided by other modules, like Nose or py.test. Moreover, the code was not looking like "neglected code", even if it did not look like the most modern kind. > experimenting, and iterating is much harder Well, that's what I like the most with core modules: they don't change overnight, and, while some of them like urllib(2) may be replaced by some because they have a better competitor, most of them are just good old friends, like scipy, that don't need to be put upside down every month because someone found a slightly more elegant way to call two of it's functions. > "core modules"' advantage evaporates in the face of baked-in concurrent library versioning and sophisticated package management. I have never been considered as a shy sysadmin when I was sysadmin. I am actually strongly against the "Tool X have misbehaved once therefore tool X is evil and will never put a foot again on my machine" philosophy. I know some guys who are. (I was also sound engineer before and mostly all musicians I met are this way, by the way). But still, having dealt with library version issues sometimes, I think "concurrent library versioning" and "sophisticated package management" sound awfully nightmarishly black-magic to me. I guess I would be more on the "let's understand the most of what happens and not change what don't need to" kind.
- hello_moto 15y agoMost people who just got into a new bandwagon are handwaving regardless.
- exogen 15y agoWhen is it going to stop being a bandwagon? Do we have to wait for you to start using it? James (the author) is probably the most prolific library author in the Node community and has a startup built on his libraries. Do you really think he's just handwaving and doesn't know what the fuck he's talking about? Node is just 3 months younger than Redis, software which plenty of people here use, or want to use, or at the very least respect. And yet when it comes to Node, all logic seems to go out the window for whatever reason.
- substack 15y ago> But still, having dealt with library version issues sometimes, I think "concurrent library versioning" and "sophisticated package management" sound awfully nightmarishly black-magic to me. I guess I would be more on the "let's understand the most of what happens and not change what don't need to" kind. Concurrent versioning lets you do the "not change what don't need to" part really, really, well. Versions of packages that have been proven to work well with one another can continue to do so because if you need a newer version of some library then both the old and the new version can live harmoniously in the same codebase. You don't need to be paranoid about upgrading modules anymore because node and npm are already paranoid on your behalf.
- moe 15y agobecause node and npm are already paranoid on your behalf. Yes, until npm blows up in obscure ways. Which it likes to do frequently.
- IsaacSchlueter 15y agoWhat do you mean by "blow up in obscure ways"? It generally dumps a ton of colorful errors to your terminal. If you find them obscure, please be comforted by the fact that I certainly do not find them obscure, and would love to fix whatever problem they indicate. It's actually my job. Also, npm is a software program, and not intelligent. It doesn't "like" things. To the extent that it has preferences, it loves semantic versions, accurate metadata, and especially you.
- zzzeek 15y ago>You don't need to reason about multiple instruction pointers or mutexes or re-entrant, interruptible execution because all the javascript you write just lives in a single thread. I see....on the other hand, when I write request-handling code using (any web framework ever on any platform), you're suggesting that we do worry about mutexes and reentrance (not to mention, handling a single request uses multiple threads?) and that these details aren't already handled by (any web framework ever) ? Interesting.
- uast23 15y agoMy understanding is: When you are using a ruby or python based web framework, each request is a blocking request i.e. after each request you wait for the response before proceeding further e.g. urllib.urlopen(), which as a result causes the no of requests handled/second to go down. Using eventmachine or gevent respectively for ruby or python is one way to overcome this. In node.js there is no such concept of blocking requests and everything is processed in a single thread. But you can always fork multiple processes using its cluster module http://nodejs.org/docs/latest/api/cluster.html http://nodejs.org/docs/latest/api/cluster.html edit: Oh, I was not trying not advocate anything. nodejs is indeed just a choice, if I didn't make myself very clear when I said "My understanding is:"
- aphyr 15y agoRuby and Python (not to mention basically every other language) have a plethora of threaded, forking, and evented models for concurrency. Thin/Rack/Sinatra, for example, behaves capably in a thread-per-request mode. Reactor systems are not the only (nor are they even preferable in many cases) choice.
- MostAwesomeDude 15y agoHow did you find gevent and totally miss Twisted, which is linked on the front page of nodejs.org? There are a handful of frameworks that assume every request is fully concurrent and non-blocking. Twisted-based stuff is the most prevalent, for Python, like Nevow, Athena, and the stuff baked into twisted.web. However, WSGI itself doesn't say anything about the concurrency of individual requests, and it's totally possible for WSGI requests to be multithreaded, multiprocess, or otherwise concurrent.
- sktrdie 15y agoThe way modules are looked up - localized to the piece of code that needs it, inside the /node_modules directory - is one of the greatest strengths of the node ecosystem. It's just dead simple and solves dependency conflicts like nothing I've ever seen before.
- phamilton 15y agoCould someone clarify something for me? Is http.createServer robust enough for production? It is my understanding that running it as is in production is not a good idea. You want to at least configure nginx between node and the world. If that's the case, doesn't that undermine the whole "focus on your application, not the configuration" point he's making? Sure you can call startServer multiple times, but then you would still have to focus on configuration.
- viscanti 15y agoI don't want to sound like I'm over qualifying things, but it really depends on the situation. For most applications http.createServer will be robust enough for production. There are node based solutions for dealing with load balancing, that would make nginx unnecessary in almost all cases. It really comes down to tradeoffs. If your primary concern is the most simultaneous connections, then you'll need to find a special tool, and Node or most other non-haskell web frameworks probably aren't for you. Node makes it really easy to do some things. That focus makes some other things more complicated than they should be (because it's asynchronous, you end up needing to deal with flow control, often times using queues that mitigate some of the asynchronous advantages). It's like everything else with computers. There's tradeoffs. http.createServer can be used when it can be used (which happens to cover most use cases).
- deleted 15y ago[deleted]
- jahewson 15y agoTo the best of my knowledges: yes. Using nginx in front of node seems to have originated as a non-root way of getting access to port 80, prior to node supporting setuid. A better way on Linux is just to use the kernel TCP routing, for example: sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080 However, if you're using HTTP virtual servers and you already use nginx, sure, place node behind it.
- peterbraden 15y agoit is robust enough in terms of scaleablity yes. Most people are just using nginx as a load balancer. This only addresses servers that you expose to the world though - I think one of the less publicised strengths of making creating servers easy is that it allows you to make internal servers for services trivially. And using a service oriented architecture is a great win.
- munificent 15y ago> So if a module "foo" was tested against and depends on "baz@0.1.x" and a module "bar" depends on "baz@0.2.x", then when you go to use both "foo" and "bar" in your own program, "foo" and "bar" will both use the version of "baz" that they were tested and depend against! That sounds like a recipe for disaster if I get an object from "bar" that came from "baz@0.2.x" and try to give it to "foo" which then gives it to "baz@0.1.x". I'm suspicious of silver bullets in general and I'm deeply suspicious of any silver bullet that claims to slay version hell. Versioning is hard.
- mikey_p 15y agoWhile I'm not saying that's not a real concern, I don't think I've ever seen code that would blow up from that. I think this comes from the concept of "limited surface area" that the OP outlines.
- benatkin 15y agoThe Law of Demeter applies here, even if traditional objects aren't being used. If the library that uses it encapsulates everything about it, or at least documents things that aren't encapsulated, it tends to work out just fine. http://en.wikipedia.org/wiki/Law_of_Demeter http://en.wikipedia.org/wiki/Law_of_Demeter
- MostAwesomeDude 15y agoI find the spinning in this article to be incredible. The "limited surface area" is all well and fine in JS, because there is no object inheritance in JavaScript. The author tries to emphasize usability over extensibility, which is a false dilemma in my book since it's possible to code to an interface in other languages. You define a usable interface, and then everybody codes things that fit that interface. You don't even have to care about whether your objects are inherited or composed. Of course, languages with inheritance are even more reusable because it's possible to inherit from, and extend, objects which implement the given interface. This is a key tenet of design in Java and Python. The second part of "limited surface area" talks about how namespaces and qualified imports are great. Yep. Welcome to the party, guys. You're only a couple decades late. The "batteries not included" section is a great dig at Python, but he could have bothered to actually bring up examples. It's easy; things like asyncore are so god-awful that it's trivial to point out where Python's batteries have expired. However, he's comparing apples and pomegranates here; Node is not a language! It's a framework. It has a large library of its own which doesn't come standard with JS. That library provides stuff which is built-in on other languages, like unit testing, cryptographic primitives, zlib, filesystem accessors, URL handlers, buffers, iterables, type checkers, and a REPL. To repeat: These are batteries which are native to other languages. Let's go ahead and compare with Twisted, shall we? I'll omit things for which Twisted provides protocols and Node provides streams, since those are (technically) equivalent. Node doesn't appear to contain these things which Twisted provides: Common protocols for handling lines, netstrings, and prefixed strings; non-blocking stdio as a protocol, serial port as a protocol, DNS as a protocol, a DNS server, a handful of RPC protocols like XML-RPC, AMP, and PB; and full suites for: NNTP, telnet, SSH, mail, more chat protocols than I care to remember... Not to mention powerful utilities like credential handling, and enhancements to the Python standard library like object-based file and module handling. And that's just what's included in the main tarball; there's a big community of third-party code which implements whatever you might happen to need. I didn't bother to list the reverse, because there is nothing in Node which is not in Twisted. "Core distributions with too many modules result in neglected code that can't make meaningful changes without breaking everything." Are you not aware of deprecation? Write the new code, mark the old code as broken or deprecated, wait a few years, remove the old code. This isn't hard. Of course, if Node or JS actually provided useful tools to mark things as deprecated, it might happen more often. Python's got DeprecationWarning; why doesn't Node? The "radical reusability" section is just the author realizing that modules are awesome. Again, welcome to the party.
- scubaguy 15y ago> Instead of the http server being an external service that we configure to run our code, it becomes just another tool in our arsenal. This is unfair. If I create a framework cal Java.js and make it possible to create a httpserver by running server.start(8080, aCallbackObject), does that make Java great? One day someone might make node.js "configurable" via a configuration file (that is not written in JavaScript). Will having a configuration file make node.js less useful? > Note also that the http snippet from earlier isn't inheriting from an http.Server base class or anything of the sort. That is also unfair. You typically don't use inheritance in JavaScript because you can compose objects or clone from a prototype. There is no static analysis of classes, which in the main benefit of classical inheritance. Programming via callbacks is simply the JavaScript style. This might even change when the language provides better support for classes, or when more people write their node.js code using CoffeeScript. > If software ecosystems are like economies then core libraries are at best government bureaucracies and at worst nationalized state corporations. This is very subjective and I strongly disagree. There is a great advantage in using a language and framework that has a strong core library and a common way of doing thing, especially when you start building teams or start recruiting people to maintain legacy code. If anything, Node should start including more batteries, such as a module for concurrency. PS - Here's the thing. I am really excited about the event driven nature of node.js and the community. However, I am new to node.js and I want to see quality critical analysis of its strength and weaknesses. If you are going to tell me its great, you better have pretty solid reasons. This article simply doesn't cut it.