Best. Autocomplete. Ever.

During a recent role-playing portion of our interview training session at Square, I was trying to come up with a caricature of an interviewing engineer attempting to impress my counterpart across the table. I ended up embellishing upon my starter project at Google; in retrospect, it was easily one of the most over-engineered pieces of work I’ve ever had the displeasure to involve myself in. Nonetheless, it makes for a fun story, so here is a short account.

To give some context, upon starting, I was placed on one of the internal tools teams within Google. Given Google’s size and its top-notch engineering teams, it’s not a surprise that there’s an abundance of internal sites and tools[1] that runs the company, everything from Eclipse extensions to the interview questions tracking app to Google’s own file and operating systems. This practice of building out custom tools extended to non-engineering teams as well; I guess the thought is that Google development is at least as good as the vast majority of software vendors, and we get to cater our software directly to our internal clients.

My team was responsible for, essentially, a database webapp with a search and settings front-end. One of the top requests was a better search UI – the search backend itself was fast enough, but sifting through tables of results was tedious and error-prone. Thus, I was tasked with building an autocomplete widget on top of the search box, and by doing so learn the ins and outs of the mostly-Closure, starting-to-be-ported-to-GWT codebase.

Had I been anywhere else, I would have thrown the jQuery autocomplete widget on top of the input box and called it a day.

But, the requirements called for something much more…elaborate. From what I can remember:

  • There was 7-8 separate entity types that we could search on. The backend did this in parallel; the UI simply had to understand the types that the return specified. Each type was modeled as a class.
  • The UI couldn’t display all the results from all the types at once. We’d have a max of 4 results per type, with a max of 4 types. Each constraint was configurable.
  • Most results took up multiple rows, but only had enough metadata to fill one row. In theory I had separate classes to customize each type’s rendering, except that sometimes, the full set of 16 results would make the results window too tall, so the widget had to figure out the optimal combination of expanded/condensed rendered result rows.
  • Rows are by default fully clickable, but there are fields which needed to allow for highlights; users would want to copy & paste emails and phone numbers, and those should not count towards selecting the item.
  • The API format was protocol buffers. Protobufs aren’t too great in JavaScript, although to Google’s credit, they do integrate well with Google Closure, as long as you don’t mind piling on a couple dozen more JS objects per response handler.

So with all that, the autocomplete to rule all autocompletes took me about three months to build and deploy to production. To be fair, much of that time was spent learning the Google stack and coding standards, and the backend fellow I was working with also had to spend two and a half months wrangling the data from the myriad of storage systems to make the entire thing searchable[2]. The truly sad part is that there was no instrumentation in the code to determine actual usage, and we didn’t even bother to get our users’ feedback post-launch.

I suppose the moral of the story is that I have contributed to the enterprise-class ruination of JavaScript and web applications. Fully knowing the issues with the processes and implementation, I willfully continued as the environment I was operating within made these choices the path of least resistance. I can’t say I’m proud of what I built, but hey, it makes for a decent (fake) interview story.

Footnotes    (↑ returns to text)
  1. Following the premise that investing in developer tools increases overall productivity and developer happiness.
  2. Although I remember that each entity type only had a few hundred thousand entries, nothing that a simple MySQL LIKE couldn’t fly through.