Wednesday, November 20, 2013

Leaping into node.js and JavaScript, the Conculsion

In three weeks I've gone from node.js newbie to beginner  to having a module on npm.  Despite the off-beat field of endeavor (Flow Cytometry), it has dozens of downloads.  I think some are robots harvesting the net.

Things I liked:
  • WebStorm made working with GitHub simple and painless.  No more series of three commands to add files, commit locally, and push to the remote site.
  • Integration with Travis-ci was nearly painless.  The main gotcha was in pasting the cute little "the build is passing" icon back into the GitHub readme.  Capitalization matters.  If your repository is CamelCase, the links to travis-ci must be CamelCase.
  • The package.json file and conventions.  Simpler, and much less verbose, than your typical web.xml descriptor.  Use npm init to create a good template, and then it's simple to edit by hand.  I found the online docs fairly inscrutable.  Better to look at various package.jsons from other npm projects, then reread the man pages with the benefit of examples.
  • Publishing to npm was also painless.  My preference is to use a text editor, not npm commands, to edit the package.json file.  Once you have logged in for the first time to npm, just go   npm publish 
  • Using simple JavaScript "objects" { } to hold incoming options, and to return multiple values from a method.
  • JavaScript "short-circuit or" syntax to test for nulls and use defaults.  e.g.  encoding = options.encoding || 'utf8';
  • JavaScript's first class functions, combined with node.js Buffers, were superb in reading binary data from a file, handling various data sizes (16, 32, 64 bit) and endianness.
  • JavaScript's optional function arguments, most of the time.
Things that worked "o.k.":
  • All the node.js callbacks.  It is a huge mental shift.  A few times I got stuck with just too many callbacks to figure things out.  Still don't know how to read a Stream synchronously, since the basic rs.read() method doesn't work.  Rethinking or refactoring so that the callbacks were distributed across more methods helped.  In other words, instead of one function with three callbacks, consider refactoring into three functions, each with one callback.
  • Closures.  O.K., yes, they are nice.  For node.js, required.  But writing line after line ending with  function() {  and then adding all the }); at the end, and getting it right, gets old.  And verbose.  And these closures in general have no names, so they lose out as self-documenting.
  • Because it seemed cool and trendy, I used mocha for unit tests, instead of the more "JUnit-like" nodeunit.  But I couldn't run it well from WebStorm 7.0.  Lo and behold, one of the features of WebStorm 7.0.2 is improved support for Mocha!  Problem largely solved, I can run my unit tests from the IDE.  Code coverage is still an issue.
  • Not sure I'm a fan of Mocha's "literate" style.  In JUnit, I'd name my test method something like testReadFCSFile().  In Mocha, you use describe to wrap the anonymous function, e.g.   describe('Read an FCS File', function() ...)  JUnit is simpler and more concise.  OTOH, Mocha definitely encourages you to think about what the results should be.
Things that didn't work or were annoying:
  • "this" changes in a closure.  So you have to go  self = this, and remember to use self!
  • JavaScript thinking that it "O-O", but the terminology is pretty fuzzy and loose.  For example, those handy { } thingies that just hold a few snippets of data - what do you call them?  "Object" is just plain wrong, since they hold no real behavior, and "hash", (or "Map" or "Dictionary" or even "Key/Value pairs") which I greatly prefer, doesn't seem all that standardized.  Let's push for "hash" or "map"!
  • The documentation for setting up your test scripts is all Unix based, not Windows.  For example, their script suggested for mocha testing is  "test": "./node_modules/.bin/mocha"  which doesn't work at all under Windows.  I played around for an hour and found a workaround, "node node_modules/mocha/bin/mocha".  Turns out that there is a super-simple way, "test":"mocha". But I had to find this out by asking on StackOverflow.
  • I still haven't figured out how to get test coverage for mocha.  Looks like I might need to install Karma, then Istanbul, then whatever...  More to come.  I'm concerned that just as Windows has DLL Hell and Java has JAR hell, node may turn into NPM hell.
  • The documentation is still, er, "young".  Maybe as you expect, node.js is only in version 0.10.  A lot of times you have to make educated guesses, or look via the debugger, as to what events a Stream will emit.  Looking at the node source is helpful, but it is daunting for a JavaScript beginner and there are distressingly few comments in there.  Many are of the "here be Dragons" type around tricky code, not "here be the parameters".  Java and Javadocs are far superior here.
  • At least for methods, I really miss Java's "verbose" style, where you know the types of the arguments and the return value.  And the JavaDocs.  Too often in JavaScript / node you are guessing, or, once you are experienced, using your instincts, as to whether an argument is a String, a hash, or an object.  And often the answer is "all of the above".
  • A common Java practice is to have an "all-powerful" method (or constructor) with all possible parameters, and "convenience" methods that provide some default parameters.  Currying.  This proves to be very awkward in JavaScript, with ugly code like     
            [].unshift.call(arguments, moreArgs);
            allPowerful.apply(this, arguments);


Friday, November 15, 2013

Leaping into node.js and JavaScript, part deux

Well, I'm making a lot of progress since my post of two weeks ago.  Might be starting to get the hang of this JavaScript and node.js stuff.  First, a few followups from last post.


  1. I like WebStorm.  Well worth the small fee for a personal license.  Even just the way it makes Git and GitHub painless is almost worth the price.  And for a relative newbie blundering along it's great.  Especially since a lot of the node.js documentation is a bit sketchy.  Setting breakpoints and looking at fields is wonderful.  My only complaint is that sometimes it gets very very slow.  I'm using version 7.0.  There's a 7.0.1 upgrade available, not sure what it fixes.
  2. The SAMs book Teach Yourself node.js in 24 Hours has been pretty useful - much better than many of the "in 24 Hours" books.
  3. Professional Node.js: Building JavaScript Based Scalable Software is o.k., but a bit disappointing compared to most of the other WROX books I have read.
A few more resources I have found that seem useful:
  1. JavaScript the Definitive Guide is essential.  Get it.
  2. Manuel Kiessling is developing a Node Craftsman followup book.  I't still pretty early in development but might be useful. 
  3. A free download of JavaScript the Good Parts.  I'm temporarily ignoring some of his advice, but it's still a good reference.
  4. Of course, Stackoverflow, within limits.  Many of the responses are very client-HTML-ish (not node.js serverish) and not all are good.  But you can dig to find good information.
Javascript

  I'm coming from 20+ years of Java experience, and my JavaScript shows it.  I put in semicolons.  Looping over arrays I use a for-next with indices, not each().  I'd like to use for (var x in theArray)more, except that stupidly returns all the indices in the array, not all the values.  Sorry, makes no sense for an array, but since JavaScript arrays aren't real I understand whats going on.  But still been burned there several times.  And I still often mistype my loops as for (int i=0; i<....).  Where the "int" should be "var".  Of course, when I go back to programming in Java I'll surely make the opposite mistake.  :-)

  Creating a JavaScript class is fraught with way too much danger.  There are too many ways to do it, all the examples are different, and you can run into religious wars.  Frankly, I think a lot of the people writing have no clue about OOP classes.  I ended up using "classical" style, partly cause it worked well with node's CommonJS module structure to simplify the namespace and export issues, and mainly cause it felt most natural to me.  With more experience this may change.  Classical style uses the .prototype field a lot.  It is well described in JavaScript the Definitive Guide, 6th ed. in section 9.3, "Java-Style Classes in JavaScript".  Example classical style code below:

I'll talk more about working with node.js in future posts...