Live data from Hacker News

The node.js aesthetic

substack.net

31–40 of 81 posts

Re: The node.js aesthetic

#31
post #2

Hmm, 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…

> 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.

This isn't really much black magic to it, all the use cases are outlined in the docs: http://nodejs.org/docs/v0.6.3/api/modules.html#loading_from_...

The bits that NPM does, is take advantage of the way node loads modules, and process dependencies recursively. For example take a look at how a few global modules are installed on my system:

  $ npm ls -g
  /usr/local/lib
  ├── bootstrap-stylus@0.2.0 
  ├─┬ express@2.4.6 
  │ ├── connect@1.7.1 
  │ ├── mime@1.2.3 
  │ └── qs@0.3.1 
This means that each of expresses dependencies, at the version listed, is installed into /usr/local/lib/node_modules/express/node_modules.

Also, by default npm installs into the current directory, or project which uses the same package.json format that modules themselves do. I find this to actually be the opposite of "black magic" since you use the same tools to manage your project at the top level, that is used to manage all your packages and dependencies.

Re: The node.js aesthetic

#32
post #29

Earlier quoted context omitted.

none of that has anything to do with writing web-request-handling code, it has to do with writing custom servers. There are plenty of asynchronous solutions for writing servers, including the very widely used Twisted platform as well as the Erlang programming language. It's a tad annoying that node.js is touted largely by front end developers as solving a supposedly previously unaddressed problem. to wit: > emerging…

The asynchronous aspects were a very small piece of the article for a reason. Node is doing a lot of very interesting, important, and novel things that aren't related to asynchronous events at all. Twisted in particular suffers from too much exposed surface area and having to manage the reactor yourself, which hurts reusability a lot.

I'd prefer to see a detailed article about that.

Also I'd like to see more detail on why exactly writing custom servers is so profoundly important all the sudden. I hardly see the advantage of even nginx over apache, though that's a different issue.

Re: The node.js aesthetic

#33

> 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 "b…

While 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.

Re: The node.js aesthetic

#34
I 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.

Re: The node.js aesthetic

#35
post #5

>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?…

When working with requests that share resources via web frameworks that deal with threads, the large consensus is to put the resource into an external managed resource. This external resource such as a database will manage the locking for you to prevent write conflicts, however, when caching values for complex interaction beyond CRUD you may have update conflicts where a new request has an in memory copy of an outdated resource. This is where the problem lies.

Re: The node.js aesthetic

#36

I 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…

You had me right up until:

> The "limited surface area" is all well and fine in JS, because there is no object inheritance in JavaScript

Re: The node.js aesthetic

#37

I 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…

You had me right up until: > The "limited surface area" is all well and fine in JS, because there is no object inheritance in JavaScript

Seek to the next paragraph and try again. Paragraphs are atomic; if there's a read error or other corruption on that first paragraph, the second one should still be readable. You should be able to get the entire message out if you use the error-correction channel to compensate.

JavaScript is prototyped, not inherited, and doesn't permit the creation of new types. 0/10; troll using facts next time.

Re: The node.js aesthetic

#38

Earlier quoted context omitted.

You had me right up until: > The "limited surface area" is all well and fine in JS, because there is no object inheritance in JavaScript

Seek to the next paragraph and try again. Paragraphs are atomic; if there's a read error or other corruption on that first paragraph, the second one should still be readable. You should be able to get the entire message out if you use the error-correction channel to compensate. JavaScript is prototyped, not inherited, and doesn't permit the creation of new types. 0/10; troll using facts next time.

JavaScript does have inheritance, and classes.

Please troll using facts next time.

Re: The node.js aesthetic

#39

I 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…

> Let's go ahead and compare with Twisted, shall we?

Oh goodness, yes.

How about an echo server. This one is from the twisted home page, so I am not knocking down a strawman.

    from twisted.internet import protocol, reactor
    
    class Echo(protocol.Protocol):
        def dataReceived(self, data):
            self.transport.write(data)
    
    class EchoFactory(protocol.Factory):
        def buildProtocol(self, addr):
            return Echo()
    
    reactor.listenTCP(1234, EchoFactory())
    reactor.run()

Versus in node you can do:

    var net = require('net');
    net.createServer(function (stream) {
        stream.pipe(stream)
    }).listen(5000)
This is what I mean by limited surface area. I shouldn't need to define 2 classes to write an echo server. An Echo class AND an EchoFactory? And on top of that I need to mess with a reactor? How does that pass for good API design?

Re: The node.js aesthetic

#40
post #5

>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?…

When working with requests that share resources via web frameworks that deal with threads, the large consensus is to put the resource into an external managed resource. This external resource such as a database will manage the locking for you to prevent write conflicts, however, when caching values for complex interaction beyond CRUD you may have update conflicts where a new request has an in memory copy of an outdat…

well, that's a cache invalidation issue. Any data that's cached, by definition may not be the freshest version, unless you've implemented a very nice write-through situation. If you'd like multiple requests to share an in-memory-only cache, potentially using write-through, then yes that deals with synchronization issues. I wouldn't characterize them as super-tough synchronization issues and you certainly won't have a "blocking IO" problem with an in-memory system.

If you want to write your own caching server, fine, use node.js. But now you're writing your own cache server, you've found some problem that memcached, redis, etc. all do not solve. Is this an everyday use case ?

Post reply on HN