Archive for the ‘books’ Category

js4php: thanks!

Monday, April 15th, 2013

JS4PHP book is almost a wrap! It started as "well, I have this blog post, then I have these slides from this conference, how hard could it be to make it into a book form?" Pretty hard, turns out. I'm surprised every time. Takes a while, you get distracted by something shinier and so on... No such thing as "quick book project", for me, at least.

But it's almost ready to go, O'Reilly folks are optimistic it will be done in time for the Fluent conference in May (where I'm not speaking btw). The price on Amazon really makes me happy, I think $7.90 for a tech book is unheard of.

JavaScript for PHP developers

So anyway, just wanted to say thanks to people that helped with the book along the way.

Thanks

First and foremost, big thanks and gratitude to my second-time reviewers who helped me with "JavaScript Patterns" before, the Three Musketeers and d'Artagnan, the ever-so-amazing Andrea Giammarchi, Asen Bozhilov, Dmitry Soshnikov and Juriy "kangax" Zaytsev. As with the previous book they helped me tremendously with their deep knowledge and experience with JavaScript, their attention to detail and technical accuracy above all. You'll see little notes in the book following bold general statements, these notes often come from one of these guys saying: "hmm, this is not entirely correct and not always true, because...". I am forever in debt to these four ridiculously talented developers who also happen to be great and friendly people.

Many thanks to Chris Shiflett and Sean Coates. They made sure the PHP side of things make sense, but what's more, this whole book started as a post on their PHPAdvent (now WebAdvent.org) blog, followed by a talk at the ConFoo conference which Sean helps organize.

Next, thanks to the Facebook engineers that hang out on the JavaScript group. I posted an early draft there asking for comments. Three people even went through the whole thing and gave me invaluable feedback and further nitpicking, which is the best quality in a technical reviewer. Thanks to Alok Menghrajani, James Ide and Alex Himel.

Finally, thanks to Randy Owens who read the "early release" of the book and meticulously filed tens of errata reports.

Unit testing in AsciiDoc

Tuesday, February 12th, 2013

While finishing off this book, which I choose to write in AsciiDoc format, I really appreciate the time I took to write myself a handy little script for testing the little code examples. Because, something always gets wrong in the final steps of editing and is nice to have some automated assurance that you didn't break something stupid.

AsciiDoc or MarkDown or some other text setup is how technical books should be written. Or any books, really. Having clear plain text lets you focus on the content and not wrestle with Word formatting. And it's also easy to parse and test.

Code in AsciiDoc

The code blocks in AsciiDoc are easy to spot. They look like:

[source,js]
----------------------------------------------------------------------
var a = 0xff;
a === 255; //:: true
----------------------------------------------------------------------

Testing and linting

All you have to do in a little unit testing utility is to extract these clearly defined blocks and run them to make sure there are no silly syntax errors, creeping in in the very last edits.

But why stop with a syntax check? Why not also run jslint and also instrument and run the code and see any expected values. Asserts, in testspeak.

In my setup I did just that: lint with jshint, instrument the places where I know the expected values, lint these too (why the hell not?), run them and assert the expected values.

Output

Here's how the output of the utility looks like:

$ node scripts/test.js 
passed: 362, skipped: 43
linted: 317, nolints: 45

Since this is a book with some educational bad examples, not everything can be linted. Or run for that matter.

JSHint

I choose JSHint over JSLint as it allows more flexibility to relax the rules. Also it's a node module I can import.

var jslint = require('jshint').JSHINT;

These are my lint options:

// JSHint options need to be more relaxed because the book also
// points out bad patterns
var lintopts = {
  indent: 2,   // 2 spaces for indentation
  trailing: true, // disallow spaces at the end of a line
  white: true,
  plusplus: false, // allows ++ and --
  browser: true,   // assumes some common browser globals exist
                   // such as `document`
  node: true,  // assumes the code can run in node.js
               // and globals such as `global` are defined
  expr: true,  // ok to have expressions that seemingly do nothing
               // such as `a; // true` which the samples use to show
               // result values
  loopfunc: true, // allows definition of a function in a loop
                  // for educational purposes (in the part about closures)
  newcap: false,  // allows calling constructors (capitalized functions) 
                  // without `new`, again just for educational purposes
  proto: true,    // allows using `__proto__` which is great for understanding
                  // prototypes, although it's not supported in all browsers
};

And the lint function that lints a snippet of code:

// lint a snippet
function lint(snip) {
  // lint the snippet with all the options and have it assume
  // assert objext exists
  if (!jslint(snip, lintopts, {assert: false})) {
    log('------');
    log(snip);
    log('------');
    log(jslint.errors[0]);
    process.exit();    
  }
}

Instrumenting and executing a snippet

Execution is simple:

// run a snippet
function exec(snip) {
  // muck some stuff up and zap log()
  var mock = "function define(){}; function alert(){}; console.log = function(){};";
  try {
    eval(snip + mock);
    passed++;
  } catch (e) {
    log('------');
    log(snip);
    log('------');
    log(e.message);
    process.exit();
  }
}

The instrumentation is a little more interesting.

I often write snippets like:

// assign
var a = 1;
// test
a; // 1

Now I need a little bit of marker that will tell the instrumentation that a; is a piece of code to execute and 1 is the expected value. I came up with //::

So the above becomes:

var a = 1;
a; //:: 1

I also like to add some more explanation besides the returned value. I use ,, for that. So:

var a = 1;
a; //:: 1,, as you'd expect

Instrumented, this becomes:

var a = 1;
assert.deepEqual("a;",  1, "Error line #2");

The line is the line in the book with all code and prose, so it's easy to find.

The special markup like //:: and ,, gets stripped by another script that I run before commit.

A few other features are: support for NaN which doesn't deepEqual to anything and expecting errors with assert.throws(..)

So I can write and test code like:

sum(21, 21); //:: 42
plum(21, 21); //:: Error:: plum() is not defined

(:: that follow Error is the same as ,,)

Also:

Number("3,14"); //:: NaN

So here's the code instrumentation:

// Add asserts
function prep(l, n) {
  var parts = l.split(/;\s*\/\/::/); // "//::" separates expression to execute from its result
  var nonspace = parts[0].match(/\S/);
  var spaces = nonspace === null ? "" : Array(nonspace.index + 1).join(" ");
  parts[0] = parts[0].trim();
  if (parts[1]) {
    var r = parts[1].split(/\s*(,,|::)\s*/)[0].trim(); // the result may have ,, or ::, ignore what's on the right
                                                       // e.g. //:: true,, of course!
                                                       // e.g. //:: ReferenceError::Invalid whatever
    if (r.indexOf('Error') !== -1) {
      // expect //:: Error to throw
      return spaces + 'assert.throws(function () {' + parts[0] + '; }, ' + r + ', "error line #' + n + '");';
    }
    if (r === 'NaN') {
      // special NaN case
      return spaces + 'assert(isNaN(' + parts[0] + '), true, "error line #' + n + '");'
    }
    // usual
    return spaces + 'assert.deepEqual(' + parts[0] + ', ' + r + ', "error line #' + n + '");';
  }
  return l;
}

Main

Dependencies, locals, options and the main parser loop is how it all begins/ends:

// dependencies where I can see them
var assert = require('assert');
var fs = require('fs');
var jslint = require('jshint').JSHINT;
 
// buncha local vars
var snip, rawsnip.....;
 
// short
var log = console.log;
 
 
// JSHint options 
var lintopts = {
  indent: 2,   // 2 spaces for indentation
  // ....
};
 
// read the book one line at a time
fs.readFileSync('book.asc').toString().split('\n').forEach(function(src, num) {
 
  // src is a line in the book
  // num is the line number
 
});

There are a few additional features at snippet-level:

Ability to continue from a previous snippet using --//-- at the top of the snippet delimiter

Let's declare a variable:

[source,js]
----------------------------------------------------------------------
var a = 1;
----------------------------------------------------------------------

And then another one:

[source,js]
--------------------------------------------------------------------//--
var b = 2;
----------------------------------------------------------------------

And let's sum

[source,js]
--------------------------------------------------------------------//--
a + b; //:: 3
----------------------------------------------------------------------

Ability to skip a non-working snippet using ////

[source,js]
----------------------------------------------------------------------////--
var 1v;  // invalid
----------------------------------------------------------------------

Ability to run in non-strict mode (because strict is default) using ++

[source,js]
----------------------------------------------------------------------++--
var a = 012;
a === 10; //:: true
----------------------------------------------------------------------

nolint option

[source,js]
----------------------------------------------------------------------
/*nolint*/
assoc["one"]; //:: 1
----------------------------------------------------------------------

Cleanup before commit

Cleaning up all instrumentation markers and hints for the lint and the tests (gist):

var clean = require('fs').readFileSync('book.asc').toString().split('\n').filter(function(line) {
  if (line.indexOf('/*nolint*/') === 0 || line.indexOf('/*global') === 0) {
    return false;
  }
  return true;
})
  .join('\n')
  .replace(/--\+\+--/g, '--')
  .replace(/--\/\/--/g, '--')
  .replace(/--\/\/\/\/--/g, '--');
 
console.log(clean);

Github gist

Here's the test.js script in its entirety.

And the winner is…

Tuesday, April 5th, 2011

In the previous post I announced that one person will win a copy of the Brazilian Portuguese translation of JavaScript Patterns. So here's the winner:

@LouMintzer

He wins a signed copy of "Padrões JavaScript". Waiting for your mailing address, Lou :)

Update: Lou Doesn't speak Portuguese, so he gets an English copy. The second winner is:

@puresight

Update: Monty is not too proud of his Portuguese skills either, so third is

@abozhilov

Asen is an awesome JavaScripter, who actually reviewed the book (thanks a million!) and he already has a copy. Next.

@mexitek

How I picked the winner

By writing some JavaScript in the console, of course.

The winner was to be randomly picked from all those who retweet my tweet or post a comment in the announcement. So I had to collect those.

Twitter

The tweet page says there has been 27 retweets (worded a bit like 28, but looks like it's 27). The page only shows about 15 people though and I need all of them. Given how Twitter doesn't let you search older stuff, I was afraid it was too late. I had to check the API first. I was expecting I can hit a few URLs and get the data I need. Tough luck. All these auth keys, tokens, secrets and stuff got me floored.

Luckily Twitter's UI is also using the APIs. Checking the network traffic I was able to spot the request I need!

The URL is:
http://api.twitter.com/1/statuses/49323240014872576/retweeted_by.json?count=15
I only needed to change the count to something over 27, so I made it 30. Lo and behold I got the data!

The rest of the stuff I did in Safari's Web Inspector console.

Visiting the URL:
http://api.twitter.com/1/statuses/49323240014872576/retweeted_by.json?count=30

We have a JSON array as a document.

>>> var a = document.body.innerHTML
>>> a
"<pre style="word-wrap: break-word; white-space: pre-wrap;">[{"profile_link_color":"0084B4","verified":false,"not....]</pre>"

Safari puts all in a PRE behind the scenes, so this is how we get the data:

>>> var source = $$('pre')[0].innerHTML;
>>> source
"[{"profile_link_color":"0084B4","verified":...]"

eval() it:

>>> source = eval(source)
[Object, Object...]
>>> source.length
27

Sounds right. Now let's move all usernames into a new array using the new ECMA5 forEach fancy-ness:

>>> var all = [];
>>> source.forEach(function(e){all.push(e.screen_name)})
>>> all.length
27
>>> all
["jrfaqcom", "gustavobarbosa", "gabrielsilva", ...."vishalkrsingh"]

Blog comments

I had 4 comments on the original post. WordPress puts all comments in a div with class commentlist, so this allows us to grab all comments:

>>> var comments = $$('.commentlist cite a')
>>> comments.length
4

Now let's only grab the names, they are in the href's innerHTML:

>>> var all = [];
>>> comments[0].innerHTML
"Fabiano Nunes"
>>> comments.forEach(function(e){all.push(e.innerHTML)})
TypeError: Result of expression 'comments.forEach' [undefined] is not a function.

Eh? What? Oh, the list of HREFs is not an array but a NodeList:

>>> comments
[
<a href="http://fabiano.nunes.me" rel="external nofollow" class="url">Fabiano Nunes</a>
, 
<a href="http://www.gabrielizaias.com" rel="external nofollow" class="url">Gabriel Izaias</a>
, 
<a href="http://www.jrfaq.com.br" rel="external nofollow" class="url">João Rodrigues</a>
, 
<a href="http://www.jrfaq.com.br" rel="external nofollow" class="url">João Rodrigues</a>
]
>>> comments.forEach
undefined

So, list of nodes converted to array:

>>> comments = Array.prototype.slice.call(comments)

Now forEach is usable:

>>> comments.forEach
function forEach() {
    [native code]
}
>>> comments.forEach(function(e){all.push(e.innerHTML)})

So we have a list of all names. Lets serialize it, so it can be pasted to the other window where we had the Twitter data.

>>> all
["Fabiano Nunes", "Gabriel Izaias", "João Rodrigues", "João Rodrigues"]
>>> JSON.stringify(all)
"["Fabiano Nunes","Gabriel Izaias","João Rodrigues","João Rodrigues"]"

(Simple array join and then string split will do too in this simple example)

All together

Back to the twitter window. Deserializing the comments array:

>>> comments = JSON.parse('["Fabiano Nunes","Gabriel Izaias","João Rodrigues","João Rodrigues"]')
["Fabiano Nunes", "Gabriel Izaias", "João Rodrigues", "João Rodrigues"]

Merging the two arrays

>>> all = all.concat(comments);
["jrfaqcom", "gustavobarbosa", ...."João Rodrigues"]
>>> all.length
31

Perfect. 31 entries. Just as many as the days in March when I announced it. So let's take the 19th array element to be the winner.

But shuffle the array a bit first.

Suffle

Sorting the array by randomness. (I shuffled and reshuffled it three times, just because.)

>> all.sort(function() {return 0 - (Math.round(Math.random()))})
["ravidsrk", "anagami", "lpetrov", ...]

And the winner is:

>>> all[18]
"LouMintzer"

“JavaScript Patterns” now in Brazilian Portuguese

Sunday, March 20th, 2011

Padrões JavaScript

I've been terrible at promoting this book. But that should change starting today :)

So today I got a copy of "Padrões JavaScript" - the Brazilian Portuguese translation of JavaScript Patterns. Happy, happy, happy!

Given that I already got two copies few weeks ago, kept one and sent one to my mom for her collection, I thought I should give this one away.

If you want to enter for a chance to win a signed copy of the Brazilian Portuguese translation of JavaScript Patterns, you can do one or more of the following:

  • Leave a comment below, or/and
  • Retweet this

That's it, shipping's on me. Boa sorte!

pssst, here are two PDFs: table of contents and about half of chapter 1 for you evaluation pleasure :)

Book is almost out

Saturday, September 4th, 2010

The JavaScript Patterns book is to be sent to the printer next week and will be available as expected (and mentioned on Amazon) on or before Sept 28. Yey!

Dunno who said: writers don't like to write, they like to have written. Exactly how I feel today.

And let me share a quote from my favorite Kurt Vonnegut along the same lines. The book is Bluebeard.

    She asked me what had been the most pleasing thing about my professional life when I was a full-time painter -- having my first one-man show, getting a lot of money for a picture, the comradeship with fellow painters, being praised by a critic, or what?
    "We used to talk a lot about that in the old days," I said. "There was general agreement that if we were put into individual capsules with our art materials, and fired out into different parts of outer space, we would still have everything we loved about painting, which was the opportunity to lay on paint."
    I asked her in turn what the high point was for writers -- getting great reviews, or a terrific advance, or selling a book to the movies, or seeing somebody reading your book, or what? She said that she, too, could find happiness in a capsule in outer space, provided that she had a finished, proofread manuscript by her in there, along with somebody from her publishing house.
    "I don't understand," I said.
    "The orgastic moment for me is when I hand a manuscript to my publisher and say, 'Here! I'm all through with it. I never want to see it again,' " she said.

So - whew!

Expect a more detailed post about the book (and the wonderful team of JS guru tech reviewers!), after all I have to start promoting it, don't I?

Literal Notations

Saturday, May 17th, 2008

A little something from my forthcoming book "Object-Oriented JavaScript" I thought would be nice to share.

Literal Notations
name literal constructor example
object {} new Object() {prop: 1}
array [] new Array() [1,2,3,'test']
regular expression
/pattern/modifiers new RegExp('pattern', 'modifiers') /java.*/img

Doug Crockford on inheritance

Tuesday, May 6th, 2008

JavaScript, the good parts

From YUI blog today, there is a free chapter of Douglas Crockford's JavaScript book.

It's a great read. I had the pleasure of reading drafts of the book and giving some inputs (Whoa, giving Doug Crockford input with his JavaScript book! Yeah, I know.) and I can only highly recommend the book. But don't take my word for it, go download the free chapter and decide for yourself.