Monday, December 27, 2010

I got a new computer for Christmas! Sorta...

About a year ago, I bought myself a Lenovo ThinkPad (T500). Because I had been working at Google from 2005-2009 and my work laptop was sufficient for surfing the Web while at home, my last personal laptop purchase was in 2004 when I bought an IBM ThinkPad (T42). I loved my ThinkPad, as I spent many hours of quality time with it implementing my Master's thesis at MIT.

Therefore, when it came time to buy a new machine in 2009, I decided to look at ThinkPads. Yes, I had heard that the quality of the ThinkPad had dropped considerably ever since Lenovo had taken things over from IBM. Yes, all my friends were developing on Macs, but I found them to be irritating to type on and my primary development applications (Google Chrome and Eclipse) felt slow on OS X. And yes, Windows has more than its share of annoyances. At the time, ThinkPads were shipping with Vista (arguably one of the worst Windows releases ever), but they came with a voucher for a free copy of Windows 7, which was reported to be a substantial improvement.

After weighing all of my options, I decided to save some cash and buck the trend of my contemporaries: I chose to be a PC instead of a Mac.

From the abysmal experience of making my online purchase of a Lenovo ThinkPad, I should have known that my experience with the machine itself would also be a disaster. The Lenovo web site was slow and failed to communicate what I was buying. I inadvertently bought a machine with a 32-bit processor (I still don't know why any new machine in the fall of 2009 would not be 64-bit), which could not take advantage of the 4GB of RAM that I paid for. (Searching online forums, I do not appear to be the only one who has made this mistake.) Further, it took two to three weeks to get my laptop. If I had decided to buy a Mac, I could have just walked to the Apple store and had one in my hot little hands that day.

Then there was Vista. Vista makes me angry. Sometimes when my laptop goes to sleep, it also turns off the wireless radio and fails to turn it back on when the machine wakes up. Sometimes the physical buttons to control the volume of the laptop fail to communicate with Vista. (Being unable to control the volume of your computer can be an embarrassing experience.) Sometimes the built-in video camera works, sometimes it doesn't, but either way, rebooting (the go-to solution for any Windows user) is an unreliable fix for the problem. The DVD drive is also finicky, as it inexplicably pops open from time to time. Overall, this is a horrible experience.

But hey, what about that Windows 7 voucher? Apparently you had to redeem it by calling Lenovo customer support after Windows 7 was officially released, which was several weeks after I got my ThinkPad. "Call Lenovo" sat near the bottom of my to-do list for months (who is eager to call customer support?), so by the time I made time to call Lenovo, they told me that my voucher had expired. I complained and they said they would speak to someone and contact me with a response, but they never did.

After all of this, I was incredibly unhappy with my ThinkPad. I wanted to try to put Linux on it, but I had a number of speaking engagements coming up where I was going to present from my laptop, so it did not seem prudent to wipe my machine before embarking on a series of talks. Though even after my speaking series was over, it was hard to find the time to sit down and install Linux. I had never done it by myself before, and I wanted to take the time to read up on it so I could understand what I was doing and have a backup plan in case I was unsuccessful and needed to revert back.

This year, on Christmas Day, I decided to just go for it and install Ubuntu on my ThinkPad. I copied the .iso onto a USB stick, wedged it in the side of my ThinkPad, and rebooted. I hit F1 to change the bootloader to run off the USB stick and made it to the Ubuntu installation screen. I spent a bit of time playing with options to repartition my hard disk so that I could preserve Vista and my files in case I needed to get them back (for me, this has always been the most confusing part when trying to step through a Linux installation), but I got fed up and decided that all of my important data was in the cloud (which includes Mercurial and SVN repos on other machines) and that I had no desire to go back to Vista anyway, so I decided to dedicate the entire hard disk to Ubuntu and abandon Vista forever.

When I decided to blow away my operating system, I knew that it would likely be a rash decision that I would pay for later, but so far, it has been FREAKING AWESOME! The physical volume buttons on the ThinkPad just work. The Google Talk plugin for Linux also just works. And instead of the dual, competing gaudy wireless managers in Vista (one provided by Windows and the other provided by Lenovo), there is now a single, simple icon/dropdown interface in the toolbar to select a wireless network, just like on OS X.

Using my laptop is now enjoyable again. It feels like I got a brand new machine, so even though I didn't manage to get the new computer that I really wanted for Christmas, this certainly seems like the next best thing.

Want to learn more about Closure? Pick up a copy of my new book, Closure: The Definitive Guide (O'Reilly), and learn how to build sophisticated web applications like Gmail and Google Maps!

Thursday, October 21, 2010

Slides from MIT Talk

Last week, I gave two talks about Closure in Cambridge: one at Google and the other at MIT CSAIL. I had a great time and fielded lots of good questions from sharp individuals, so I'm looking forward to my next two speaking events in New York City.

As someone requested that I upload my slides, I am more than happy to share them:



I would argue that one of the best parts of the talk is the plovr demo, which sadly is not communicated through the slides. Though if you are in the NYC area, you can come and see such a demo live if you come to one of my upcoming talks! Also, O'Reilly provides me with three copies of my book to give away at each event, so even if you aren't interested in plovr, you are probably interested in the chance to win a free book! (Though I am embarrassed to admit that I don't have the hang of how to run a "giveaway" yet, so at the MIT talk, I ended up giving books to those who hung out the longest to ask questions.)

Though after spending quite a bit of time preparing my talks last week, I am pretty disappointed with my experience creating a presentation with Google Docs. Given that the UI is displayed using HTML and CSS, it should be dead simple to change the color palette of a presentation. For example, I am generally interested in three styles: slide title, plain text, and sample code. Every time I want to set text as sample code, I have to select the text, choose "Courier New" from the font dropdown and then select my code color from the font color picker. Under the hood, there are tons of <div>s with the same inline CSS styles whereas if I created my slides by hand in HTML, I would have many <code> tags that could easily be restyled with a single CSS rule.

Trying to use different themes for Google and MIT for the same presentation would have taken hours because of all the time mousing around to select text and change all the styles, so I didn't even try. I know that Google Docs is nowhere near Keynote or Powerpoint in terms of its feature set, but I didn't realize how far behind it is. It only comes with 15 themes, and I'd argue that none of them are particularly good for a developer who wants to display code samples. I would switch to a Microsoft or an Apple solution, but I am often switching between computers, and the thought of emailing a slide deck around and clogging my inbox with twenty versions of the same presentation is depressing.

There's a good chance that I'll build my own lightweight presentation editor in HTML that is tailored for creating talks by software engineers. I basically had to do something similar in order to write my book, but that's an exciting topic for a future blog post!

Want to learn more about Closure? Pick up a copy of my new book, Closure: The Definitive Guide (O'Reilly), and learn how to build sophisticated web applications like Gmail and Google Maps!

Monday, October 11, 2010

Upcoming Talks

Over the next couple of months, I will be giving several talks about Closure:

October 13: Getting the most out of Closure
Google: Cambridge, MA

October 15: Building a 100K LOC JavaScript application with Google Closure
MIT CSAIL: Cambridge, MA

October 27: Introduction to Closure Tools and plovr
Google: New York, NY (as part of the NYC-GTUG Meetup)

November 10: Compiling your web site: Closure compiler
Location TBA: New York, NY (as part of the Web Performance NY Meetup)

If you are in the area for any of these talks, please come and say hello! I'm also more than happy to sign books (and may even be giving some away!) at each of these talks.

Hopefully, I will also get a chance to speak at both the Boston and NYC JavaScript meetups. I also hope to make it out to the Bay Area, Austin, Chicago, and Sydney (where I seem to have an open invitation!). As I have no official "book tour," my personal travel basically determines when and where I set up speaking events.

Want to learn more about Closure? Pick up a copy of my new book, Closure: The Definitive Guide (O'Reilly), and learn how to build sophisticated web applications like Gmail and Google Maps!

Wednesday, October 6, 2010

Creating a 100K LOC Application in JavaScript with Closure and plovr

Last night at an MIT infosession for Yext, I presented some statistics about the codebase for Yext Rep, which is our free, online reputation management system for local businesses. Rep is a substantial Rich Internet Application (RIA), topping out at just over 144K lines of JavaScript and Closure Templates, which amounts to over 4MB of JavaScript. In the spirit of a traditional RIA, Rep is a single web page that dynamically loads both code and data via AJAX (navigation state is stored in the URL fragment, just like in Gmail).

The first challenge in writing a 100K LOC JavaScript application is managing the codebase. Fortunately, the Closure Library provides both a comprehensive API and a meaningful way to organize dependencies in JavaScript. By using thoughtful namespaces and explicit dependencies, it is easy to find the functionality you are looking for and to build things up without creating cyclical dependencies.

The second challenge, of course, is getting the application to load quickly even though there is 4380K of JavaScript to send down to the browser. Any solution that would prevent Rep from loading quickly would not be an option. As you may have guessed, leveraging Closure makes it possible for us to reduce that 4380K down to 73K, which is less than 2% of the original size. Here is how it breaks down:

KB Technique
4380 Original JavaScript
709 Compilation using the Advanced mode of the Closure Compiler (84% reduction)
215 Dividing the compiled code into modules using plovr (70% reduction)
73 gzip (66% reduction)

One of the less commonly known techniques that we use is dividing JavaScript into modules. This is a feature of the Closure Compiler, but using plovr makes the module splitting feature of the Compiler far more accessible and manageable. Over the weekend, I worked on improving module support in plovr. There are still a few bugs left to shake out, but I plan to do another release of plovr with more detailed documentation on modules soon.

Want to learn more about Closure? Pick up a copy of my new book, Closure: The Definitive Guide (O'Reilly), and learn how to leverage Closure to create your own RIA!

Monday, September 27, 2010

Give a man a fish or teach a man to fish?

Ostensibly, Closure: The Definitive Guide is a book about Closure, a suite of JavaScript tools from Google, but I tried to make it about more than that. It also discusses some of the more subtle aspects of JavaScript, examines the clever aspects of Closure’s design, and espouses best practices for software engineering. That last point is of particular importance to me, because as I explain in the preface, I expect the size of JavaScript codebases to grow quickly in the coming years (if not sooner), and developers will need Closure (or something like it) in order to do JavaScript programming in the large.

Therefore, even if you have adamantly committed yourself to jQuery, I think you will learn a lot from this book. As some members of the jQuery community have already begun to concede, jQuery is not the right solution for large software projects. Perhaps jQuery will reach a point where it is redesigned for writing more complex applications, and if it does, I certainly hope it looks to Closure for guidance. If one wants to build something that rivals Gmail or Google Maps in frontend sophistication and performance, then why not look to the toolkit that made those products possible and learn from the design decisions that shaped it?

An alternative interpretation of Closure: The Definitive Guide is that it is just a braindump of everything I learned about web development while at Google. As I chose to spend four years at Google rather than in a PhD program, I often think of the book as my dissertation (though unlike a doctoral thesis, someone will actually read it -- zing!). However, the analogy does not quite fit, as I cannot claim Closure to be a product of my own research. At Google, I was far more often a consumer of Closure than a producer. Yet in the course of writing the book, the balance has shifted, and I have found more time to submit patches, file bug reports, and build tools on top of Closure such as plovr. I think that it was only until I had really gotten into writing the book that I could fully appreciate the entire toolkit and confidently contribute back to all areas of it, knowing that my contributions would be consistent with its underlying principles.

Which brings me to the title of this blog post: Give a man a fish or teach a man to fish? In a world filled with O’Reilly cookbooks and Stack Overflow articles, I often see developers focused on consuming the information that helps them fix the issue that they are currently debugging and then moving on to the next problem. The drawback of this approach is that when that developer encounters a problem that no one has blogged about, he is stuck. Because the Web has always given him fish, he has no idea how to fish when Google cannot find the answer.

For this reason, Closure: The Definitive Guide aims to be a “teach a man to fish” type of book. When I think about my favorite technical books, such as Effective Java by Joshua Bloch, they are the ones that discuss principles as well as practice. When you have the correct mental model for a tool or programming language, it is possible to exploit that knowledge to solve new problems. By comparison, if you limit yourself to solutions that are pasted on message boards, then by definition, you will never be solving problems that have not been solved before (how boring!). Rest assured that at 550 pages, Closure: The Definitive Guide contains plenty of code samples and other practical information, but it also does its best to explain the problems that Closure is designed to solve and why the tools work the way they do.

The book also touches upon other areas related to web development. As mentioned earlier, I care a lot about software engineering, so I include a surprisingly large discussion of Ant, as I believe it is incredibly important to have scripts for automating common tasks (it is not important that they be written in Ant, just that they exist). I even went so far as to create plovr (which is introduced in Appendix C) because I did not feel that the edit-reload-test cycle that one gets out of the box with Closure was fast enough. The book also contains other such “digressions,” such as the section on goog.partial() that goes into considerable detail about function currying and the scope of a closure. In other parts of the book, you will find short asides on security vulnerabilities such as XSS and XSRF (which gave me an excuse to include Exploits of a Mom on page 76!).

In sum, Closure: The Definitive Guide aims to be much more than a manual. (The last thing I wanted to do was produce a tome that was a rehash of documentation that was already freely available online.) Instead, it tries to explain the tools and principles that you need to build a rich web application in JavaScript while demonstrating how Closure employs those principles to be the best tool for the job. If you find that your latest web project is starting to collapse under its own weight, then perhaps it’s time you decided to learn what Closure is all about.

Wednesday, September 22, 2010

Is Your Book Published Yet?

Over the past few months, I have often been asked: “When is your book going to be published?” In today’s world, that is a surprisingly difficult question to answer.

For example, shortly after the book went to print, the electronic version of the final draft became available for purchase on O’Reilly’s web site (while simultaneously appearing on O’Reilly’s Rough Cuts page, implying that it is not yet complete). According to Amazon, the publication date is September 27, though it is unclear whether that is when Amazon pre-orders will be shipped or when they will be received (or neither!). As if my eagerness had not already gotten the best of my patience, my editors at O’Reilly explained to me that the book will not appear in brick-and-mortar bookstores until two to three weeks after Amazon has it!

So for myself, I decided to consider my book “published” as soon as I had a physical copy in my own hot little hands, which finally graced my doorstep today:




If you need me, I’ll be at home spilling champagne on my new book!

Update: I stopped by the Union Square Barnes and Noble in NYC and they said that they should have Closure: The Definitive Guide in stock on Tuesday. Also, sometime in the last couple of days, Amazon changed from taking pre-orders to declaring the book "In Stock," so perhaps 9/27 is a real date for both online and brick-and-mortar sales!

Tuesday, September 7, 2010

Using Soy instead of PHP or JSP

Traditionally, I have used PHP to create the basic template for bolinfest.com, but I never felt good about it. The mixture of presentation and content made my PHP files hard to organize, and having my URLs end in .php was embarrassing (and would be a pain to set up redirects for if I ever wanted to change them).

Nevertheless, PHP was dead simple to setup with Apache on Linux, and it was a convenient way to include a standard header and footer, along with a little logic to highlight the navigation tab for the page that was currently being displayed. At the same time, I found it annoying to duplicate the setup on Windows, which meant that I often ended up editing the files directly on the server rather than developing locally, checking into version control, and checking out on the server. It just encouraged bad habits all around.

Fortunately, I eliminated this problem over the weekend by creating a dead simple web server that works with Closure Templates. For now, I'm calling it soyweb (Soy is another name for Closure Templates), and it is available as an experimental feature of plovr. (You can download the latest version of plovr/soyweb from its Google Code site.)

Because Closure Templates are written in Java, so is my web server, which is fairly easy to do with the HttpServer class introduced in Java 1.6. Instead of having to set up a Windows service, I can run the following command to serve a directory of Soy files as HTML:
java -jar plovr.jar soyweb --dir DIRECTORY_OF_SOY_FILES
Each Soy file that is served by soyweb must have a template named .base that does not take any parameters. Currently, plovr.com is being served using soyweb, so you can see the Soy templates that power the web site in the repository.

A file such as docs.soy is served via both http://plovr.com/docs and http://plovr.com/docs.html. Personally, I have been linking to the version with the .html extension, but I can see where it may be desirable to not use any extension at all, so soyweb supports both. In either case, I am no longer exposing the underlying technology used to serve the site via the file extension.

As Soy supports specifying compile time global variables, I have decided to expose this feature via a JSON config file. This appears to be more flexible than Soy's file format for globals, as the config file for soyweb will turn a JSON list into a SoyListData and a JSON map into a SoyMapData. (Currently, comments are not allowed in the config file, but as soon as the fix for bug 212 is released for gson, I will upgrade plovr to allow comments in config files.) The use of globals has already proven useful as I use one set of values when developing locally, and another set of values when developing in production.

By default, soyweb recompiles all Soy files on every request, which is extremely convenient for development. (In reading about node.js, it sounded like I would have to restart Node every time I edited a Soy file, which would be unacceptable for development. Nevertheless, I am very excited about the future of Node, and would love to see more Node/Closure integration down the road.) Obviously, dynamic recompilation is not a good feature for soyweb in production, so there is a --static flag that can be used to disable it. The other flag of interest is --port, which can be used to specify which port soyweb runs on (defaults to 9811), so I use the following command to run soyweb in production to serve plovr.com:
java -jar plovr.jar soyweb --dir www --static --globals prod-globals.js
Because I am running Apache, I had to set up the following proxy from port 80:
  ProxyRequests Off

<Proxy *>
Order deny,allow
Allow from all
</Proxy>

ProxyPass / http://plovr.com:9811/
ProxyPassReverse / http://plovr.com:9811/
Be aware that I produced that by a series of guess-and-check operations while reading the Apache documentation on mod_proxy, so it is quite possible I am not using best practices in that respect.

Tuesday, August 31, 2010

Trying out the Amazon Associates Program

As my book will be available for sale on Amazon soon (currently, you can only pre-order it), I have decided to try out their affiliates program. The idea is that I place an ad to a product on Amazon on my site, and I get some fraction of the sale, if one occurs. Although the concept is straightforward, setting up the ad is not.

Setting up the ad is awkward, as the HTML snippet I am instructed to embed is:
<a href="http://www.amazon.com/gp/product/1449381871?
ie=UTF8&tag=bolinfestcom-20&linkCode=as2&camp=1789&
creative=9325&creativeASIN=1449381871">
<img border="0" src="517mVDCbOtL._SL160_.jpg">
</a><img src="http://www.assoc-amazon.com/e/ir?
t=bolinfestcom-20&l=as2&o=1&a=1449381871"
width="1" height="1" border="0" alt=""
style="border:none !important; margin:0px !important;" />
As I have highlighted in red, the source of the first image is a relative URL. That means you have to host the image yourself in order for this to work. Amazon has instructions that tell you as much:

IMPORTANT: Save this image to your server, then cut and paste the HTML code in the lower left textbox into your web page.

But...why? I can think of three possible reasons:
  1. Amazon requires the image to be on a foreign server because they have some bizarre tracking JavaScript that requires it.
  2. Amazon is too cheap to host the image themselves.
  3. Amazon is being dumb.
Neither of the first two reasons make a lot of sense to me, so I'll have to assume it's the third. Having created embeddable advertising units for web pages and helped users set them up, I can say with certainty that this additional step will make embedding the ad substantially more difficult for the average web site owner.

(Another nit: one of the image tags is self-closing while the other is not. Is Amazon trying to embed HTML or XHTML? I don't really care which, I'd just like them to be consistent!)

The image that Amazon provided me with was small and grainy, so I decided to use a different book cover image that I cropped from O'Reilly's web site (that is why it still has the Rough Cuts branding on it). At 56K, I really need to use Pngcrush, but I'll save that task for another day. By changing the source of the image tag from 517mVDCbOtL._SL160_.jpg to http://plovr.com/cover.png and embedding the HTML, everything seems to work just fine.

Except...then I wanted to enable the fancy Product Previews feature that enables a user to mouse over the book cover to get a hovercard with more product details. I followed the instructions and added the script tag to enable Product Previews on my page:
  • On Firefox, the script works as intended.
  • On IE 8, the hovercard appears briefly, triggering the progress bar. Once the progress bar finishes loading, the hovercard disappears again.
  • On Webkit-based browsers (i.e., both Chrome and Safari), the hovercard appears, but it is empty. When I inspect it, the hovercard appears to contain an iframe with all of the appropriate content, except the CSS of the iframe is visibility:hidden, which is why nothing is displayed.
Also, the snippet of JavaScript that you are instructed to use is:
<script type="text/javascript" src="http://www.assoc-amazon.com/
s/link-enhancer?tag=bolinfestcom-20&o=1">
A blocking script tag? Gross! As Steve Souders explains on his blog, Google Analytics has gone async and so should you! I wrote some JavaScript that would load Amazon's JavaScript asynchronously, but that did not work because Amazon's script contains a call to document.write(), so it must be executed while the page is still being written.

For a company like Amazon, this is pretty pathetic. Again, they need to:
  1. Host the images for their products so the HTML snippet is easier to embed.
  2. Clean up the HTML snippet so it is consistent with its use of closing tags.
  3. Get a higher quality image for the cover of my book!
  4. Fix the JavaScript for the Product Previews feature so that it works on all modern browsers, including IE6 and later.
  5. Rewrite the Product Previews JavaScript so that it can be run after the page loads (i.e., so it does not depend on document.write()).
  6. Change the Product Previews snippet that users have to embed so that it loads the Product Previews JavaScript asynchronously.
This is fairly basic stuff that could easily help Amazon drive more traffic to their site. What are they waiting for?

Monday, August 9, 2010

plovr: Lowering the Barrier to Entry for Closure

In drafting Closure: The Definitive Guide, it became pretty obvious that it was not easy to get up and running with Closure. Currently, using the full suite of Closure Tools requires checking out three projects from code.google.com via Subversion, and a combination of Python and Java to compile JavaScript code.

Over the past month, I have been working on a build tool that integrates the Closure Compiler, Closure Library, and Closure Templates into a single download. It is named plovr, and can be downloaded as a single jar file that can be run with the JRE.

In creating plovr, I tried to address problems that frequently appeared in the discussion groups, such as:To this end, plovr can be run both as a server during development that dynamically recompiles Soy and JavaScript files when you reload a web application that depends on them. It can also be used as a command line build tool to generate compiled JavaScript. Because there are so many configurable options when using Closure, options are specified in a JSON config file rather than on the command line.

Like many open-source projects, the documentation is still under development, though hopefully it is enough to get you started. I am also reluctant to commit to official documentation before getting feedback from more developers, so please download it and try it out! I have found plovr to be particularly effective in facilitating my Closure development, but I would like to hear whether it is meeting your needs before I promote it from alpha to beta software.

And if you are planning on entering the contest to see what you can build with 1K of JavaScript, I strongly urge you to use plovr to help you stay under the 1K limit. I am planning to release a new feature of plovr in the next week or two that will expose more features of the Compiler that will help you minify your code for the contest. Stay tuned!

Wednesday, July 14, 2010

Manuscript Submitted!

On Monday, I submitted my manuscript for Closure: The Definitive Guide to O'Reilly for copyedit review. The past two months of revisions were extremely stressful, so I can't even begin to describe what a huge relief hitting that milestone has been for me. Honestly, I thought the draft was in reasonable shape when I finished it back in May, so I ended up doing a lot more work than I expected to get it into a state suitable for submitting for copyedit.

Nevertheless, I am really excited with how much better the book has gotten in the past two months (it's probably one Amazon star better than it was before), though what is even more exciting is that I am already able to share the latest version with you via O'Reilly's Rough Cuts program. What I submitted for copyedit on Monday was just made available on Rough Cuts today! (Apparently you can see the Table of Contents and read the Foreword and Preface without paying for the book.)

Since the last update to Rough Cuts (mind you, that is when I thought I had a complete first draft), I have added an additional 91 pages for a whopping total of 546 pages. The following are some of the new sections that were added:

  • Detailed example of dividing compiled code into modules and loading them with the Closure Library (appears in Chapter 12).
  • Rewrite of the complex component example at the end of end of Chapter 8.
  • More hidden options in Chapter 14, which has been renamed to "Inside the Compiler."
  • An explanation of goog.events.KeyHandler in Chapter 6.
  • A section on goog.Uri in Chapter 7.
  • A section on mock objects in Chapter 15.
  • A new appendix on plovr (appears as Appendix C).
  • Acknowledgments in the Preface.
As part of the revising process, I (with the help of contributing author, Julie Parent) responded to all 100+ comments made on the Rough Cuts web site, which were a big help in improving the quality of the draft. Thank you so much to everyone who contributed so far! (Special thanks to Derek Slager, who filed the overwhelming majority of the corrections.) As the manuscript has not been finalized yet, you can still submit feedback now to help improve the final version of the book, so don't be shy!

For the next month or so, the manuscript will bounce back and forth between O'Reilly and me. According to Amazon, my book will be out on September 15, 2010, though I think that may be a little optimistic. Fortunately, the beauty of Rough Cuts is that you don't have to wait until the fall to get the help you need with Closure today!

Saturday, May 15, 2010

All Chapters Drafted!

This past week, I published a new update to my book-in-progress, Closure: The Definitive Guide. This update includes new chapters on the Closure Inspector and Closure Templates, which means that now every chapter has been drafted, so if you have been holding off on subscribing to the book because you thought the Rough Cut was "too rough," now you no longer have an excuse!

Though there are admittedly some sections that are still marked TODO, such as the section on "mocks" in Chapter 15 on the Testing Framework. There are also some sections that are mentioned in the text but lack a reference because they have not been drafted yet, such as the one on creating multiple modules with the Compiler and understanding line joining in Closure Templates. (Though the latter is explained in the online documentation.) Although I have my own punch list of things to add, please feel free to add comments on the Safari books page, as the feedback I have gotten there so far has already proved useful!

Also, if you have been following along with my page count graph, you will notice that things have flattened out lately:



There is also a striking difference of the slope of the lines in the blue and white sections, though what you may find even more curious is the discontinuity in the blue section. That's because I decided to try working in finance, and after seven weeks, I decided that it wasn't for me. It was actually a great company with incredibly sharp people, but I just couldn't get excited about the problems there as I could for the ones in building Web applications.

I got a new job at Yext, which is a much better fit for me. I realize the home page of Yext does not look like much, but I think that this TechCrunch article tells the story better than I can.

Fortunately, Yext has been very supportive of my book, so I was able to take a bit of time before starting to focus on writing, and as you can see from the graph, it has really paid off! Clearly, working at a startup has slowed my rate of progress, but it has given me more experience training engineers (who have never worked at Google) how to use Closure, so I think The Definitive Guide will be a better book in the long run because of it.

Although now that I'm about to enter the revising stage, I think a real sign of progress will be when the line on the graph starts to go down, because as Blaise Pascal (apparently not Mark Twain) said: "I have only made this [letter] longer, because I have not had the time to make it shorter."

Sunday, March 21, 2010

I'm a Golden Plover!


Today's update to the Rough Cut is particularly momentous as it features the cover of my book for the first time: the mysterious cover-choosing-cabal over at O'Reilly has chosen a golden plover as my animal, and I could not be more excited! (Contrary to popular belief, no, you do not get to pick your own animal.)

Although the Rhino has long been an icon of JavaScript books from O'Reilly, some of the more recent releases appear to be birds, so I'm thrilled to be part of that group.

The latest installment to the Rough Cut are the chapters on Client-Server Communication (20pp) and User Interface Components (50pp), which are core modules to the Closure Library, so I'm sure that this new information will be of great use to Closure neophytes (and likely some veterans, as well.)

Over the weekend, I finished drafting the chapter on Working with the Compiler Source Code. I am quite happy with the code samples that I came up with, and I hope they encourage JavaScript developers to start thinking about more innovative uses of the Compiler. Also, guest author Julie Parent has been hard at work on a chapter on goog.editor, the rich text editor widget in the Closure Library that seems to be a popular topic in the discussion group. Hopefully both of those chapters will also hit the Rough Cut in the next few weeks.

This means that 12 of the 16 chapters have been drafted, and the topics for the remaining four chapters are not as complex as those of the existing chapters, so the end is in sight! My current estimate for the final page count for the book is between 450-500 pages, which is nearly twice as long as I originally anticipated. I'm doing my best to put the Definitive in Closure: The Definitive Guide!

Friday, March 5, 2010

toString() Might Not Return a String

I was reading NCZ's JavaScript quiz, and it occurred to me that toString() is not guaranteed to return a string because it is, after all, just a method. Try to guess what is printed to the console when the following JavaScript is executed:
var obj = {
nine: 9,
toString: function() {
return this.nine;
},
valueOf: function() {
return 10;
}
};

console.log(obj.toString() === '9');
console.log('' + obj === '9');
console.log('' + obj.toString() === '9');
console.log(obj + obj);
console.log(String(obj) === '9');
Because obj.toString() returns a number, not a string, obj.toString() is the number 9, not the string '9', so the first expression is false.

In the second example, I would expect that because '' is a string, the value on the right of the + would also be coerced to a string via its toString() method, which means the result would be '9'. But I am wrong! It turns out that valueOf takes precedence, so '' + obj evaluates to '10', which means '' + obj === '9' is false. It would be true if there were no valueOf method defined on obj, though.

Because toString() is called explicitly in the third example, '' + obj.toString() becomes '' + 9, which evaluates to '9', so the expression is true.

The fourth one is interesting because '99', 18, and 20 are all reasonable guesses, but it turns out that valueOf() takes precedence again, so this evaluates to 20. If there were no valueOf() method defined on obj, then the result would be 18.

In the final example, String() is used as a function (and not as a constructor function, which you should never do!), and it does, in fact, return a string, so String(obj) === '9' evaluates to true. I always assumed that the implementation of String was something like:
function(s) {
return '' + s.toString();
};
Though a few years back, I discovered that alert.toString() throws an exception on IE6 (also alert.toString evaluates to undefined on IE6), but '' + alert and String(alert) return 'function alert() { [native code] }', as expected. At least in that case, my proposed implementation for String() would not work, though IE6 has been known to be nonstandard and buggy...

Monday, March 1, 2010

Update to Closure: The Definitive Guide

Today I'm excited to announce a significant update to Closure: The Definitive Guide. The book contains complete drafts of two new chapters that focus on the Closure Compiler: Using the Compiler and Advanced Compilation. These two chapters contribute 80 pages of new content in addition to the 167 pages that are already available.

Because I was curious, I also created a graph of my progress on the book that is automatically updated every six hours:



When I put together the original proposal for the book, I projected that it would only be 250 pages long. Clearly, that was an underestimate. This presents quite the opportunity for you, the reader, since I'd argue that the book is now underpriced as you can preorder the print version for only $25.99. For only $14 more, you can also get online and PDF access to the book today. If you do, I strongly encourage you to provide feedback on O'Reilly's web site. Remember, the book is still in draft form, so if you have suggestions on how the book could be improved, make them now so they can be included in the final version!

Sunday, February 21, 2010

New Firefox Extension: Fullscreen Tasks in Gmail

I know that when you have a lot of things to do, using Tasks in the cramped space within Gmail or Calendar may seem frustrating. There is actually a great workaround, which is to use the fullscreen version of the Tasks iGoogle gadget available at https://mail.google.com/tasks/canvas. Unfortunately, few people seem to know about it even though it was posted on the Gmail blog back in October.

My new extension simply adds a link in the sidebar that makes it possible to bring up the fullscreen version of Tasks in an iframe without leaving Gmail:



You can download the extension from http://bolinfest.com/chickenscratch/fullscreen-tasks-in-gmail.xpi. For some reason, you need to install it by first downloading it and then using the File -> Open File... menu in Firefox to open it up and install it. The traditional method of installing, which is just going to the URL in Firefox, does not seem to work for some reason: I get some nonsense about it not being a valid install package.

Because I thought this was going to be a short script, I originally tried to write it in Greasemonkey because I feel like it is easier to get users to install Greasemonkey scripts than separate extensions these days. Initially I tried using the Gmail Greasemonkey API, but unfortunately it is super-busted: many of the methods in the API do not work right now.

Then I considered looking under the hood of Gmail and trying to use XPaths, but those were nightmarish and would be likely to break, so I decided that I really needed some of the primitives in Chickenfoot to grab the appropriate DOM elements. For example, to display Tasks, I need to hide the threadlist and insert my iframe. In Chickenfoot, I came up with a fairly good heuristic:
  var n1 = find('first select all').element;
var n2 = find('second select all').element;
if (!n1 || !n2) {
return false;
}
ancestor = goog.dom.findCommonAncestor(n1, n2);
dom = goog.dom.getDomHelper(ancestor);

This essentially finds the DOM element for each of the "Select: All" controls that appear above and below the threadlist, and uses their common ancestor as the node to hide to make room for my Tasks iframe.

If you are interested, the code for the Chickenfoot script is also available. In creating the extension, I ended up fixing some bugs in Chickenfoot, but also added some new features, so when Chickenfoot 1.0.8 is released, it will be possible to run my script as-is. One new feature is that Closure Lite will be available as a library in Chickenfoot, so with the include('closure-lite.js') call in Chickenfoot, lots of goog goodness will be readily available, which made the development of this script go so much faster.

For a script that should be so easy to write, it may be surprising that it is over 100 lines long. Much of this is because I tried to include a number of features that should make the extension easier to use:
  • Keyboard shortcut that works when either the threadlist or the Tasks iframe have focus.
  • Tooltip to make the keyboard shortcut more discoverable.
  • Logic to ensure that the style of the "Full Tasks" link matches that of your Gmail theme.
  • Focus is given back to the threadlist when exiting fullscreen Tasks.
  • The Tasks iframe is resized when the browser window is resized.
  • Timing logic to account for the fact that many things in Gmail are loaded asynchronously.
I bring this up not just to toot my own horn, but to comment on something that I recently read about in Coders at Work that Kushal recently touched upon on his blog as well, which is the idea of the "empathy gene". (Some bloggers misattribute the phrase to Josh Bloch because he brings it up in his interview in Coders at Work, but Bloch actually attributes the phrase to Kevin Bourrillion during the interview.)

I think it's particularly relevant in this example because most userscripts that I have looked at are pretty hacky pieces of code. This is partially because most userscripts are viewed as hacks in the first place, though there is nothing about writing userscripts that forces them to be that way. For example, with my new extension, there are a million ways I could have chosen to jam a Tasks iframe into Gmail, most of which would have taken many fewer lines of code. But to make something reliable, thoughtful, and usable took a lot more code than that. I like to think that this is my empathy gene at work.

An even better example of non-hacky Greasemonkey scripts are those written by Mihai. Mihai clearly has the empathy gene, which is one of the reasons why Google Reader is such a great product. (Though even an empathetic guy like Mihai has been known to ruin Christmas every once in awhile -- oops!)

Finally, although I enjoyed creating this extension and am glad that I also made improvements to Chickenfoot in the process, I would be even happier if this feature (or something like it) were made available in Gmail (I'm looking at you, Mountain View!). Though if Tasks were able to "graduate" into the navigation bar in the top of the page that is available across all apps, that would solve most of my problems. It may be time to update iGoogleBar to do exactly that!

Tuesday, January 26, 2010

I'm a Semi-Published Author! (Closure: The Definitive Guide)

Today, I am officially a semi-published author in that the half of the book I am working on is available (for pay) online as part of O'Reilly's Rough Cuts program! The title is Closure: The Definitive Guide, and as you may have guessed, the aim is to create an (invaluable!) manual for the Closure Tools suite. When I am finished, the book will cover the Library, Templates, the Compiler, the Testing Framework, and the Inspector, though the six chapters that are available today are only on the Library. However, if you purchase the book through Rough Cuts, you will get the updates to the book as I publish them there, so it is more like buying a subscription than a book.

I am extremely excited about the Rough Cuts program because it allows me to get information out to you, the web developer, much faster than I could if I forced you to wait for the print version. It also gives you the opportunity to provide me with feedback to help ensure that the Guide contains the information that you need.

For those of you who have purchased a book via Rough Cuts before, you may be surprised to see how "rough" my book is compared to the other offerings. This is a fairly new program at O'Reilly, so the first books to go through Rough Cuts were not made available until a nearly complete draft of the book was done. By comparison, my book is half done and has gone through neither copy edit nor technical review. So when providing feedback, please bear in mind the staff at O'Reilly will ultimately help with things like the misuse of parallel structure, but I need your help in determining when something merits a code sample or more explanation.

The material that is currently available is:
  • Preface
  • Chapter 1: Introduction to Closure
  • Chapter 2: Annotations for Closure JavaScript
  • Chapter 3: Closure Primitives
  • Chapter 4: Common Utilities
  • Chapter 5: Classes and Inheritance
  • Chapter 6: Event Management
  • Appendix A: Inheritance Patterns in JavaScript
  • Appendix B: Frequently Misunderstood JavaScript Concepts
Although there is nothing that requires me to write the chapters in order, I was encouraged to start out that way in order to have something that would be well-connected for Rough Cuts readers. This meant that I had to draft the introduction earlier than I would have liked, but I am actually quite happy with what is there right now. Among other things, it contains a complete "Hello World" example that shows how to use all of the tools together, which is something I have yet to see on any blogs or even as part of Google's own documentation.

Currently, I am taking a break from writing more on the Library and am skipping a few chapters ahead to start focusing on the Compiler. As an active member of the Closure Google Groups, it is pretty clear to me that developers need more help in that area, so I hope to make that information available soon.

I also hope to improve Closure in the process of writing this book. When I run into things that I feel are hard to explain, sometimes I end up filing bugs or feature requests against Closure with proposed changes. It is so much easier to write a few paragraphs to report a bug than it is to draft several pages to explain away a quirk!

With 150 pages of content, I suspect I have given you enough to chew on while I put together more information on the Compiler. Please take a look and let me know what you think.

Update: Changed the book link from http://techbus.safaribooksonline.com/9781449381882 to http://my.safaribooksonline.com/9781449381882 where it is actually possible to purchase the book! There is a button that says "Purchase Options" on the upper-right.

Saturday, January 2, 2010

google.com uses AJAX to update search results in place?

My Gmail account appears to be in an experiment where searches from google.com update in place. That is, a search for bolinfest takes me to:

http://www.google.com/#hl=en&source=hp&q=bolinfest&aq=f&aqi=g10&oq=&fp=cbc2f75bf9d43a8f

Rather than the classic:

http://www.google.com/search?hl=en&source=hp&q=bolinfest&aq=f&oq=&aqi=g-p1g2

Apparently this was first reported in January 2009. There was immediately an outcry because the fragment (with includes the keywords used in the Google search) was not included in the referrer, so sites who analyze their traffic using that information were at a loss.

In my version of the experiment, this is no longer an issue because the search results use a URL redirector (which I do not believe is a new practice). Although the first search result is for www.bolinfest.com/, and when I hover over the link in Firefox, the status bar says http://www.bolinfest.com/, the actual destination of the link is:

http://www.google.com/url?sa=t&source=web&ct=res&cd=1&ved=0CAoQFjAA&url=http%3A%2F%2Fwww.bolinfest.com%2F&rct=j&q=bolinfest&ei=kYU_S8nZAdC0lAeJ0fmVBw&usg=AFQjCNEgHH2q8kppSggtQt45aSSazDTynA&sig2=G54nS0q_UtfEChH7icC_NA

When I follow the link and run javascript:alert(document.referrer) in the address bar, I see the same thing:

http://www.google.com/url?sa=t&source=web&ct=res&cd=1&ved=0CAoQFjAA&url=http%3A%2F%2Fwww.bolinfest.com%2F&rct=j&q=bolinfest&ei=kYU_S8nZAdC0lAeJ0fmVBw&usg=AFQjCNEgHH2q8kppSggtQt45aSSazDTynA&sig2=G54nS0q_UtfEChH7icC_NA

Note that this URL contains the query in the URL parameter q=bolinfest, which should appease those who are concerned with keyword tracking.

What is interesting is that the AJAX request to load the search results appears to be an ordinary GET request to:

http://www.google.com/search?hl=en&q=bolinfest&aq=&aqi=g2&oq=bolinfest&fp=cbc2f75bf9d43a8f

The content of that URL is an HTML page with 21 <script> tags in the <head> and an empty <body> tag.

Also, copying and pasting http://www.google.com/#hl=en&source=hp&q=bolinfest&aq=f&aqi=g10&oq=&fp=cbc2f75bf9d43a8f into the address bar of a new tab works as expected (though I do get a JavaScript error when I paste the URL into a new tab that I do not get when doing the initial search from google.com).

It's hard to say what this really means, if anything. Presumably, Google's objective is to make search results load faster without pissing off advertisers. As I'm not in the SEO racket, I'm not terribly interested in the latter, but I am curious whether Google is on to a new technique for loading web content faster!