<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>NCZOnline</title>
	
	<link>http://www.nczonline.net/blog</link>
	<description>The Official Web Site of Nicholas C. Zakas</description>
	<lastBuildDate>Tue, 22 May 2012 14:00:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/nczonline" /><feedburner:info uri="nczonline" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>nczonline</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Working with files in JavaScript, Part 3: Progress events and errors</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/N9gS7y4GCfw/</link>
		<comments>http://www.nczonline.net/blog/2012/05/22/working-with-files-in-javascript-part-3/#comments</comments>
		<pubDate>Tue, 22 May 2012 14:00:29 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[FileReader]]></category>
		<category><![CDATA[Files]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2928</guid>
		<description><![CDATA[The FileReader object is used to read data from files that are made accessible through the browser. In my previous post, you learned how to use a FileReader object to easily read data from a file in a variety of formats. The FileReader is very similar to XMLHttpRequest in many ways. Progress events Progress events [...]]]></description>
			<content:encoded><![CDATA[<p>The <code>FileReader</code> object is used to read data from files that are made accessible through the browser. In my <a href="http://www.nczonline.net/blog/2012/05/15/working-with-files-in-javascript-part-2/">previous post</a>, you learned how to use a <code>FileReader</code> object to easily read data from a file in a variety of formats. The <code>FileReader</code> is very similar to <code>XMLHttpRequest</code> in many ways.</p>
<h2>Progress events</h2>
<p>Progress events are becoming so common that they&#8217;re actually written up in a separate specification<sup>[1]</sup>. These events are designed to generically indicate the progress of data transfers. Such transfers occur when requesting data from the server, but also when requesting data from disk, which is what <code>FileReader</code> does. </p>
<p>There are six progress events:</p>
<ul>
<li><code>loadstart</code> &#8211; indicates that the process of loading data has begun. This event always fires first.</li>
<li><code>progress</code> &#8211; fires multiple times as data is being loaded, giving access to intermediate data.</li>
<li><code>error</code> &#8211; fires when loading has failed.</li>
<li><code>abort</code> &#8211; fires when data loading has been canceled by calling <code>abort()</code> (available on both <code>XMLHttpRequest</code> and <code>FileReader</code>).</li>
<li><code>load</code> &#8211; fires only when all data has been successfully read.</li>
<li><code>loadend</code> &#8211; fires when the object has finished transferring data. Always fires and will always fire after <code>error</code>, <code>abort</code>, or <code>load</code>.</li>
</ul>
<p>Two events, <code>error</code> and <code>load</code>, were discussed in my previous post. The other events give you more fine-grained control over data transfers.</p>
<h3>Tracking progress</h3>
<p>When you want to track progress of a file reader, use the <code>progress</code> event. The <code>event</code> object for this event contains three properties to monitor the data being transferred:</p>
<ul>
<li><code>lengthComputable</code> &#8211; a boolean indicating if the browser can determine the complete size of the data.</li>
<li><code>loaded</code> &#8211; the number of bytes that have been read already.</li>
<li><code>total</code> &#8211; the total number of bytes to be read.</li>
</ul>
<p>The intent of this data is to allow for progress bars to be generated using the information from the <code>progress</code> event. For example, you may be using an HTML5 <code>&lt;progress&gt;</code> element to monitor the progress of reading a file. You can tie the progress value to the actual data using code like this:</p>
<pre><code>var reader = new FileReader(),
     progressNode = document.getElementById("my-progress");

reader.onprogress = function(event) {
    if (event.lengthComputable) {
        progressNode.max = event.total;
        progressNode.value = event.loaded;
    }
};

reader.onloadend = function(event) {
    var contents = event.target.result,
        error    = event.target.error;

    if (error != null) {
        console.error("File could not be read! Code " + error.code);
    } else {
        progressNode.max = 1;
        progressNode.value = 1;
        console.log("Contents: " + contents);
    }
};

reader.readAsText(file);
</code></pre>
<p>This is similar to the approach that Gmail uses for its drag and drop file upload implementation, where you see a progressbar immediately after dropping a file onto the email. That progressbar indicates how much of the files has been transferred to the server.</p>
<h2>Dealing with errors</h2>
<p>Even though you&#8217;re reading a local file, it&#8217;s still possible for the read to fail. The <cite>File API specification</cite><sup>[2]</sup> defines four types of errors:</p>
<ul>
<li><code>NotFoundError</code> &#8211; the file can&#8217;t be found.</li>
<li><code>SecurityError</code> &#8211; something about the file or the read is dangerous. The browser has some leeway as to when this occurs, but generally if the file is dangerous to load into the browser or the browser has been performing too many reads, you&#8217;ll see this error.</li>
<li><code>NotReadableError</code> &#8211; the file exists but can&#8217;t be read, most likely due to a permissions problem.</li>
<li><code>EncodingError</code> &#8211; primarily when trying to read as a data URI and the length of the resulting data URI is beyond the maximum length supported by the browser.</li>
</ul>
<p>When an error occurs during a file read, the <code>FileReader</code> object&#8217;s <code>error</code> property is assigned to be an instance of one of the above mentioned errors. At least, that&#8217;s how the spec is written. In reality, browsers implement this as a <code>FileError</code> object that has a <code>code</code> property indicating the type of error that has occurred. Each error type is represented by a numeric constant value:</p>
<ul>
<li><code>FileError.NOT_FOUND_ERR</code> for file not found errors.</li>
<li><code>FileError.SECURITY_ERR</code> for security errors.</li>
<li><code>FileError.NOT_READABLE_ERR</code> for not readable errors.</li>
<li><code>FileError.ENCODING_ERR</code> for encoding errors.</li>
<li><code>FileError.ABORT_ERR</code> when <code>abort()</code> is called while there is no read in progress.</li>
</ul>
<p>You can test for the type of error either during the <code>error</code> event or during <code>loadend</code>:</p>
<pre><code>var reader = new FileReader();

reader.onloadend = function(event) {
    var contents = event.target.result,
        error    = event.target.error;

    if (error != null) {
        switch (error.code) {
            case error.ENCODING_ERR:
                console.error("Encoding error!");
                break;

            case error.NOT_FOUND_ERR:
                console.error("File not found!");
                break;

            case error.NOT_READABLE_ERR:
                console.error("File could not be read!");
                break;

            case error.SECURITY_ERR:
                console.error("Security issue with file!");
                break;

            default:
                console.error("I have no idea what's wrong!");
        }
    } else {
        progressNode.max = 1;
        progressNode.value = 1;
        console.log("Contents: " + contents);
    }
};

reader.readAsText(file);
</code></pre>
<h2>Up next</h2>
<p>The <code>FileReader</code> object is a fully-featured object with a lot of functionality and a lot of similarities to <code>XMLHttpRequest</code>. By following these last three posts, you should now be able to read data from files using JavaScript and send that data back to the server if necessary. However, the <cite>File API</cite> ecosystem is quite a bit larger than has been already discussed in this series, and in the next part you&#8217;ll learn about a powerful new features designed to work with files.</p>
<h2>References</h2>
<ol>
<li><a href="http://www.w3.org/TR/progress-events/">Progress Events</a></li>
<li><a href="http://www.w3.org/TR/FileAPI/">File API</a></li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=N9gS7y4GCfw:rfKjY88czOM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=N9gS7y4GCfw:rfKjY88czOM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=N9gS7y4GCfw:rfKjY88czOM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=N9gS7y4GCfw:rfKjY88czOM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=N9gS7y4GCfw:rfKjY88czOM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=N9gS7y4GCfw:rfKjY88czOM:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/N9gS7y4GCfw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/05/22/working-with-files-in-javascript-part-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/05/22/working-with-files-in-javascript-part-3/</feedburner:origLink></item>
		<item>
		<title>Working with files in JavaScript, Part 2: FileReader</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/Ud1dhk6BAFg/</link>
		<comments>http://www.nczonline.net/blog/2012/05/15/working-with-files-in-javascript-part-2/#comments</comments>
		<pubDate>Tue, 15 May 2012 14:30:05 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[File API]]></category>
		<category><![CDATA[FileReader]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2921</guid>
		<description><![CDATA[In my previous post, I introduced using files in JavaScript, focusing specifically on how to get access to File objects. These objects contain file metadata obtained only when the user opts to either upload a file or drags and drops a file onto the web page. Once you have files, however, the next step is [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://www.nczonline.net/blog/2012/05/08/working-with-files-in-javascript-part-1/">previous post</a>, I introduced using files in JavaScript, focusing specifically on how to get access to <code>File</code> objects. These objects contain file metadata obtained only when the user opts to either upload a file or drags and drops a file onto the web page. Once you have files, however, the next step is to read data from them.</p>
<h2>The FileReader type</h2>
<p>The <code>FileReader</code> type has a single job: to read data from a file and store it in a JavaScript variable. The API is intentionally designed to be similar to <code>XMLHttpRequest</code> since both are loading data from an external (outside of the browser) resource. The read is done asynchronously so as not to block the browser.</p>
<p>There are several formats that a <code>FileReader</code> can create to represent the file data, and the format must be requested when asking the file to be read. Reading is done through calling one of these methods:</p>
<ul>
<li><code>readAsText()</code> &#8211; returns the file contents as plain text</li>
<li><code>readAsBinaryString()</code> &#8211; returns the file contents as a string of encoded binary data (<em>deprecated &#8211; use <code>readAsArrayBuffer()</code> instead</em>) </li>
<li><code>readAsArrayBuffer()</code> &#8211; returns the file contents as an <code>ArrayBuffer</code> (good for binary data such as images)</li>
<li><code>readAsDataURL()</code> &#8211; returns the file contents as a data URL</li>
</ul>
<p>Each of these methods initiates a file read similar to the XHR object&#8217;s <code>send()</code> method initiating an HTTP request. As such, you must listen for the <code>load</code> event before starting to read. The result of the read is always represented by <code>event.target.result</code>. For example:</p>
<pre><code>var reader = new FileReader();
reader.onload = function(event) {
    var contents = event.target.result;
    console.log("File contents: " + contents);
};

reader.onerror = function(event) {
    console.error("File could not be read! Code " + event.target.error.code);
};

reader.readAsText(file);
</code></pre>
<p>This example simply reads the contents of a file and outputs it in plain text to the console. The <code>onload</code> handler is called when the file is successfully read whereas the <code>onerror</code> handler is called if the file wasn&#8217;t read for some reason. The <code>FileReader</code> instance is available inside of the event handler via <code>event.target</code> and it&#8217;s recommended to use that instead of referencing the <code>reader</code> variable directly. The <code>result</code> property contains the file contents on success and <code>error</code> contains error information about the failed operation. </p>
<h3>Reading data URIs</h3>
<p>You can use the same basic setup for reading to a data URI. Data URIs (sometimes called data URLs) are an interesting option if you want to, for example, display an image that was just read from disk. You could do so with the following code:</p>
<pre><code>var reader = new FileReader();
reader.onload = function(event) {
    var dataUri = event.target.result,
        img     = document.createElement("img");

    img.src = dataUri;
    document.body.appendChild(img);
};

reader.onerror = function(event) {
    console.error("File could not be read! Code " + event.target.error.code);
};

reader.readAsDataURL(file);
</code></pre>
<p>This code simply inserts an image that was read from disk into a page. Since the data URI contains all of the image data, it can be passed directly into the <code>src</code> attribute of an image and displayed on the page. You could, alternately, load the image and draw it onto a <code>&lt;canvas&gt;</code> as well:</p>
<pre><code>var reader = new FileReader();
reader.onload = function(event) {
    var dataUri = event.target.result,
        context = document.getElementById("mycanvas").getContext("2d"),
        img     = new Image();

    // wait until the image has been fully processed
    img.onload = function() {
        context.drawImage(img, 100, 100);
    };
    img.src = dataUri;
};

reader.onerror = function(event) {
    console.error("File could not be read! Code " + event.target.error.code);
};

reader.readAsDataURL(file);
</code></pre>
<p>This code loads the image data into a new <code>Image</code> object and then uses that to draw the image onto a canvas (specifying both the width and height as 100).</p>
<p>Data URIs are generally used for this purpose, but can be used on any type of the file. The most common use case for reading a file into a data URI is to display the file contents on a web page immediately.</p>
<h3>Reading ArrayBuffers</h3>
<p>The <code>ArrayBuffer</code> type<sup>[1]</sup> was first introduced as part of WebGL. An <code>ArrayBuffer</code> represents a finite number of bytes that may be used to store numbers of any size. The way data is read from an <code>ArrayBuffer</code> is by using a specific view, such as <code>Int8Array</code>, which treats the underlying bytes as a collection of 8-bit signed integers or <code>Float32Array</code>, which treats the underlying bytes as a collection of 32-bit floating point numbers. These are called typed arrays<sup>[2]</sup>, which force you to work with a specific numeric type rather than containing any type of data (as with traditional arrays).</p>
<p>You use an <code>ArrayBuffer</code> primarily when dealing with binary files, to have more fine-grained control over the data. It&#8217;s beyond the scope of this post to explain all the ins and outs of <code>ArrayBuffer</code>, just realize that you can read a file into an <code>ArrayBuffer</code> pretty easily if you need it. You can pass an <code>ArrayBuffer</code> directly into an XHR object&#8217;s <code>send()</code> method to send the raw data to the server (you&#8217;ll have to read this data from the request on the server to reconstruct the file), so long as your browser fully supports <cite>XMLHttpRequest Level 2</cite><sup>[3]</sup> (most recent browsers, including Internet Explorer 10 and Opera 12).</p>
<h2>Up next</h2>
<p>Reading data from a file using a <code>FileReader</code> is pretty simple. If you know how to use <code>XMLHttpRequest</code>, there&#8217;s no reason you can&#8217;t also be reading data from files. In the next part of this series, you&#8217;ll learn more about using the <code>FileReader</code> events and understanding more about possible errors.</p>
<h2>References</h2>
<ol>
<li><a href="https://developer.mozilla.org/en/JavaScript_typed_arrays/ArrayBuffer">ArrayBuffer</a></li>
<li><a href="http://www.khronos.org/registry/typedarray/specs/latest/">Typed Array Specification</a></li>
<li><a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest Level 2</a></li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=Ud1dhk6BAFg:caqe7RgWm8w:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=Ud1dhk6BAFg:caqe7RgWm8w:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=Ud1dhk6BAFg:caqe7RgWm8w:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=Ud1dhk6BAFg:caqe7RgWm8w:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=Ud1dhk6BAFg:caqe7RgWm8w:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=Ud1dhk6BAFg:caqe7RgWm8w:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/Ud1dhk6BAFg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/05/15/working-with-files-in-javascript-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/05/15/working-with-files-in-javascript-part-2/</feedburner:origLink></item>
		<item>
		<title>Working with files in JavaScript, Part 1: The Basics</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/hMyQ-_P7Y1Y/</link>
		<comments>http://www.nczonline.net/blog/2012/05/08/working-with-files-in-javascript-part-1/#comments</comments>
		<pubDate>Tue, 08 May 2012 14:30:01 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[File API]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2917</guid>
		<description><![CDATA[Many years ago, I was asked during a job interview at Google what changes I would make to the web in order to provide better experiences. At the top of my list was having some way to work with files other than the &#60;input type="file"&#62; control. Even as the rest of the web was evolving, [...]]]></description>
			<content:encoded><![CDATA[<p>Many years ago, I was asked during a job interview at Google what changes I would make to the web in order to provide better experiences. At the top of my list was having some way to work with files other than the <code>&lt;input type="file"&gt;</code> control. Even as the rest of the web was evolving, the way we dealt with files never changed since it was first introduced. Thankfully, with HTML5 and related APIs, we now have far more options for working with files than ever before in the latest versions of desktop browsers (iOS still has no support for the File API).</p>
<h2>The File type</h2>
<p>The <code>File</code> type is defined in the <cite>File API</cite><sup>[1]</sup> specification and is an abstract representation of a file. Each instance of <code>File</code> has several properties:</p>
<ul>
<li><code>name</code> &#8211; the filename</li>
<li><code>size</code> &#8211; the size of the file in bytes</li>
<li><code>type</code> &#8211; the MIME type for the file</li>
</ul>
<p>A <code>File</code> object basically gives you essential information about the file without providing direct access to the file contents. That&#8217;s important because reading from files requires disk access, and depending on the size of the file, that process has the potential to take a significant amount of time. A <code>File</code> object is just a reference to a file, and getting data from that file is a separate process altogether.</p>
<h2>Getting File references</h2>
<p>Of course, access to user files is strictly forbidden on the web because it&#8217;s a very obvious security issue. You wouldn&#8217;t want to load up a web page and then have it scan your hard drive and figure out what&#8217;s there. You need permission from the user in order to access files from their computer. There&#8217;s no need for messy permission windows, however, because users grant permission for web pages to read files all the time when they decide to upload something.</p>
<p>When you use a <code>&lt;input type="file"&gt;</code> control, you&#8217;re giving the web page (and the server) permission to access that file. So it makes sense that the first place you can retrieve <code>File</code> objects is through a <code>&lt;input type="file"&gt;</code> control.</p>
<p>HTML5 defines a <code>files</code> property for all <code>&lt;input type="file"&gt;</code> controls. This collection is a <code>FileList</code>, which is an array-like structure called <code>FileList</code> containing <code>File</code> objects for each selected file in the control (remember, HTML5 allows multiple file selection in these controls). So at any point in time, you can get access to the files a user has selected using code similar to this:</p>
<pre><code>&lt;input type="file" id="your-files" multiple&gt;
&lt;script&gt;
var control = document.getElementById("your-files");
control.addEventListener("change", function(event) {

    // When the control has changed, there are new files

    var i = 0,
        files = control.files,
        len = files.length;

    for (; i < len; i++) {
        console.log("Filename: " + files[i].name);
        console.log("Type: " + files[i].type);
        console.log("Size: " + files[i].size + " bytes");
    }

}, false);
&lt;/script&gt;</code></code></pre>
<p>This relatively simple code listens for the <code>change</code> event on the file control. When the event fires, it signifies that the file selection has changed, and the code iterates through each <code>File</code> object and outputs its information. Keep in mind that the <code>files</code> property is always accessible from JavaScript, so you don&#8217;t have to wait for <code>change</code> to try to read it.</p>
<h2>Drag and drop files</h2>
<p>Accessing files from form controls still requires the form control and the associated user action of browsing to find the files of interest. Fortunately, <cite>HTML5 Drag and Drop</cite><sup>[2]</sup> provides another way for users to grant access to their files: by simply dragging a file from the desktop into the web browser. All you have to do to take advantage is listen for two events.</p>
<p>In order to read files that are dropped onto an area of the page, you must listen for the <code>dragover</code> and <code>drop</code> events and cancel the default action of both. Doing so tells the browser that you are handling the action directly and it shouldn&#8217;t, for example, open an image file. </p>
<pre><code>&lt;div id="your-files"&gt;&lt;/div&gt;
&lt;script&gt;
var target = document.getElementById("your-files");

target.addEventListener("dragover", function(event) {
    event.preventDefault();
}, false);

target.addEventListener("drop", function(event) {

    // cancel default actions
    event.preventDefault();

    var i = 0,
        files = event.dataTransfer.files,
        len = files.length;

    for (; i < len; i++) {
        console.log("Filename: " + files[i].name);
        console.log("Type: " + files[i].type);
        console.log("Size: " + files[i].size + " bytes");
    }

}, false);
&lt;/script&gt;</code></code></pre>
<p>The <code>event.dataTransfer.files</code> is another <code>FileList</code> object that you can access to get file information. The code is almost exactly the same as using the file form control and the <code>File</code> objects can be accessed in the same way.</p>
<h2>Ajax file upload</h2>
<p>Once you have a reference to the file, you&#8217;re able to do something that&#8217;s pretty cool: upload a file via Ajax. This is all possible due to the <code>FormData</code> object, which is defined in <cite>XMLHttpRequest Level 2</cite><sup>[3]</sup>. This object represents an HTML form and allows you to add key-value pairs to be submitted to the server via the <code>append()</code> method:</p>
<pre><code>var form = new FormData();
form.append("name", "Nicholas");
</code></pre>
<p>The great thing about the <code>FormData</code> object is that you can add a file directly to it, effectively mimicking a file upload by HTML form. All you have to do is add the <code>File</code> reference with a specific name, and the browser does the rest. For example:</p>
<pre><code>// create a form with a couple of values
var form = new FormData();
form.append("name", "Nicholas");
form.append("photo", control.files[0]);

// send via XHR - look ma, no headers being set!
var xhr = new XMLHttpRequest();
xhr.onload = function() {
    console.log("Upload complete.");
};
xhr.open("post", "/entrypoint", true);
xhr.send(form);
</code></pre>
<p>Once the <code>FormData</code> object is passed into <code>send()</code>, the proper HTTP headers are automatically set for you. You don&#8217;t have to worry about setting the correct form encoding when using files, so the server gets to act as if a regular HTML form has been submitted, reading file data from the &#8220;photo&#8221; key and text data from the &#8220;name&#8221; key. This gives you the freedom to write processing code on the backend that can easily work with both traditional HTML forms and Ajax forms of this nature.</p>
<p>And all of this works in the most recent version of every browser, including Internet Explorer 10.</p>
<h2>Up next</h2>
<p>You now know the two methods of accessing <code>File</code> information in the browser: through a file upload control and through native drag and drop. There will likely be other ways to access files in the future, but for now, these are the two you need to know. Of course, reading information about files is just part of the problem. The next step is read data from those files, and that&#8217;s where part 2 will pick up.</p>
<h2>References</h2>
<ol>
<li><a href="http://dev.w3.org/2006/webapi/FileAPI/">File API specification (editor&#8217;s draft)</a></li>
<li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dnd">HTML5 Drag and Drop</a></li>
<li><a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest Level 2</a></li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=hMyQ-_P7Y1Y:lN7_FiGP95Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=hMyQ-_P7Y1Y:lN7_FiGP95Q:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=hMyQ-_P7Y1Y:lN7_FiGP95Q:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=hMyQ-_P7Y1Y:lN7_FiGP95Q:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=hMyQ-_P7Y1Y:lN7_FiGP95Q:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=hMyQ-_P7Y1Y:lN7_FiGP95Q:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/hMyQ-_P7Y1Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/05/08/working-with-files-in-javascript-part-1/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/05/08/working-with-files-in-javascript-part-1/</feedburner:origLink></item>
		<item>
		<title>Book review: The Linux Command Line</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/K4rtSspWR2Q/</link>
		<comments>http://www.nczonline.net/blog/2012/05/01/book-review-the-linux-command-line/#comments</comments>
		<pubDate>Tue, 01 May 2012 14:00:21 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Book Reviews]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2911</guid>
		<description><![CDATA[I have a confession to make, before joining Yahoo!, I had never used Linux before. After having one semester of UNIX in college, I spent the next five years just using Windows. When I got to Yahoo!, I was faced with the daunting task of learning Linux on the job as I went. I still [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.com/gp/product/1593273894/ref=as_li_ss_tl?ie=UTF8&#038;tag=nczonline-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1593273894"><img src="http://www.nczonline.net/blog/wp-content/uploads/2012/04/lrg-226x300.jpg" alt="The Linux Command Line" width="226" height="300" style="float:right" /></a>I have a confession to make, before joining Yahoo!, I had never used Linux before. After having one semester of UNIX in college, I spent the next five years just using Windows. When I got to Yahoo!, I was faced with the daunting task of learning Linux on the job as I went. I still remember our intern that first year I was there laughing as I struggled to navigate around my development box. Yeah, the intern was laughing at me.</p>
<p>I really and truly wish that <cite><a href="http://www.amazon.com/gp/product/1593273894/ref=as_li_ss_tl?ie=UTF8&#038;tag=nczonline-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1593273894">The Linux Command Line</a></cite> had been available to me at that time. This is exactly what a Linux beginner needs to get up to speed quickly. The book goes beyond simply walking through all of the command line utilities, and ventures into the realm of theory and how things work together. I&#8217;m definitely not a Linux expert, but I have been using it on a day-to-day basis for about six years, and I still felt like I learned an incredible amount from this book.</p>
<p>The author approaches all of the topics in a very friendly way. All of the examples are easy to follow and he even takes time to explain some of the differences across various flavors of Linux. He covers all of the common command line tools, taking you through in a logical order with great narrative.</p>
<p>This book has earned a permanent place on my desk, as I find myself repeatedly going back to it when I get stuck on something. If you&#8217;re a Linux beginner, or just really want to understand the system better, I can&#8217;t recommend this book enough. I&#8217;ll probably be rereading it a couple more times, myself, to make sure that everything sticks. In the meantime, I&#8217;ve already gone through and updated a bunch of bash scripts that I now realize aren&#8217;t coded as well as they should be.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=K4rtSspWR2Q:Crwa5sL-ucU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=K4rtSspWR2Q:Crwa5sL-ucU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=K4rtSspWR2Q:Crwa5sL-ucU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=K4rtSspWR2Q:Crwa5sL-ucU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=K4rtSspWR2Q:Crwa5sL-ucU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=K4rtSspWR2Q:Crwa5sL-ucU:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/K4rtSspWR2Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/05/01/book-review-the-linux-command-line/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/05/01/book-review-the-linux-command-line/</feedburner:origLink></item>
		<item>
		<title>The performance of localStorage revisited</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/6mA2S8PkfSM/</link>
		<comments>http://www.nczonline.net/blog/2012/04/25/the-performance-of-localstorage-revisited/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 21:52:33 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2907</guid>
		<description><![CDATA[Now a few weeks removed from a large amount of hand-ringing around the performance of localStorage in browsers, I&#8217;ve learned some more about why there was such a concern at Mozilla (which prompted Chris to write his blog post[1]). The post was met with skepticism because it lacked two key components: numbers and a comparison. [...]]]></description>
			<content:encoded><![CDATA[<p>Now a few weeks removed from a large amount of hand-ringing around the performance of <code>localStorage</code> in browsers, I&#8217;ve learned some more about why there was such a concern at Mozilla (which prompted Chris to write his blog post<sup>[1]</sup>). The post was met with skepticism because it lacked two key components: numbers and a comparison. The assertion was that <code>localStorage</code> is slow, but there was no data to back it up.</p>
<p>Wanting to get to the bottom of it, I<sup>[2]</sup> and John Allsopp<sup>[3]</sup> wrote blog posts trying to provide numbers around <code>localStorage</code>. John&#8217;s post focused on quantifying the amount of time it takes to perform a single read and a single write, which gave us good initial numbers for these operations. My post focused on comparing <code>localStorage</code> reads and writes to cookie reads and writes from JavaScript. My theory was that cookies are the closest appromixation of <code>localStorage</code> due to the fact that its contents are stored on disk and are shared by all tabs pointing to the same origin. Both John and I concluded by saying that <code>localStorage</code> doesn&#8217;t have an appreciably bad affect on performance either as an aggregate rating or in comparison to cookies. </p>
<h2>More details</h2>
<p>Subsequent to that, I started a conversation with Jonas Sicking from Mozilla, who actually worked on the <code>localStorage</code> implementation for Firefox and so has a unique perspective. He started from the position that there is a performance problem and I started from the position that there is not, based on the numbers from John and I. Jonas pointed out a key piece of information I wasn&#8217;t aware of: the performance issue isn&#8217;t with individual reads and writes, it&#8217;s with the initial read into memory.</p>
<p>Firefox starts out by reading all of the data from <code>localStorage</code> into memory for the page&#8217;s origin. Once the data is in memory, reads and writes should be relatively fast (though they do still appear slower than reading and writing to a native JavaScript object &#8211; not sure why), so our measuring of reads and writes doesn&#8217;t capture the full picture. Jonas&#8217; assertion is that reading the data from <code>localStorage</code> on page load is the concern.</p>
<p>As Jonas kept telling me (and finally it stuck), the real problem with <code>localStorage</code> is that it&#8217;s a synchronous API, which makes the implementors decide between a limited number of options. One option is to load all the data as the page is loading, but that has a side effect of slowing down initial page load because JavaScript using <code>localStorage</code> can&#8217;t execute until the data for <code>localStorage</code> has been completely read. That means a large amount of data in <code>localStorage</code> could actually increase page load time because JavaScript needs to wait before executing.</p>
<p>The other option isn&#8217;t much better. If you were to wait until the first time <code>localStorage</code> was used, it would require a full (blocking) stop while the data was read from disk initially. Once again, this could be noticeable if there&#8217;s a large amount of data on disk. What&#8217;s more, you could argue that a delay on calling <code>localStorage.getItem()</code> is unexpected, because there is an assumption that you&#8217;re already working in memory and so the operation should be fast. This is why Firefox loads the data on page load.</p>
<p>In reality, this becomes the same problem as cookies. Cookies are stored on disk and read into memory upon page load as well. The difference is in the size of the data. Cookies are still fairly limited in size (around 4KB) where <code>localStorage</code> is much large (5MB). Of course, reading a 5MB file from the file system will be faster than downloading it over the internet, but who&#8217;s to say if it would significantly affect page load time?</p>
<h2>Benchmarks?</h2>
<p>I tried to run some benchmarks but was met with a technical limitation: no one is sure if our current testing tools are accurately taking the initial <code>localStorage</code> read into account. Without that information, it&#8217;s hard to know whether or not <code>localStorage</code> is actually a performance problem for initial page load. It definitely isn&#8217;t a performance issue for reads and writes after the fact (though it doesn&#8217;t come without some cost, as noted previously). </p>
<h2>A new API?</h2>
<p>The call to create a new API to replace <code>localStorage</code> seems a bit permature, but is basically centered around three main ideas:</p>
<ol>
<li>The browser shouldn&#8217;t need to read a large amount of data from disk on page load.</li>
<li>The read from disk should be asynchronous and not block the UI thread.</li>
<li>The developer should be able to indicate when the read should happen.</li>
</ol>
<p>This led Jonas to suggesting several alternatives APIs on Chris&#8217; original post. The one I like the best is this:</p>
<pre><code>getBetterLocalStorage(function(storage) {
    x = storage.foo;
    storage.bar = calculateStuff(y);
    storage.baz++;
});</code></pre>
<p>Ignoring the name, the <code>getBetterLocalStorage()</code> function signals the browser that it&#8217;s time to read everything into memory, so the <code>storage</code> object can be used as any other object. Once the callback function is finished executing, the changes would be written back to disk. Though I&#8217;m not ready to throw out <code>localStorage</code> completely, I do like the direction of this API. In fact, it closely follows a proposal I made for improving <code>localStorage</code> with expiration dates and encryption.<sup>[4]</sup></p>
<h2>Conclusion</h2>
<p>Whether or not <code>localStorage</code> is a performance issue on page load is still a question. It&#8217;s hard for to know for sure if this is a real issue until we can get some good benchmarks from browsers. Unfortunately, this will likely have to come from browser developers who can look at the code and figure out whether <code>localStorage</code> is already being accounted for, and if not, how to measure it. </p>
<p>In the meantime, IndexedDB is definitely <em>not</em> a suitable replacement for <code>localStorage</code> in almost every case. IndexedDB could be used, as Jonas pointed out, to create a solution similar to the one he proposed. However, it&#8217;s still a bit of overhead to write that out. My advice: don&#8217;t worry too much about <code>localStorage</code> for now&#8230;but don&#8217;t go storing 5MB of data in it either, just in case.</p>
<h2>References</h2>
<ol>
<li><a href="http://hacks.mozilla.org/2012/03/there-is-no-simple-solution-for-local-storage/">There is no simple solution for localStorage</a> by Chris Heilmann</li>
<li><a href="http://www.nczonline.net/blog/2012/03/07/in-defense-of-localstorage/">In defense of localStorage</a> by Me</li>
<li><a href="http://www.webdirections.org/blog/localstorage-perhaps-not-so-harmful/">localStorage, perhaps not so harmful</a> by John Allsopp</li>
<li><a href="http://www.nczonline.net/blog/2010/04/13/towards-more-secure-client-side-data-storage/">Towards more secure client-side data storage</a> by Me</li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=6mA2S8PkfSM:BopZnR8SwgY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=6mA2S8PkfSM:BopZnR8SwgY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=6mA2S8PkfSM:BopZnR8SwgY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=6mA2S8PkfSM:BopZnR8SwgY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=6mA2S8PkfSM:BopZnR8SwgY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=6mA2S8PkfSM:BopZnR8SwgY:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/6mA2S8PkfSM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/04/25/the-performance-of-localstorage-revisited/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/04/25/the-performance-of-localstorage-revisited/</feedburner:origLink></item>
		<item>
		<title>How to install Apache Ant on Windows</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/W_Qy0OO76Gc/</link>
		<comments>http://www.nczonline.net/blog/2012/04/12/how-to-install-apache-ant-on-windows/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 16:49:04 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2901</guid>
		<description><![CDATA[Apache Ant[1] is still my favorite tool for creating build systems for my code. Yes, I know there are a lot of shiny new tools written in Node.js or something else, but I&#8217;ve used Ant for a long time and have found it easy to teach others. What&#8217;s more, it comes installed on Macs and [...]]]></description>
			<content:encoded><![CDATA[<p>Apache Ant<sup>[1]</sup> is still my favorite tool for creating build systems for my code. Yes, I know there are a lot of shiny new tools written in Node.js or something else, but I&#8217;ve used Ant for a long time and have found it easy to teach others. What&#8217;s more, it comes installed on Macs and is an easy install on Linux as a package.</p>
<p>Unfortunately, it&#8217;s a bit of a beast to install on Windows. Every time I have to install Ant on another Windows machine I end up searching the web yet again for a good set of instructions. So this post is primarily for myself, so that I don&#8217;t need to search too far.</p>
<h2>Prerequisites</h2>
<p>Before beginning, make sure you have the latest JDK installed. If not, go download it from Sun<sup>[2]</sup> and install it. It&#8217;s better to install the JDK instead of just the JRE because some Ant tasks require the JDK.</p>
<h2>Step 1: Download and install</h2>
<p>The first step, as with most software, is to download Ant. Go to the Ant homepage and click to download the binary. Because we&#8217;re talking about Windows, choose to download the ZIP file rather than any of the others. Scroll down to where it says &#8220;Current release of Ant&#8221; and click on the ZIP filename.</p>
<p>Once downloaded, unzip the file. You&#8217;ll now need to choose a permanent home for Ant on the computer. I tend to use c:\java\ant for simplicity, but you can use whatever you want. I do recommend, however, that the path have no spaces in it (spaces make things more complicated).</p>
<h2>Step 2: Set environment variables</h2>
<p>This is the part that I always forget. Because you&#8217;re installing Ant by hand, you also need to deal with setting environment variables by hand. </p>
<p><strong>For Windows XP</strong>: To set environment variables on Windows XP, right click on My Computer and select Properties. Then go to the Advanced tab and click the Environment Variables button at the bottom.</p>
<p><strong>For Windows 7</strong>: To set environment variables on Windows 7, right click on Computer and select Properties. Click on Advanced System Settings and click the Environment Variables button at the bottom.</p>
<p>The dialog for both Windows XP and Windows 7 is the same. Make sure you&#8217;re only working on system variables and not user variables.</p>
<p>The only environment variable that you absolutely need is <code>JAVA_HOME</code>, which tells Ant the location of your JRE. If you&#8217;ve installed the JDK, this is likely <code>c:\Program Files\Java\jdk1.x.x\jre</code> on Windows XP and <code>c:\Program Files(x86)\Java\jdk1.x.x\jre</code> on Windows 7. You&#8217;ll note that both have spaces in their paths, which causes a problem. You need to use the mangled name<sup>[3]</sup> instead of the complete name. So for Windows XP, use <code>C:\Progra~1\Java\jdk1.x.x\jre</code> and for Windows 7, use <code>C:\Progra~2\Java\jdk1.6.0_26\jre</code> if it&#8217;s installed in the <code>Program Files(x86)</code> folder (otherwise use the same as Windows XP).</p>
<p>That alone is enough to get Ant to work, but for convenience, it&#8217;s a good idea to add the Ant binary path to the <code>PATH</code> variable. This variable is a semicolon-delimited list of directories to search for executables. To be able to run <code>ant</code> in any directory, Windows needs to know both the location for the <code>ant</code> binary and for the <code>java</code> binary. You&#8217;ll need to add both of these to the end of the <code>PATH</code> variable. For Windows XP, you&#8217;ll likely add something like this:</p>
<pre><code>;c:\java\ant\bin;C:\Progra~1\Java\jdk1.x.x\jre\bin</code></pre>
<p>For Windows 7, it will look something like this:</p>
<pre><code>;c:\java\ant\bin;C:\Progra~2\Java\jdk1.x.x\jre\bin</code></pre>
<h2>Done</h2>
<p>Once you&#8217;ve done that and applied the changes, you&#8217;ll need to open a new command  prompt to see if the variables are set properly. You should be able to simply run <code>ant</code> and see something like this:</p>
<pre><code>Buildfile: build.xml does not exist!
Build failed</code></pre>
<p>That means Ant is installed properly and is looking for a <code>build.xml</code> file.</p>
<h2>References</h2>
<ol>
<li><a href="http://ant.apache.org/">Apache Ant homepage</a></li>
<li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Java SE Downloads</a></li>
<li><a href="http://en.wikipedia.org/wiki/Tilde#Microsoft_filenames">Microsoft filenames</a></li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=W_Qy0OO76Gc:p2cHqIqCp5c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=W_Qy0OO76Gc:p2cHqIqCp5c:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=W_Qy0OO76Gc:p2cHqIqCp5c:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=W_Qy0OO76Gc:p2cHqIqCp5c:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=W_Qy0OO76Gc:p2cHqIqCp5c:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=W_Qy0OO76Gc:p2cHqIqCp5c:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/W_Qy0OO76Gc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/04/12/how-to-install-apache-ant-on-windows/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/04/12/how-to-install-apache-ant-on-windows/</feedburner:origLink></item>
		<item>
		<title>It’s time to start using JavaScript strict mode</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/iW3em0rCYxc/</link>
		<comments>http://www.nczonline.net/blog/2012/03/13/its-time-to-start-using-javascript-strict-mode/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 23:44:43 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Strict Mode]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2889</guid>
		<description><![CDATA[ECMAScript 5 introduced strict mode to JavaScript. The intent is to allow developers to opt-in to a &#8220;better&#8221; version of JavaScript, where some of the most common and egregious errors are handled differently. For a while, I was skeptical, especially with only one browser (Firefox) initially supporting strict mode. Fast forward to today, every major [...]]]></description>
			<content:encoded><![CDATA[<p>ECMAScript 5 introduced strict mode to JavaScript. The intent is to allow developers to opt-in to a &#8220;better&#8221; version of JavaScript, where some of the most common and egregious errors are handled differently. For a while, I was skeptical, especially with only one browser (Firefox) initially supporting strict mode. Fast forward to today, every major browser supports strict mode in their latest version, including Internet Explorer 10 and Opera 12. It&#8217;s time to start using strict mode.</p>
<h2>What does it do?</h2>
<p>Strict mode makes a lot of changes to how JavaScript runs, and I group these into two categories: obvious and subtle. The subtle changes aim to fix subtle problems, and I&#8217;m not going to delve into those here; if you&#8217;re interested in those details, please see Dmitry Soshnikov&#8217;s excellent, <cite>ECMA-262-5 in Detail. Chapter 2. Strict Mode</cite><sup>[1]</sup>. I&#8217;m far more interested in talking about the obvious changes: the ones you should know about before using strict mode, and the ones that will most likely help you the most.</p>
<p>Before getting into specific features, keep in mind that one of the goals of strict mode is to allow for faster debugging of issues. The best way to help developers debug is to throw errors when certain patterns occur, rather than silently failing or behaving strangely (which JavaScript does today outside of strict mode). Strict mode code throws far more errors, and that&#8217;s a good thing, because it quickly calls to attention things that should be fixed immediately.</p>
<h3>Eliminates with</h3>
<p>To begin, strict mode eliminates the <code>with</code> statement. It is now considered invalid JavaScript syntax and will throw a syntax error when it appears in strict mode code. So first step to using strict mode: make sure you&#8217;re not using <code>with</code>.</p>
<pre><code>// Causes a syntax error in strict mode
with (location) {
    alert(href);
}</code></pre>
<h3>Prevents accidental globals</h3>
<p>Next, variables must be declared before they can be assigned to. Without strict mode, assigning a value to an undeclared variable automatically creates a global variable with that name. This is one of the most common errors in JavaScript. In strict mode, attempting to do so throws an error.</p>
<pre><code>// Throws an error in strict mode
(function() {

    someUndeclaredVar = "foo";

}());
</code></pre>
<h3>Eliminates this coercion</h3>
<p>Another important change is a <code>this</code>-value of <code>null</code> or <code>undefined</code> is no longer coerced to the global. Instead, <code>this</code> remains its original value, and so may cause some code depending on the coercion to break. For example:</p>
<pre><code>window.color = "red";
function sayColor() {
    alert(this.color);
}

// Throws an error in strict mode, "red" otherwise
sayColor();

// Throws an error in strict mode, "red" otherwise
sayColor.call(null);
</code></pre>
<p>Basically, the <code>this</code>-value must be assigned a value or else it remains <code>undefined</code>. That means constructors accidentally called without <code>new</code> are also affected:</p>
<pre><code>function Person(name) {
    this.name = name;
}

// Error in strict mode
var me = Person("Nicholas");
</code></pre>
<p>In this code, <code>this</code> is <code>undefined</code> when the <code>Person</code> constructor is called without <code>new</code>. Since you can&#8217;t assign a property to <code>undefined</code>, this code throws an error. In non-strict mode, <code>this</code> would be coerced to the global and so <code>name</code> would be assigned as a global variable.</p>
<h3>No duplicates</h3>
<p>It can be quite easy to duplicate properties in objects or named arguments in functions if you&#8217;ve been doing a lot of coding. Strict mode throws an error when it comes across either pattern:</p>
<pre><code>// Error in strict mode - duplicate arguments
function doSomething(value1, value2, value1) {
    //code
}

// Error in strict mode - duplicate properties
var object = {
    foo: "bar",
    foo: "baz"
};
</code></pre>
<p>These are both syntax errors and so the error is thrown before the code is executed.</p>
<h3>Safer eval()</h3>
<p>Even though <code>eval()</code> wasn&#8217;t removed, it has undergone some changes in strict mode. The biggest change is that variables and functions declared inside of an <code>eval()</code> statement are no longer created in the containing scope. For example:</p>
<pre><code>(function() {

    eval("var x = 10;");

    // Non-strict mode, alerts 10
    // Strict mode, throws an error because x is undeclared
    alert(x);

}());
</code></pre>
<p>Any variables or functions created inside of <code>eval()</code> stay inside of <code>eval()</code>. You can, however, return a value from <code>eval()</code> if you wish to pass a value back out:</p>
<pre><code>(function() {

    var result = eval("var x = 10, y = 20; x + y");

    // Works in strict and non-strict mode (30)
    alert(result);

}());
</code></pre>
<h3>Errors for immutables</h3>
<p>ECMAScript 5 also introduced the ability to modify property attributes, such as setting a property as read only or freezing an entire object&#8217;s structure. In non-strict mode, attempting to modify an immutable property fails silently. You&#8217;ve probably run into this issue with some native APIs. Strict mode ensures that an error is thrown whenever you try to modify an object or object property in a way that isn&#8217;t allowed.</p>
<pre><code>var person = {};
Object.defineProperty(person, "name", {
    writable: false,
    value: "Nicholas"
});

// Fails silently in non-strict mode, throws error in strict mode
person.name = "John";
</code></pre>
<p>In this example, the <code>name</code> property is set to read only. In non-strict mode, assigning to <code>name</code> fails silently; in strict mode, an error is thrown.</p>
<p><strong>Note:</strong> I very strongly encourage you to use strict mode if you&#8217;re using any of the ECMAScript attribute capabilities. If you&#8217;re changing the mutability of objects, you&#8217;ll run into a lot of errors that will fail silently in non-strict mode.</p>
<h2>How do you use it?</h2>
<p>Strict mode is very easily enabled in modern browsers using the following pragma:</p>
<pre><code>"use strict";</code></pre>
<p>Even though this looks like a string that isn&#8217;t assigned to a variable, it actually instructs conforming JavaScript engines to switch into strict mode (browsers that don&#8217;t support strict mode simply read this as an unassigned string and continue to work as usual). You can use it either globally or within a function. That being said, <em>you should never use it globally</em>. Using the pragma globally means that any code within the same file also runs in strict mode.</p>
<pre><code>// Don't do this
"use strict";

function doSomething() {
    // this runs in strict mode
}

function doSomethingElse() {
    // so does this
}</code></pre>
<p>This may not seem like a big deal, however, it can cause big problems in our world of aggressive script concatenation. All it takes is one script to include the pragma globally for every script its concatenated with to be switch into strict mode (potentially revealing errors you never would have anticipated).</p>
<p>For that reason, it&#8217;s best to only use strict mode inside of functions, such as:</p>
<pre><code>function doSomething() {
    "use strict";
    // this runs in strict mode
}

function doSomethingElse() {
    // this doesn't run in strict mode
}</code></pre>
<p>If you want strict mode to apply to more than one function, use an immediately-invoked function expression (IIFE):</p>
<pre><code>(function() {

    "use strict";

    function doSomething() {
        // this runs in strict mode
    }

    function doSomethingElse() {
        // so does this
    }
}());</code></pre>
<h2>Conclusion</h2>
<p>I strongly recommend everyone start using strict mode now. There are enough browsers supporting it that strict mode will legitimately help save you from errors you didn&#8217;t even know where in your code. Make sure you don&#8217;t include the pragma globally, but use IIFEs as frequently as you like to apply strict mode to as much code as possible. Initially, there will be errors you&#8217;ve never encountered before &#8211; this is normal. Make sure you do a fair amount of testing after switching to strict mode to make sure you&#8217;ve caught everything. Definitely don&#8217;t just throw <code>"use strict"</code> in your code and assume there are no errors. The bottom line is that it&#8217;s time to start using this incredibly useful language feature to write better code.</p>
<p><strong>Update (14-Mar-2012):</strong> Added note about using strict mode pragma with non-conforming JavaScript engines.<br />
<strong>Update (21-Mar-2012):</strong> Fixed typo.</p>
<h2>References</h2>
<ol>
<li><a href="http://dmitrysoshnikov.com/ecmascript/es5-chapter-2-strict-mode/">ECMA-262-5 in Detail. Chapter 2. Strict Mode</a> by Dmitry Soshnikov</li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=iW3em0rCYxc:ETP9pMos_Yc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=iW3em0rCYxc:ETP9pMos_Yc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=iW3em0rCYxc:ETP9pMos_Yc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=iW3em0rCYxc:ETP9pMos_Yc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=iW3em0rCYxc:ETP9pMos_Yc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=iW3em0rCYxc:ETP9pMos_Yc:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/iW3em0rCYxc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/03/13/its-time-to-start-using-javascript-strict-mode/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/03/13/its-time-to-start-using-javascript-strict-mode/</feedburner:origLink></item>
		<item>
		<title>In defense of localStorage</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/jpO9DjzDSPs/</link>
		<comments>http://www.nczonline.net/blog/2012/03/07/in-defense-of-localstorage/#comments</comments>
		<pubDate>Thu, 08 Mar 2012 03:01:07 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2885</guid>
		<description><![CDATA[Earlier this week, Chris Heilmann wrote a blog post entitled, There is no simple solution for localStorage[1] in which he decried localStorage as slow and encouraged everyone to stop using it. Surprisingly, in a post about performance, there was no mention of what &#8220;slow&#8221; or &#8220;terrible performance&#8221; actually meant. Performance can&#8217;t be discussed in a [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week, Chris Heilmann wrote a blog post entitled, <cite>There is no simple solution for localStorage</cite><sup>[1]</sup> in which he decried <code>localStorage</code> as slow and encouraged everyone to stop using it. Surprisingly, in a post about performance, there was no mention of what &#8220;slow&#8221; or &#8220;terrible performance&#8221; actually meant. Performance can&#8217;t be discussed in a vacuum, which is part of what made my reaction to his post one of confusion more than anything else.</p>
<h2>What is slow?</h2>
<p>So does <code>localStorage</code> have a performance problem? Quite simply, I don&#8217;t know. Is storing and retrieving data from <code>localStorage</code> slower than that of a regular, in-memory object? Yes. I wrote a post about this for 2011 Performance advent calendar<sup>[2]</sup>. In fact, it&#8217;s quite a bit slower when reading data out. My conclusion was that you should try to limit reads by storing multiple pieces of data in the same key. But as with most performance metrics, this really only matters when you&#8217;re performing the same operation multiple times in a row. If you&#8217;re only ever reading one value or writing one value, you&#8217;ll likely never run into a performance issue regardless of the data size or what&#8217;s going on with your system.</p>
<p>So <code>localStorage</code> is slower than using an in-memory object. Cars are slower than airplanes. What does that tell us? Not a whole lot.</p>
<h2>Pain points</h2>
<p>The fact of the matter is that <code>localStorage</code> reads from and writes to disk, which is always slower than an in-memory operation because there&#8217;s hardware involved. That&#8217;s the first problem. The second problem is the per-origin nature of <code>localStorage</code>. This characteristic means that two browser windows or tabs open to the same origin can both be reading from or writing to the same <code>localStorage</code> at the same time. That, in turn, means the browser needs to be incredibly smart about how it performs each operation. If tab A is writing to <code>localStorage</code> around the same time that tab B is reading from <code>localStorage</code>, which operation should happen first?</p>
<p>Each operation, read and write, then needs to lock <code>localStorage</code> to ensure data integrity. This is actually a big issue. Interacting with files is also dicey since another system process might also be working the same file. Consider a simple write operation:</p>
<pre><code>localStorage.setItem("foo", "bar");</code></pre>
<p>This operation is synchronous, meaning that the UI thread is blocked in the browser until the write is complete. No further JavaScript will execute and no further UI updates drawn. During this one method call, several things happen:</p>
<ol>
<li>If <code>localStorage</code> is busy with another window or tab, then wait. This is problematic since there&#8217;s no way to know how long this will be.</li>
<li>If the file is busy, then wait. The files may be scanned by antivirus, be included in a backup job, etc., and may therefore be unavailable until such operations complete. This is also problematic because it&#8217;s unpredictable.</li>
<li>Open the file for writing.</li>
<li>Seek the right spot to write to the file.</li>
<li>Write to the file.</li>
<li>Close the file.</li>
</ol>
<p>Only after all of that completes can the browser continue on to execute other statements. So really, the issue isn&#8217;t that <code>localStorage</code> is slow, it&#8217;s that <code>localStorage</code> must necessarily block on each operation to maintain data integrity.</p>
<h2>Compared to cookies</h2>
<p>The closest comparable API for JavaScript is the cookie API (though calling <code>document.cookie</code> an API is incredibly generous). Cookies are also name-value pairs, albeit with some additional metadata, which uses files as storage and must be synchronized across browser windows and tabs. I was surprised that Chris didn&#8217;t compare <code>localStorage</code> to cookies since the API was clearly meant to move us from storing client-only data in cookies to storing it in <code>localStorage</code>. It&#8217;s no accident that the <code>localStorage</code> API looks a lot like various cookie APIs.</p>
<p>When I created a benchmark<sup>[3]</sup> to test <code>localStorage</code> against cookies for reading and writing, the results were quite interesting. Internet Explorer, Chrome, and Safari (including iOS), reading cookies was slower than reading from  <code>localStorage</code> and writing to cookies was much slower than writing to <code>localStorage</code>. Firefox and Opera exhibit the same performance characteristics on writes as the others (with cookies being slower), but reading from a cookie is faster. So in many cases across browsers, <code>localStorage</code> is actually a <em>performance improvement</em> over using cookies with JavaScript.</p>
<h2>APIs</h2>
<p>The reason <code>localStorage</code> is popular is partly due to its simplicity. That simplicity is by design and was first designed and implemented by browser vendors, which is why it seems strange that a browser vendor would now lead the charge against an API it had a hand in creating. Yes, humans create browsers and humans can make mistakes, but I don&#8217;t think the design of <code>localStorage</code> is a mistake.</p>
<p>As I was reading over Chris&#8217; plea to look for alternatives, my engineer brain kept repeating to myself, &#8220;this is an implementation issue, not an interface issue&#8221;. Firefox is choosing to preload the <code>localStorage</code> data to improve read performance later, but that&#8217;s an implementation issue. Likewise, the need to read and write synchronously is an implementation issue &#8211; many forget that Internet Explorer 8&#8242;s implementation of <code>localStorage</code> actually wrote asynchronously. That an implementation-specific detail. Why not make all writes happen asynchronously and just keep a copy of the data in memory so it can always be read correctly regardless of the write state?</p>
<p>I&#8217;m not saying that this is necessarily an easy problem to solve; what I am saying is that the API design works well for developers, and for that reason it&#8217;s worth looking at the implementation details to figure out if there&#8217;s an efficient way to hide the warts of the system from web developers.</p>
<p>The proposed alternative, IndexedDB, is perhaps one of the worst API designs I&#8217;ve ever seen. To read and write a single piece of data requires way too many lines of code, ensuring that the API won&#8217;t be used by most developers until someone comes up with a library to abstract away the horribleness. I understand the rationale behind providing such a low-level, asynchronous API (I was even part of the discussions held at Mozilla around web databases), but this absolutely stinks of browser developers creating an API that&#8217;s easy to implement rather than creating an API that&#8217;s easy to consume. This is the opposite of how good APIs are made. IndexedDB will never be a replacement for <code>localStorage</code>, it&#8217;s just too complicated for most uses.</p>
<h2>Non-blocking localStorage</h2>
<p>As discussed previously, the real issue is that <code>localStorage</code> blocks on reads and writes, and the amount of time it blocks can&#8217;t be determined ahead of time. If this turns out to be a concern for you (after benchmarking, of course), then the solution is to use a non-blocking  <code>localStorage </code>mechanism. When you hear the term &#8220;non-blocking&#8221; these days, you should immediately be thinking about Web Workers.</p>
<p>In the near future, I believe that client-side architectures that perform I/O should perform all of that I/O in Web Workers. That means all of your <code>localStorage</code>, XMLHttpRequest, Web Socket, etc., I/O should be done inside of a worker. Basically, you should be able to do something like this:</p>
<pre><code>var worker = new Worker("io.js"); 

worker.postMessage({
    type: "write",
    src: "localStorage",
    key: "foo",
    value: "bar"
}); 

worker.postMessage({
    type: "read",
    src: "localStorage",
    key: "foo"
}); 

worker.onmessage = function(event) {
    alert(event.data.value);
};</code></pre>
<p>All of the reading and writing would be done off of the UI thread, so blocking really doesn&#8217;t matter. I know I&#8217;m not alone in thinking this is the way of the future as the IndexedDB spec has a whole section on synchronous APIs available in workers<sup>[5]</sup>. Having synchronous APIs for IndexedDB makes it less horrible to deal with, but you need to use them in a worker. This hasn&#8217;t been implemented by all browsers yet, but should be coming soon. Add to that the concept of shared workers, web workers that are shared amongst all tabs with pages from the same origin, and you have a great recipe for resolving a lot of I/O issues.</p>
<p>Workers currently have access to <code>XMLHttpRequest</code>, Web Sockets, File Readers, and the such&#8230;and yet no access to <code>localStorage</code>. Why? This is really the solution to the problem: don&#8217;t throw away a great API because in some cases it will cause issues. Instead, make it available in workers so that we have an option for moving the reading/writing off of the UI thread.</p>
<p>Note: It&#8217;s possible that the cross-domain <code>localStorage</code> approach I wrote about previously<sup>[6]</sup> might provide some non-blocking benefits. The cross-frame postMessage() API is asynchronous, but I&#8217;ve not figured out a good way to test if the containing page freezes if an iframe from the same domain accesses <code>localStorage</code> .</p>
<h2>Conclusion</h2>
<p>Asking web developers to give up <code>localStorage</code> is ridiculous. Are there problems with the API? Yes, indeed there are. Are they bad enough to abandon using it altogether? Absolutely not. Claims of terrible performance haven&#8217;t been substantiated. Despite the complaints of browser developers as to the technical difficulties, there are no good alternatives to <code>localStorage</code>. We could always go back to using cookies, but as the previous benchmark shows, that doesn&#8217;t necessarily guarantee better performance. And IndexedDB is a non-starter because the API is too complex for most use cases.</p>
<p>So to Mozilla, and the other browser vendors out there, you&#8217;re a victim of your own success. You wanted to create an API that could be used in place of cookies for storing client-side data, and you created something great. The interface is friendly to web developers and that&#8217;s why it&#8217;s had such rapid adoption. You&#8217;re all quite smart, capable people and I&#8217;m sure you can come up with better ways to implement the API than what we have today. And also, make <code>localStorage</code> accessible in Web Workers, please.</p>
<p><strong>Update (8 March 2012):</strong> Fixed typos and added shared worker reference.</p>
<h2>References</h2>
<ol>
<li><a href="http://hacks.mozilla.org/2012/03/there-is-no-simple-solution-for-local-storage/">There is no simple solution for localStorage</a> by Chris Heilmann</li>
<li><a title="Permanent Link to localStorage Read Performance" href="http://calendar.perfplanet.com/2011/localstorage-read-performance/" rel="bookmark">localStorage Read Performance</a> by Nicholas C. Zakas</li>
<li><a href="http://jsperf.com/localstorage-vs-objects/19">localStorage vs. cookies</a> by Nicholas C. Zakas</li>
<li><a href="http://msdn.microsoft.com/en-us/library/cc197062(v=vs.85).aspx">Introduction to Web Storage</a> by MSDN</li>
<li><a href="http://www.w3.org/TR/IndexedDB/#sync-database">Indexed Database &#8211; Synchronous APIs</a></li>
<li><a href="http://www.nczonline.net/blog/2010/09/07/learning-from-xauth-cross-domain-localstorage/">Learning from XAuth: Cross-Domain localStorage</a> by Nicholas C. Zakas</li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=jpO9DjzDSPs:f-o7mW3xHVQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=jpO9DjzDSPs:f-o7mW3xHVQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=jpO9DjzDSPs:f-o7mW3xHVQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=jpO9DjzDSPs:f-o7mW3xHVQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=jpO9DjzDSPs:f-o7mW3xHVQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=jpO9DjzDSPs:f-o7mW3xHVQ:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/jpO9DjzDSPs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/03/07/in-defense-of-localstorage/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/03/07/in-defense-of-localstorage/</feedburner:origLink></item>
		<item>
		<title>Understanding technical debt</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/UT2oSbBaZGk/</link>
		<comments>http://www.nczonline.net/blog/2012/02/22/understanding-technical-debt/#comments</comments>
		<pubDate>Wed, 22 Feb 2012 17:13:22 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Technical Debt]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2881</guid>
		<description><![CDATA[In the creation of a web site, there are several groups of people who participate: product managers or marketing representatives who are responsible for defining functionality and design, user interface designers who create the actual visuals, and the developers who are responsible for implementing the final product. Of these groups, developers tend to get a [...]]]></description>
			<content:encoded><![CDATA[<p>In the creation of a web site, there are several groups of people who participate: product managers or marketing representatives who are responsible for defining functionality and design, user interface designers who create the actual visuals, and the developers who are responsible for implementing the final product. Of these groups, developers tend to get a reputation for being a bit touchy and grumpy for coming up with reasons why things can&#8217;t or shouldn&#8217;t be done. The reason why this happens is because the developer is, consciously or subconsciously, trying to manage the project&#8217;s technical debt.</p>
<p>Technical debt, or tech debt for short, is quite simply the amount of technical work remaining on a project. It&#8217;s something that is hard to quantify, typically existing in one or more developer minds at any given point in time. There&#8217;s the initial debt of hours or days to completion which is usually the estimate delivered to the manager. After that, every technical decision that&#8217;s made comes with some sort of tech debt.</p>
<p>Deadlines rarely align with the amount of time needed to complete work, and so technical compromises are made along the way. There&#8217;s a short-term tradeoff to get something working initially. The developer knows the lifetime of the solution and accepts that he or she will have to go back and create the longer-term solution later on. While those looking in from the outside might consider this to be sloppy engineering, it&#8217;s actually what allows products to be released on time. And also how tech debt accumulates.</p>
<p>Tech debt doesn&#8217;t show up on any product roadmap and so developers frequently try to address it as they&#8217;re working on other features. In some organizations, a savvy manager may be able to buy the developers some time pay down their tech debt, but that is the exception more than the rule. Those making business decisions typically don&#8217;t like giving time for paying tech debt because, in their mind, the work isn&#8217;t resulting in any new features. Why should they give you time to work on something when the end result isn&#8217;t a new feature?</p>
<p>In the worst case, tech debt can accumulate to the point where the web application is destined to fail. A classic tech debt issue is scalability. Initially, the goal is to get the web application up and running so that anyone can use it. Decisions are made to allow that to happen. But an app that can handle 100 users isn&#8217;t built the same way as an app to handle 1,000,000 users. In the back of the developers&#8217; minds are a list of things that need to happen in order to scale out: hit the database less, implementing several layers of caching, reduce the size of responses, figure out a faster way to process orders, and so on.</p>
<p>Just like monetary debt, tech debt is best dealt with before it gets too large and overwhelming. Regularly tending to tech debt is a process I like to call code hygiene. If you don&#8217;t go to the dentist for ten years and then finally go, chances are you&#8217;ll be in for a nasty surprise by not practicing proper dental hygiene. Code hygiene is the same. Keeping on top of your tech debt means regularly going in and addressing what you can with the time available. Good code hygiene means regularly:</p>
<ol>
<li><strong>Deleting unused code</strong> &#8211; I always say that any day you can delete multiple lines of code is a good day, and one where you earned your paycheck. Unused code shouldn&#8217;t be allowed to live in a codebase because, just like bacteria, all it needs is one opening to cause a big problem. If you suspect code isn&#8217;t being used, verify and then remove it. Don&#8217;t make a note to do it later, thus creating more tech debt, do it immediately. Less code means less to go wrong and faster builds and deployments.</li>
<li><strong>Refactor code</strong> &#8211; The time to refactor is as soon as you notice a problem. Don&#8217;t allow sloppy or bad code to remain in the code base. Code has a way of duplicating itself without warning. New developers come in looking for an example, find bad code, copy it, and now you have two pieces of bad code instead of one. That&#8217;s more tech debt. Make sure that all code you check in is worthy of being copied to prevent future tech debt. When you&#8217;re building off of existing code, make sure to include some time in your estimates for refactoring.</li>
<li><strong>Rewrite code</strong> &#8211; It&#8217;s rare for developers to be able to rewrite something from scratch, but it&#8217;s a necessary part of code hygiene. Good code should be able to run for five years without being rewritten; bad code needs to be rewritten as soon as possible. You should always try to refactor first, but if that fails, it&#8217;s time to rewrite. Making the business case for rewriting is difficult, but if you can tie the rewrite to a new feature, you have a better chance of getting the time.</li>
</ol>
<p>Technical debt is a part of every project, and one that needs to be better understood by all parties involved. Building time into every release for code hygiene is a good idea and can take many forms: bug bashes, where everyone takes a day or two and just works on bugs, engineering-driven features, which are features of the platform rather than end-user features, and code reviews, where engineers inspect each other&#8217;s code, are all good practices to have on the team to ensure tech debt doesn&#8217;t get out of control.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=UT2oSbBaZGk:kKAjYawNf8Y:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=UT2oSbBaZGk:kKAjYawNf8Y:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=UT2oSbBaZGk:kKAjYawNf8Y:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=UT2oSbBaZGk:kKAjYawNf8Y:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=UT2oSbBaZGk:kKAjYawNf8Y:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=UT2oSbBaZGk:kKAjYawNf8Y:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/UT2oSbBaZGk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/02/22/understanding-technical-debt/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/02/22/understanding-technical-debt/</feedburner:origLink></item>
		<item>
		<title>Book review: The Art of Readable Code</title>
		<link>http://feedproxy.google.com/~r/nczonline/~3/unr0eJAGXuU/</link>
		<comments>http://www.nczonline.net/blog/2012/02/13/book-review-the-art-of-readable-code/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 21:54:06 +0000</pubDate>
		<dc:creator>Nicholas C. Zakas</dc:creator>
				<category><![CDATA[Book Reviews]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Maintainability]]></category>
		<category><![CDATA[Readability]]></category>

		<guid isPermaLink="false">http://www.nczonline.net/blog/?p=2877</guid>
		<description><![CDATA[When I first proposed my upcoming book, Maintainable JavaScript, I was offered the chance to review a book on a similar topic. The Art of Readable Code by Dustin Boswell and Trevor Foucher is a book after my own heart. While not strictly about JavaScript, this book delves into the little explored region of code [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.com/Art-Readable-Code-Dustin-Boswell/dp/0596802293?tag=nczonline-20"><img src="http://www.nczonline.net/blog/wp-content/uploads/2012/02/artof.jpg" alt="The Art of Readable Code Book Cover" align="right" width="318" height="417"/></a>When I first proposed my upcoming book, <cite>Maintainable JavaScript</cite>, I was offered the chance to review a book on a similar topic. <cite><a href="http://www.amazon.com/Art-Readable-Code-Dustin-Boswell/dp/0596802293?tag=nczonline-20">The Art of Readable Code</a> by Dustin Boswell and Trevor Foucher is a book after my own heart. While not strictly about JavaScript, this book delves into the little explored region of code hygiene like no other. I&#8217;m a big believer in the value of readable, maintainable code, and this book presents some great techniques for overall code readability regardless of language.</p>
<p>The book starts by talking about time until understanding, and how important that is for programmer productivity.Of course, you can&#8217;t even begin to start working with code until you understand it. The authors talk about just how important this is on a large development team where you have multiple people working on the same code at different times in the project. This is something I&#8217;ve been preaching for a while in my talks, and I&#8217;m glad that </cite><cite>The Art of Readable Code follows the same reasoning.</p>
<p>The first few chapters go into specifics of naming and how naming can really help in the understanding of code. Little tidbits about how naming affects our understanding are included, as well as some of the questions around naming such as how long the name should be. The difference between a naming variables, functions, and Constance is discussed, along with some great examples of how to naming should meet developer expectations. For example, a method beginning with the word &#8220;get&#8221; this often assumed to be a fast getter method that doesn&#8217;t do much processing. However, if such a method ends up doing expensive processing and taking a long time, this gets confusing for developers. I had never thought about method naming in this way, but it makes a lot of sense.</p>
<p>The next few chapters focus on comments and when to use them. This is another topic that&#8217;s very close to my heart, as I generally feel like people don&#8217;t use comments enough. These chapters have some great examples of both bad and good comments. If we all just commented a little more, dealing with the world&#8217;s code would be much easier.</p>
<p>Other topics in the book include how to properly structure flow control statements for best understanding, how to properly break down large chunks of code, and how to re-factor for better readability. Most of the topics are accompanied by small comics that help to get the point across and give some welcome levity to the discussion.</p>
<p>If you care about writing maintainable code, whether it be in JavaScript or any other language, this book is a great read. Those who never stopped to consider how their coding style affects the maintainability of their code should definitely pick up this book to get a nice overview of the issues. Every reader will appreciate how the authors continually say that there is no one right way to do anything, it&#8217;s all based on the context of your code and your team. I found myself disagreeing with some of the approaches in the book, but with a complete understanding of why the authors would choose that particular approach. But that&#8217;s okay, as it shows an important concept in maintainable code: it&#8217;s much more important for everyone to be doing things one way than it is for everyone to be doing things your way.</cite></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nczonline?a=unr0eJAGXuU:HLoM1tUPTfg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nczonline?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=unr0eJAGXuU:HLoM1tUPTfg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nczonline?i=unr0eJAGXuU:HLoM1tUPTfg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=unr0eJAGXuU:HLoM1tUPTfg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nczonline?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nczonline?a=unr0eJAGXuU:HLoM1tUPTfg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/nczonline?i=unr0eJAGXuU:HLoM1tUPTfg:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/nczonline/~4/unr0eJAGXuU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.nczonline.net/blog/2012/02/13/book-review-the-art-of-readable-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.nczonline.net/blog/2012/02/13/book-review-the-art-of-readable-code/</feedburner:origLink></item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Served from: nczonline.net @ 2012-05-25 11:16:51 -->

