Monday, December 13, 2010

Hiring Front-End Engineers

When I started at YouTube nearly three and a half years ago, there was only one full-time web developer (and one other web developer who, shortly before I started, transitioned into product management). Needless to say, there were plenty of things to work on the moment I walked through the door. In fact, the first order of business was to set to work recruiting our third full-time web developer.

By the time I left YouTube in August, 2010, I had been introduced to hundreds of potential candidates. I reviewed resumes, held phone screens, gave onsite interviews, worked with potential acquisitions, recruited at conferences, and generally socialized with a wide assortment of technology geeks. Despite all of this work and our desperate need for front-end engineers, I would estimate that only 3-5% of the candidates I interacted with ever made it to an offer letter.

It would be easy to blame this situation on an overly selective hiring process, but I do not believe this to be the case. Rather, the problem it seemed was a systemic misunderstanding as to what characteristics make for a top-level web developer and where to look for those types of candidates. The types of candidates that we would be asked to evaluate were most often excellent engineers, but simply the wrong people for the job.

Here are my observations on what to look for in potential candidates. These are generalizations based on experiences I have had. Of course there will be plenty of exceptions out there.

1.) Good front-end engineers rarely have a computer science degree. It certainly does not hurt to have one, but it just does not happen that often. Some of the best web developers I interviewed, and helped hire, barely had a degree that resembled anything close to computer science. Most of them were self-taught, building websites for family members and friends, long before they ever entered college. It was a hobby they did in their spare time and then realized somewhere early on that they could build a career out of it. A lot of them came from other disciplines, such as computer graphics, electrical engineering, mechanical engineering, information systems, graphic design, printing, and even packaging science.

2.) Good front-end engineers cannot be forged from back-end engineers. A prevailing sentiment for quite some time was "why hire a specialist front-end engineer when we can hire a generalist back-end engineer and train them in front-end technologies?" Unfortunately, it proved not so simple. While back-end engineers can quite easily pick up the languages and semantics, their talents tend to work against them when it comes to the front-end. Good back-end engineers work to create solutions that are definitive, measurable, testable, predictable, reproducible and stable. The consumer web rarely affords you any of these noble aims and any lofty attempts to ignore this fact will only lead to eventual insanity. The back-end engineers that break the mold and do eventually transition into becoming good front-end engineers usually have some kind of alternate background that facilitates the jump.

3.) Good front-end engineers list Javascript on their resume, not jQuery. I do not mean to pick on jQuery, but it certainly was the most popular Javascript library referenced on resumes from my experiences. Bad front-end engineers are dependent on jQuery and other libraries. Good front-end engineers make use of libraries like jQuery to empower themselves, but are not beholden to them. About a month in, I scrapped nearly all of my interview questions for just one Javascript problem:

A div with an id of 'slideshow' contains five images, the first of which is shown and the others are hidden using a display style of none. Using Javascript, create a simple slideshow that cycles through the images, displaying each image for three seconds at a time, looping back to the first image when the end is reached. You cannot use jQuery or any other library.

I had to add that last stipulation because far too often, a candidate would gleefully exclaim that there was some jQuery plugin for that, scribble three lines of code on the whiteboard, and then sit down triumphantly. When I would explain that we only used proprietary libraries (at the time Closure, which is now open source) and that jQuery plugins were not an option, the candidate would end up spending the next 30 minutes sweating through an often regrettable solution.

The good front-end engineers would solve that problem in about 5 minutes and 15 lines of code, then sit down nervously wondering what the catch was. What made it worse was that someone actually solving that problem, given the constraints I provided, was so inexplicably rare that I never bothered to have any real follow up questions and often sat in shell-shocked silence trying to invent a next question. Once I collected myself, it would quickly follow that these candidates knew Javascript inside and out, regardless of whether they used a library or not.

4.) Good front-end engineers are artists. Nearly every first rate web developer I have worked with had some kind of extracurricular, no matter how casual, that focused around some form of art. I have worked with painters, photographers, singers, writers, actors, musicians, sculptors, printmakers, and graffiti artists. One question I started to ask candidates was "Do you play an instrument?" If they did, it was usually a good sign. (Disclosure: I do not play any instruments and was not looking to start a band) My thought on this is that artistically-minded individuals derive personal value from expressing themselves through their work. Consequently, they become much more entwined in what they create and its success. They are often emotionally tethered to the product and will surface gripes long before they echo back from your users. These types of web developers are nearly incapable of "phoning it in" or letting something subpar slip through the cracks.

5.) If you want to find good front-end engineers, look to the newspaper and print industry. People who work in print media make excellent potential web developers as long as they have at least some technical skill to expand on. Consider the general environment of the print world and what is required of its workers. Workers often work on tight schedules, with very sharp deadlines that mean last-minute cuts may have to be made in order to ship their product. They have to construct and layout items within grid systems. They have to know typography fundamentals like fonts, leading, and kerning. They often have to work within color constraints and style guides. They value things like legibility, copywriting, and visual hierarchy. If they know Quark or InDesign, they probably understand many of the concepts behind stylesheets. These components are extremely desirable in a front-end engineer and difficult to transfer to someone brought up in traditional engineering habits. The best part is that the best potential candidates from the print world are relatively easy to spot. Just ask them to send you a printed copy of their resume. It will look so good you will want to have it framed.

Friday, May 29, 2009

Lessons From Building a Basic Video Player in HTML5

HTML5 browsers that support the <video> tag are required to provide a basic set of controls for watching video on a web page. The built-in controls can be turned on by adding the "controls" attribute to the <video> tag. However, in many cases, you will want to provide your own richer set of playback controls. In this post, I intend to call out some of the hurdles that I have run across working on various HTML5 video players. If you want to see many of these techniques in action, check out the source code for http://www.youtube.com/html5.

A few quick warnings. First, I have no prior experience in building video players on platforms such as Flash or Silverlight. Some of these tips may be second nature to someone who already understands building players in these technologies. Secondly, many of these techniques are unabashedly broken in many browsers as this is exceedingly bleeding edge technology. Your best bet is to bounce between browsers such as Safari 4 Beta, Webkit nightlies, Chromium nightlies, FireFox 3.5 Beta, and Opera 9.64 until you find one that works. Finally, this post contains only a subset of topics involving HTML5 video players. Please leave a comment if there are other specific topics you would like me to discuss.

Markup


Early on, you need to decide how you want to build your video controls (e.g. play button, progress bar, etc.). Resist the temptation to use a single <canvas> element for all of it. Using actual markup has several benefits. For instance, blind and visually-impaired users make up a decent number of video consumers. Semantic markup will make your player accessible to them. If you want the flexibility of <canvas> elements, you can nest them inside of your video controls like so:

<button class="play-button"><canvas class="play-icon" height="32" width="32"></button>

Also, take advantage of new tags such as <progress>, <time>, <meter> and <button> (new-ish). These tags allow you to store additional information about the current state of your player. Whenever possible, have your Javascript update these elements and their attributes, and then base your CSS styles on these values. For example:

HTML

<meter id="my-video-rating" class="video-rating" value="4"></meter>

CSS

.video-rating {
 display: block;
 width: 100px;
 height: 20px;
}
.video-rating[value=0] { background-image: url(/img/stars-0.png); }
.video-rating[value=1] { background-image: url(/img/stars-1.png); }
.video-rating[value=2] { background-image: url(/img/stars-2.png); }
.video-rating[value=3] { background-image: url(/img/stars-3.png); }
.video-rating[value=4] { background-image: url(/img/stars-4.png); }
.video-rating[value=5] { background-image: url(/img/stars-5.png); }

Javascript

function changeRating(newRating) {
 document.getElementById("my-video-rating").value = newRating;
}


User Interface


Capturing every video event that affects your user interface will quickly become unmanageable. Furthermore, there is no single event fired periodically during the video that you can use to update your UI to reflect the current time of the video while its playing. The best solution I have found is to fire off a function that updates the video controls on a set interval of 100ms. The function uses the state of the player at the moment the function fires to drive the UI. This greatly simplifies the code but results in the UI being updated constantly even when the video is paused.

One thing that caught me off guard was the nature of volume and muting. For whatever reason, I expected setting muted to true would be reflected in the volume property (e.g. setting the volume to 0). However, the specification explicitly keeps these two values separately, which actually makes life much easier. Just remember to check both values when trying to update your player's volume controls.

Fullscreen


Fullscreen support is still a much debated topic. Currently, it looks like fullscreen support will originate with the browser and not the video element itself. This makes sense since you will want your controls, ads, and other elements external to the video to show up in fullscreen mode. However, there is no way presently to toggle fullscreen mode from inside the page (as this is a security concern). The best you can do from inside the page is scale up your video player to fill the browser window. I have a prototype I am working on that does this by adding a CSS class to my player. The code looks something like this:

.video-player video {
 display: block;
 width: 640px;
 height: 360px;
}
.video-player.fullscreen video {
 display: block;
 width: 100%;
 height: 100%;
 position: absolute;
 z-index: 9999;
 top: 0;
 left: 0;
}

I am still working on getting the controls to layout properly in full-window mode, and will update this post with any insights I uncover.

Some talk has occurred over changing the CSS media type of the document when the browser's built-in fullscreen mode is toggled. For instance, have the media type change from "screen" to "projection". This could be used to change stylesheets or select different sets of CSS rules inside of a stylesheet. For example:

<link rel="stylesheet" type="text/css" media="screen" href="videoplayer.css">
<link rel="stylesheet" type="text/css" media="projection, tv" href="videoplayer-full.css">

Or you could do this in the CSS code:

@media screen {
 /* Do your normal video player styles here */
}
@media projection, tv {
 /* Do your fullscreen styles here */
}

Finally, one hurdle that remains is supporting the ability to show an embedded video in fullscreen on a third-party site. The security puzzle that this introduces is still undergoing heavy debate. Currently, there is no way to accomplish this that I know of.

Embedding


Embedding your videos in third-party pages is another area that is still very much in flux. At the core, you will be embedding an HTML document instead of a Flash or Silverlight binary. To accomplish this, you will need to use an <iframe> tag like so:

<iframe src="http://some.video.site.com/get_player?video=1234" height="360" width="640"></iframe>

There are other tags that would seem more semantically correct such as the <embed> and the <object> tag. According to the specification, the <embed> is meant to be an entrypoint for external plugins and not typically intended for HTML content. Setting the source of an <embed> element to an HTML document does work in some browsers. In my mind, this is the most semantically correct tag for embedding since video players do not need the "nested browsing context" of an <iframe> (e.g. ability to navigate forwards and backwards inside the frame). However, since there are no affordances for <embed> tags supporting HTML in the spec currently, it is best to stick with an <iframe>.

The <object> tag does accept HTML content as a source and will establish a nested browsing context if HTML is passed to it. Fundamentally, the behavior of the <object> tag is to act like an <iframe> if HTML content is passed to it or to act like an <embed> if any other content is passed to it. It seems unreasonable to use this tag and its additional logic when an <iframe> is a more direct path to the desired behavior.

Conclusion


The HTML5 <video> element is quickly finding its way into all of the modern browsers. It is important to invest our time in finding good, semantic HTML solutions for the problems that other technologies are primed to solve, such as fullscreen support and embedding. We also need to make sure that we establish good patterns for combining existing technologies (e.g. Flash, Silverlight) with the new capabilities of HTML5. I do not think the aim should be to try and outright replace these technologies. Rather, as developers, we should be taking this opportunity to focus on the benefits of each technology and to make it easy for these technologies to coexist.

Monday, December 8, 2008

Adding Textile to Google App Engine

By default, App Engine includes a copy of Django that it pulls in components from. However, the integration points between App Engine and Django are fairly custom and not well documented. Trying to follow vanilla Django examples for installing Textile will not work in the context of App Engine. To get Textile to work will involve a number of steps.

To begin with, you will want to create a lib folder in your App Engine project's home directory.

~/Projects/Example$ mkdir lib

You will then want to download Textile and extract into your newly created lib folder.

~/Projects/Example$ cd lib
~/Projects/Example/lib$ curl -O http://pypi.python.org/packages/source/t/textile/textile-2.1.2.tar.gz
~/Projects/Example/lib$ tar xzf textile-2.1.2.tar.gz

The Django template library django.contrib.markup will attempt to import from the namespace textile. You need to let Python know to look inside directories in the lib directory for namespaces. To do this, you will need to modify your sys.path to include those directories. The way to do this is to add the following code to the top of the file or files that contain your main functions, such as main.py in some of the App Engine demos.

import os
import sys
import logging

DIR_PATH = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
LIB_PATH = os.path.join(DIR_PATH, "lib")
EXTRA_PATHS = []
for path in os.listdir(LIB_PATH):
fullpath = os.path.join(LIB_PATH, path)
if os.path.isdir(fullpath) and not path.startswith("."):
EXTRA_PATHS.append(fullpath)
sys.path = sys.path + EXTRA_PATHS

This will modify the sys.path and let Python know to look inside of your lib directory for namespaces to import.

Now that Textile is installed, you need to register the necessary Django template library with App Engine. To do this, you need to make the following call in your code before rendering a template. I put this call in my base controller, as the first line of my get and post functions.

def get(self):
template.register_template_library('django.contrib.markup.templatetags.markup')
# Do your template processing here.

At this point, you should be able to use the textile template tag in App Engine templates like so.

<span>{{someVar|textile}}</span>

Saturday, April 5, 2008

One Tag Solution: Simple CSS Ratings

The 4- or 5-star rating has become the default for conveying popularity or relevance across the web. There are many ways to render a rating using stars in HTML and CSS. However, I have not seen a solution that is simultaneously simple, optimized, semantic, and accessible. Therefore, I set to work to uncover my own. The result looks like this: (The image 'none.gif' is a 1x1 transparent gif file)

<img class="rating" alt="3.5" src="/none.gif" />



The initial goal was to start by rendering a rating using only a single HTML tag that both visually displays the rating and retains its numerical value. The tag to use was very obviously the <img> tag. It is meant to display visual information and the 'alt' attribute is the perfect way to convey the numerical value of the rating. For slow-loading webpages, the numerical value of the rating will be displayed until the images load in.

The next objective was to make use of image spriting to contain the stars so that only one image has to be loaded and cached for all ratings. There are several different approaches to this. The image sprite I chose to make use of looks like this:



The idea is to set the width of the image to be 5-stars wide and then slide this sprite around to get the desired rating.

Building the CSS for this is rather simple. I will demonstrate the intended, but IE6-incompatible approach first. IE6 is the only modern browser that does not support the attribute selector syntax.

img.rating {
background: transparent url(stars.gif) no-repeat scroll;
width: 100px;
height: 20px;
}
img.rating[alt="0.0"] { background-position: -100px 0; }
img.rating[alt="0.5"] { background-position: -80px -20px; }
img.rating[alt="1.0"] { background-position: -80px 0; }
img.rating[alt="1.5"] { background-position: -60px -20px; }
img.rating[alt="2.0"] { background-position: -60px 0; }
img.rating[alt="2.5"] { background-position: -40px -20px; }
img.rating[alt="3.0"] { background-position: -40px 0; }
img.rating[alt="3.5"] { background-position: -20px -20px; }
img.rating[alt="4.0"] { background-position: -20px 0; }
img.rating[alt="4.5"] { background-position: 0 -20px; }
img.rating[alt="5.0"] { background-position: 0 0; }

The less than desirable CSS solution that works with IE6 is to simply add an additional class to the image indicating which rating is being displayed.

img.rating {
background: transparent url(stars.gif) no-repeat scroll;
width: 100px;
height: 20px;
}
img.rating-0\.0 { background-position: -100px 0; }
img.rating-0\.5 { background-position: -80px -20px; }
img.rating-1\.0 { background-position: -80px 0; }
img.rating-1\.5 { background-position: -60px -20px; }
img.rating-2\.0 { background-position: -60px 0; }
img.rating-2\.5 { background-position: -40px -20px; }
img.rating-3\.0 { background-position: -40px 0; }
img.rating-3\.5 { background-position: -20px -20px; }
img.rating-4\.0 { background-position: -20px 0; }
img.rating-4\.5 { background-position: 0 -20px; }
img.rating-5\.0 { background-position: 0 0; }

The modified HTML code would look like:

<img class="rating rating-3.5" alt="3.5" src="/none.gif" />

In the end, the result is a simple, semantic rating in one tag and one image. For part 2, I will demonstrate how to turn this into a rating you can pick from.