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.