NodeJS – radical advance uses JavaScript on the Server!

I have heard a couple people in the past several weeks comment on how novel or noteworthy NodeJS is, for allowing devs to employ their beloved JavaScript language on the server!! Can you believe that? How awesome is it that we can write JavaScript on the server?!

Uh, folks, I’m here to tell ya, that ain’t new or novel.

By my reckoning, the first company to support JavaScript on the server side was named Netscape, and around 1995 or 96, they released Netscape Live Server, or something like that, which had a JavaScript programming model for web servers. Brendan Eich invented JavaScript in a rush-rush job, 10 days in May, 1995, for use in the Netscape browser. But Netscape also released a server platform that they tried to monetize, and it had a JavaScript-powered extension mechanism.

Not long after that, Microsoft released the NT Option Pack. I think this was in mid-1996. The Option Pack was a free add-on for Windows NT 4.0. An “out of band release”, they called it then. The NTOP included the first edition of ASP, what we now call “ASP Classic”, which allowed developers to use VBScript or JavaScript (Microsoft called it JScript then) to dynamically generate web content. (See The ABCs of Active Server Pages from 1997, content still on MSDN!).

ASP later became part of Windows NT, and in subsequent service packs and in Windows 2000, IIS + ASP was just “in there”. Prior to the NTOP, Windows NT 4.0 included IIS, but IIS was just a static web page server and CGI server. (I think). ASP was something a little different. By the way, ASP is still supported in IIS, yea verily, after yea these many years, 17 years by my count. So… to all those poeple who claim that Microsoft doesn’t support technologies long enough, ASP is counterexample #1.

Yes, I am not making this up: today you can install Windows Server 2008 or whatever the latest server is, enable ASP, and then deploy your JavaScript ASP code and begin serving web apps with it. It just works.

Classic ASP works for any type of content – so you can serve HTML markup of course, but also XML, or CSS (dynamically generated CSS? Maybe…) and of course client-side Javascript. This would be server-side Javascript potentially dynamically generating then emitting client-side JavaScript and yes, it is possible. Dynamic images, plaintext, of course any mime type, any content. What about REST APIs? Yes, you can use Classic ASP and JavaScript running on a Windows Server to implement a REST API, which is a use-case that is very common for NodeJS these days. Classic ASP can do content negotiation, can inspect and set cookies, can do anything a web platform can do. This also just works.

In practice, “Classic ASP” code often resembles what I will call “Rubbish PHP” code, which is to say, it mixes markup with code, willynilly, there’s poor templating, poor code re-use, poor use of classes and generally things are just an unmaintainable mess. But that is by no means required by either Classic ASP or PHP. That is just an unpleasant side effect of being really easy to use, which means novice programmers use it. Both Classic ASP and PHP have that quality. It is possible to author nicely architected ASP code, and PHP code.

Nicely architected? If I may be so bold, here’s an example.

        
        
      

In any case, NodeJS is by no means the first JavaScript-on-the-server runtime environment.

One thing that makes NodeJS different is asynchrony. Classic ASP did not support asynchrony very well.

On the other hand, NodeJS claims to be “super fast” or whatever. And from my point of view, Classic ASP running JavaScript was pretty fast dating back to 2002. Even in Windows 2000 Server, the Script host compiled the JavaScript and cached the compilation unit, so the first time you ran a page you’d incur the compile cost but thereafter all other requests executed the pre-compiled cached result. Which meant much better performance. And starting with Windows Server 2003, you could use the kernel-level cache in Windows Server, and lots of other nifty features. ASP really performed quite well. The performance of ASPNET on similar workloads is measurably better, but not by orders of magnitude. I would bet that Classic ASP with JavaScript gives NodeJS a run for its money on performance, even today.

As far as I know, Classic ASP has not been enhanced to use the new Chakra JavaScript engine. Chakra was built for IE9, the v8 competitor, and is significantly faster than the older Microsoft Script Host, about twice the throughput in the workloads I tested. I suppose that Microsoft did not see a customer benefit for using Chakra under Classic ASP. Classic ASP people aren’t clamoring for more performance out of their Classic ASP apps; at this point, they just want stability.

Another thing that sets NodeJS apart now, is the active community and the sharing. the npm is a beautiful thing, and while there were many many ASP Classic developers back in the day, there was no such thing as npm and they resorted to newsgroups and forums to share code. Primitive approaches compared to what we do now, for sure.

You are not an idiot if you use NodeJS

Just saw this. A Youtube rant by Brandon Wirtz clarifying for us all how stupid NodeJS is. From January 2012.

Most excellent. Well played. Even the title is deliciously Colbert-esque: “Node.JS Is Stupid And If You Use It So Are You”. Highly Recommended if you like nerd rants, and I mean that in the best way.

Even so, I disagree. Mostly I don’t disagree with the specific points Mr Wirtz makes, but I do disagree that those points are important, and I also disagree with his conclusion. Be assured: You are not an idiot if you use NodeJS.

Mr Wirtz’s main point is that NodeJS is based on JavaScript, which historically has been slow. Very slow, when compared to C/C++, pretty slow when compared to a modern Java or C#. JavaScript running in v8, which is what you get with NodeJS, is Fast fast FAST compared to JavaScript from 1997 running in an interpreter. But even so it is still has been slow compared to other options like C and Java.

So, why is this not a disqualifier?

First, lately, v8 micro-benchmarks (example 1, example 2) are showing that JavaScript can match the performance of C or Java, or even beat the performance of Java. I don’t put much stock in micro-benchmarks, because they are too simplistic and the performance they measure is often not indicative of real world scenarios. But even so, these benchmarks seem to show that the performance of JavaScript running on v8 is at least comparable. JS may not be faster than Java, but at least it is not orders of magnitude slower.

But more importantly, the performance of JavaScript is not a disqualifier for NodeJS because writing JavaScript is fun. People like it. People like coding in JavaScript, obviously, and many people are attracted to the idea of one-language-everywhere. Not in the Write-Once-Run-Anywhere (WORA) sense of Java circa 1997, but in the learn-once-write-for-anywhere sense. Just about everyone learns JavaScript. (though many of us learn it poorly. Douglas Crockford has said in his “Good Parts” lectures, that the people who know curly-brace languages like Java and C often begin to use JavaScript without actually learning it, because it’s forgiving, and they can actually limp through. In general, people don’t learn JavaScript very rigorously. As an example of this, not very long ago a respected colleague observed that JavaScript is “Not OO”, and many people have told me JavaScript, the language, is never JIT compiled.)

The obvious comparison is Java, which is a big pain to write. Building something in Java often requires very verbose code, lots of boilerplate, class structure and explicit interface implementation, and so on. The polar opposite of JavaScript.

To my mind, the popularity of NodeJS is similar to the popularity of PHP. People like both of these flawed environments because they mostly work and they are easy to use. NodeJS may be slow, or it may not be. But that is sort of irrelevant. Slow compared to what? It is theoretically slow, but practically speaking, it’s plenty fast for most applications. It’s faster than PHP or Ruby. Also, we have an embarrassment of Gigahertz riches and if we choose to frivolously spend CPU cycles on JavaScript engines, so what?

Also, unlike Mr Wirtz, I don’t care about whether the marketing around NodeJS is accurate or not. They say it’s really fast, and maybe that’s not generally true. But I don’t worry about that. The bottom line is: people like NodeJS because it’s nice and easy and friendly and familiar, and fun damnit, and the performance is plenty good enough.

That doesn’t mean that JavaScript or NodeJS is the answer to all programming questions. It isn’t. For large projects I’d be concerned about type integrity (though we can try using Microsoft’s TypeScript for that), or the hierarchy of modules. I think npm kindof just punted on that. Also the explosion of modules in npm makes it clear that NodeJS is a technology that is not quite stable. Lots of things are changing, very rapidly. There’s good and bad there, but surely the relative safety and stability of Java v6 offers a stark comparison. So NodeJS is not the answer to every problem, but it is a good answer to many programming problems. You’re not stupid if you use NodeJS.

If I were advising a young aspiring programmer today, I’d tell them to learn JavaScript and Go.

Pet peeve – NodeJS people, What’s with “err”?

This is a pet peeve of mine.

I think the code is the documentation, and names of variables, functions, and classes used in the code are important. These names communicate the purpose of the things being named.

It makes sense that Node’s package manager is called “npm” because that denotes “node package manager.” Easy to decipher, and if you know what a package manager is, then you know what npm is. No need to think about it.

The names of variables in a program implemented in any particular language are also important. i and j indicate loop indices. Variables like req and res might indicate a request and a response object, respectively, though in many cases I would prefer to just see request and response.

Ok

  var http = require('http'),
      server = http.createServer();

  function handleRequest(req, res) {
    res.writeHead(200, { 'content-type': 'text/plain'});
    res.write('Hello, World!');
    res.end();
  }

  server.on('request', handleRequest);

  server.listen(8080);

Better

  var http = require('http'),
      server = http.createServer();

  function handleRequest(request, response) {
    response.writeHead(200, { 'content-type': 'text/plain'});
    response.write('Hello, World!');
    response.end();
  }

  server.on('request', handleRequest);

  server.listen(8080);

Or, if you look at Java, something like an exception is usually named with an e, or an exc, sometimes followed by a numeric suffix. Like so:

    try {
        arf me = new arf(args);
        me.Run();
    }
    catch (java.lang.Exception exc1) {
        System.out.println("Exception:" + exc1.toString());
        exc1.printStackTrace();
    }

It makes sense.

To err is human.

Which brings me to the point. There are numerous examples showing how to code a callback function in Node, that look like this:

  fs.readFile('/etc/passwd', function (err, results) {
    if (err) {
      handleError(err);
      return;
    }
    console.log('File contents:', results);
  });

As you can see, the variable that holds the error is called err. Now if English is one of the languages you use, which is probably true if you are reading this, then you probably know that “error” is a noun and “err” is a verb.

Using the verb form of that word as a “shorthand” for the noun is confusing to code reviewers, and therefore wrong. Yes, everyone is assumed to know that “err” really refers to an error, but everyone incurs a small but not negligible mental burden in reconciling that difference, every time they look at that variable. Why? To save 2 characters? If really we are economizing on variable name length, and I respect efforts to do so, then why not just use the letter e, which is often used to represent errors or exceptions?

Either e or error is preferred over err.

An error does not become truth by reason of multiplied propagation, nor does truth become error because nobody sees it. – Mahatma Gandhi

I hate Node.js

Node.js is cool, so they say. Everybody’s doing it, so I hear.

I hate it. Node.js has wasted so much of my time, I don’t think I will ever forgive it. But take that with a grain of salt. I don’t use Node.js for its intended purpose, which is server-side Javascript.

What I want is a scripting environment for automation on the local machine. In this particular case, I want to script an FTP session from my bash prompt, I want to script a directory sync. I know I can do this with bash scripting, but I already know Javascript syntax and semantics, so I’d like to use what I know. It’s FTP in this case, but in general I want to be able to script arbitrary things on the local machine.

By the way: I can do this on Windows. I can run Javascript programs from the CMD shell, to script an FTP session, automate filesystem operations, launch applications, and a bunch of other things. It’s really nice. There’s a whole catalog of COM objects that can be scripted, including obscure stuff like the fax system in Windows, or more mainstream things like IE settings (like proxies), or IIS administration. Tons of things.

Of course I could do similar things with Node.js on MacOS, too. The problem is, the Node.js model is designed for server use. Everything is asynchronous. When I retrieve a set of files from an FTP server, and I want to iterate and retrieve each file, I have to do that asynchronously. But I don’t want it to be asynchronous. Writing asynchronous code lets me get really good throughput on a server. Writing asynchronous code for my purpose just obscures the goal of the code. I want to do this:

    fileList.forEach(function(item) {
        var modTime = ftp.getModTime(item);
        if (modTime > lastUpdate) {
            ftp.retrieveFile(item);
        }
    });

But I can’t do that. No sir. No I cannot. I’m using Node.js. And because of that, I need this:


    var c = 0, L = flist.length, 
        checkIfDone = function() {
            c++;
            if (c == L) { next(); }
        };

    fileList.forEach(function(item, ix) {
        var localPath = (dir == '.') ? item : Path.join(dir, item),
            stat, localMtime = ...,
            remoteMtime = 0;

        // get modification time of the remote file
        sync.ftp.raw.mdtm(localPath, function (e, res) {
            var d, tm;
            if (e) { }
            else {
                remoteMtime = new Date(res);
                if (localMtime == 0 || (remoteMtime > localMtime)) {
                    // Retrieve the file using async streams
                    sync.ftp.getGetSocket(localPath, function(e, sock) {
                        if (e) return console.error(e);
                        var fd = fs.openSync(localPath, "w+");

                        // `sock` is a stream. attach events to it.
                        sock.on("data", function(p) {
                            fs.writeSync(fd, p, 0, p.length, null);
                        });
                        sock.on("close", function(e) {
                            if (e) return console.error(new Error("error"));
                            fs.closeSync(fd);
                            checkIfDone();
                        });

                        // The sock stream is paused. Call
                        // resume() on it to start reading.
                        sock.resume();
                    });
                }
                else {
                    checkIfDone();
                }
            }
        });
    });

Can anyone ELSE see why I’d rather not use an asynchronous-optimized, server-oriented programming environment to script my desktop?

It’s not Javascript that’s the problem here. I can grab the v8 Javascript engine and use it to run JS code. That works. The problem is that there are no JS libraries for v8. There’s no FTP library. There’s no “any” library. The only FTP libraries I’ve found are Node-compliant. To use it, I have to do Node.js things. Likewise for all the other purposes. There’s no package manager for JS libraries, except for Node.js.

I think the solution here is for me to learn to use Bash scripting and use CURL. But that’s a lame solution. It would be nice if MacOS supported Javascript for client-side use, as nicely as Windows does. Because I hate Node.js.