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