<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Tom Dale</title>
	<atom:link href="http://tomdale.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://tomdale.net</link>
	<description>Make decisions so your users don&#039;t have to.</description>
	<lastBuildDate>Mon, 14 May 2012 15:57:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Our Approach to Routing in Ember.js</title>
		<link>http://tomdale.net/2012/05/ember-routing/</link>
		<comments>http://tomdale.net/2012/05/ember-routing/#comments</comments>
		<pubDate>Mon, 14 May 2012 15:57:45 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=602</guid>
		<description><![CDATA[The URL is an important strength that the web has over native apps. In web apps, the URL goes beyond just being a static reference to the location of a document on a server. The best way to think of it is as the serialization of the application’s current state. As the user interacts with [...]]]></description>
			<content:encoded><![CDATA[<p>The URL is an important strength that the web has over native apps. In web apps, the URL goes beyond just being a static reference to the location of a document on a server. The best way to think of it is as the serialization of the application’s current state. As the user interacts with the application, the URL should update to reflect what the user is seeing on their screen.</p>

<p>In most applications, state is tracked in an ad hoc way. To answer the question <em>&#8220;What is the current state of the application?&#8221;</em> you must synthesize several different properties (usually stashed away on different controllers) to arrive at an answer. If there are bugs in your application, it is possible to get into a conceptually broken state. For example, imagine you have an  <code>isAuthenticated</code> property that is <code>true</code> but there is no <code>currentUser</code> property. How did you get into this state? Diagnosing these kinds of bugs is difficult. And more importantly, serializing that state in a sane way is basically impossible, because it’s scattered across the application.</p>

<p>Ember.js&#8217; implementation of state charts solves these issues nicely. Using <code>Ember.StateManager</code>, you describe your application as a hierarchical tree of objects—one object per conceptual state. Because you explicitly enumerate the possible states, it is impossible to be in an unknown state. And if you try to perform an action in a state that doesn&#8217;t support it, an exception is raised immediately, making it easy to diagnose and debug the problem.</p>

<p>It also means that we can easily serialize the state of your application on demand. Assuming you model your application’s behavior using a state manager, we can map the state hierarchy to a URL, and update it as you navigate through the hierarchy.</p>

<p>This is an important departure from how most other web frameworks handle routing. They invert the model; the URL is the source of truth for the current state of the application. To change states (for example, to show a different view), you hardcode the URL into your application. If I want to display a photo with an ID of 1, I must synthesize the URL <code>'/photo/1'</code> and send it to my router.</p>

<p>This approach is not ideal for several reasons.</p>

<p>First, it couples your URLs to your application code. Changing segment names means you have to go through your entire app and update the hardcoded strings. It also requires that, if you want to enter a new state, you must go consult the router to be reminded what the particular URL is. Breaking encapsulation this way quickly leads to out-of-control code that is hard to maintain.</p>

<p>You’re in for an especially painful experience if you later need to change the hierarchy of your URLs. For example, imagine you have a blog app that displays different kinds of media. You have URLs like this:</p>

<ul>
<li><code>/posts/my-favorite-dog-breeds</code>
</li><li><code>/photos/1234</code>
</li><li><code>/audio/sweet-child-o-mine.mp3</code>
</li></ul>

<p>Your app gets so popular that you decide to add multiple blogs:</p>

<ul>
<li><code>/blogs/tom/posts/my-favorite-dog-breeds</code>
</li><li><code>/blogs/wycats/audio/a-whole-new-world.mp3</code>
</li></ul>

<p>You now need to audit every URL in your application! With Ember&#8217;s approach, it&#8217;s as simple as adding a route property to the parent state to have it start appearing in the URL. Because state changes are triggered by events being sent to your state manager by your views (instead of them routing to a specific URL), nothing in your view code changes.</p>

<p>The other problem with describing state in terms of URLs is that there is a cumbersome and pointless serialization step. In my JavaScript, I am dealing with controllers and model objects. Having to turn them into a string form just to get them to interact is brittle and unnecessary.</p>

<p>To use the photo example from above, which one of these is nicer?</p>

<p><pre>stateManager.send('showPhoto', user, photo);</pre></p>

<p><pre>
var url = '#/user/' + user.get('id') + '/photo/' + photo.get('id');
router.route(url);
</pre></p>

<p>Having multiple sources of truth in any application quickly leads to chaos. One of the primary benefits of Ember.js is that it ruthlessly moves truth about your application state out of the DOM and into JavaScript. The DOM is always just a reflection of the current truth in JavaScript.</p>

<p>The work we&#8217;re doing on routing in Ember.js will have a similar effect on keeping truth out of the URL. The URL becomes just a reflection of the current truth in JavaScript. Because state managers allow you define your application state in an encapsulated and semantically rich way, changing how your URLs are built is as easy as changing a few properties on the state objects.</p>

<p>For a more concrete description of how routing ties into Ember&#8217;s state managers, see <a href="https://gist.github.com/2679013">Yehuda&#8217;s gist, which includes code samples</a>. This work is currently happening on Ember&#8217;s <code>routing</code> branch, but we hope to merge it into master soon.</p>

<p>I&#8217;m really excited about this feature. We&#8217;ve been thinking about this problem for a while now and it&#8217;s satisfying to finally be able to start working on it. I think that explicitly modeling application state using objects is a very exciting and powerful technique, and getting routing &#8220;for free&#8221; by doing it makes it a no-brainer.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2012/05/ember-routing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Best Practices Exist for a Reason</title>
		<link>http://tomdale.net/2012/04/best-practices-exist-for-a-reason/</link>
		<comments>http://tomdale.net/2012/04/best-practices-exist-for-a-reason/#comments</comments>
		<pubDate>Sun, 29 Apr 2012 03:54:18 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=593</guid>
		<description><![CDATA[If you&#8217;ve ever used node.js, you&#8217;ve probably also used Isaac Schlueter&#8217;s npm, the node package manager. By maintaining a central repository to which authors can quickly publish their JavaScript modules, npm has made it easy to get started building node apps and its popularity has exploded over the past year. Unfortunately, two months ago, the [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever used node.js, you&#8217;ve probably also used Isaac Schlueter&#8217;s npm, the node package manager. By maintaining a central repository to which authors can quickly publish their JavaScript modules, npm has made it easy to get started building node apps and its popularity has exploded over the past year. Unfortunately, two months ago, <a href="https://gist.github.com/2001456">the hashed passwords of all npm accounts were leaked.</a> npm uses CouchDB for its backend, and the default security model is to grant administrator access to all databases, but only when connections originate from the same machine. It appears that in this case, the CouchDB server was made accessible to the world over HTTP with the default access settings left in place.</p>

<p>In retrospect, it&#8217;s obviously a dumb mistake, but the same kind of dumb mistake you or I or anyone ten times smarter than us could make; whether because we&#8217;re sick or tired or under pressure or simply because we&#8217;re using a new system that we&#8217;ve never used before.</p>

<p>The community&#8217;s reaction to the security leak was relatively forgiving, and rightly so. After all, npm is a community project that was created and is maintained for free, and we all benefit from the enormous amount of time and energy that Isaac and the other npm contributors have generously donated.</p>

<p>And yet, npm is no longer just a hobby project. Thousands of people rely on it to provide services to themselves, their friends, and to paying customers. Additionally, when it comes to security, there can be repercussions far beyond the original breach. Anyone who created an npm account and used the same password for another web service is potentially at risk.</p>

<p>So this is the eternal balancing act that open source maintainers (and, indeed, many startups) must face: limited time and resources for building, securing and maintaining systems that will be used by hundreds, thousands, or even millions of people.</p>

<p>Which is why I have been so saddened and, yes, angry, about the recent trend in the JavaScript community; to throw away the best practices we have spent a long time honing in what, to my eyes, is an act of machismo; a revolt against good engineering practices for the sake of revolting rather than to make the world a better place.</p>

<p>As a community we&#8217;ve advocated for these things precisely because most comers to JavaScript are not us, not as invested in the language and the ecosystem as us; but rather have been thrown at some problem because all of a sudden it&#8217;s 2012 and not writing JavaScript is no longer an option. They are not JavaScript developers per se; they are Java developers or Ruby developers or .NET developers or any of the thousands of possible kinds of developers who are now thrust into this unfamiliar world where JavaScript is the substrate that holds the web together.</p>

<p>Here&#8217;s the thing about best practices: at the point at which you become sufficiently experienced, you understand why they are good and so can choose to not use them as the situation allows. Your understanding of the language or the ecosystem or the particular problem at hand has allowed you to view the problem from the same vantage point of the people that came up with those best practices; and so you are free to discard them if the situation merits.</p>

<p>But until your understanding has crystallized, not following those best practices can cost you hours of wasted time tracking down bugs that didn&#8217;t have to otherwise exist. But <strong>writing code before you have an expert-level understanding is okay</strong>. It&#8217;s okay because it is reality and there is nothing you can do to change the fact that people with a very tenuous grasp of these technologies are being thrown at hard problems that they will solve one way or another.</p>

<p>Which is why I have to admit that my blood boiled when I read <a href="http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding">Isaac&#8217;s post about automatic semicolon insertion</a>. I don&#8217;t want to re-litigate the semicolon debate because I think we were all tired of it before it even began. What I want to highlight is a general attitude that I find very disappointing:</p>

<blockquote>
I am sorry that, instead of educating you, the leaders in this language community have given you lies and fear.
</blockquote>

<p>By couching it in these terms, it implies that anyone who follows best practices has given in to &#8220;lies and fear!&#8221; Who wants to be swayed by that?</p>

<p>A more generous interpretation is that the leaders Isaac accuses of spreading lies and fear know that the reality is that you have a month to ship a JavaScript app, and asking you to understand the ECMAScript spec is not reasonable. (Because it&#8217;s not just automatic semicolon insertion, right? It&#8217;s <code>this</code> binding and anonymous functions and a million other features of JavaScript that confuse newcomers.)</p>

<p>We can&#8217;t front-load complexity and let people sort it out. That way lies madness. We must distill the rules down so that people can be effective, and help them along their journey towards JavaScript mastery. It&#8217;s a learning curve, not a learning cliff.</p>

<p>So I have to vehemently disagree with this statement in Isaac&#8217;s post:</p>

<blockquote>
If you don’t understand how statements in JavaScript are terminated, then you just don’t know JavaScript very well, and shouldn’t write JavaScript programs professionally without supervision…
</blockquote>

<p>I find this staggeringly condescending, but maybe it&#8217;s just my reading of it. But even if my reading is wrong, it rejects reality. Isaac knows this because the npm team deployed a misconfigured CouchDB instance to production <strong>and it&#8217;s not their fault.</strong> To suggest they needed &#8220;supervision&#8221; is absurd. They were not expert-level CouchDB users but they had a job to do so they picked the tool and went to town. This is a CouchDB failing; because the best practices were not made clear enough or the default settings were not strict enough.</p>

<p>So let&#8217;s learn from our mistakes and realize that the bulk of JavaScript developers are not experts. Let&#8217;s stop tearing down the hard work our predecessors have done to shepherd JavaScript from a toy language to the language that is revolutionizing how the web applications are built. Let&#8217;s embrace good engineering practices and have the sense to know when to ignore them, and not abandon them altogether to prove how smart we are. We&#8217;re all in this together.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2012/04/best-practices-exist-for-a-reason/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>Ember.js Resources</title>
		<link>http://tomdale.net/2012/02/ember-js-resources/</link>
		<comments>http://tomdale.net/2012/02/ember-js-resources/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 18:22:44 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=578</guid>
		<description><![CDATA[I come across a lot of really interesting links related to Ember.js, but often don&#8217;t have anywhere useful to put them, or don&#8217;t really know how to describe the thread that holds them all together. So here is my linkdump post, which I will update as I remember things, that contains useful stuff for Ember [...]]]></description>
			<content:encoded><![CDATA[<p>I come across a lot of really interesting links related to Ember.js, but often don&#8217;t have anywhere useful to put them, or don&#8217;t really know how to describe the thread that holds them all together. So here is my linkdump post, which I will update as I remember things, that contains useful stuff for Ember developers.</p>

<p><a href="https://github.com/emberjs/todos">Ember.js Todos</a>
<br />
Sample todo application. Particularly useful for its heavily-commented Assetfile. Great starting point if you&#8217;d like to know how to use Rake::Pipeline together with Ember.</p>

<p><a href="http://gmoeck.github.com/2011/03/10/sproutcore-mvc-vs-rails-mvc.html">SproutCore MVC vs. Rails MVC</a><br />
Written back in the SproutCore 2.0 days, Greg Moeck&#8217;s seminal post describes how, despite the same name, Rails&#8217; concept of MVC differs radically from MVC systems like SproutCore, Ember.js, and Cocoa.</p>

<p><a href="https://github.com/interline/ember-skeleton">Ember Skeleton</a><br />
Boilerplate for starting a new Ember.js project, using Rake::Pipeline to assemble and serve your files.</p>

<p><a href="http://www.cerebris.com/blog/2012/01/24/beginning-ember-js-on-rails-part-1/">Beginning Ember.js on Rails</a><br />
Dan Gebhart&#8217;s three-part tutorial, which eases you gently into using Ember.js with a Rails backend. Resources are loaded with <a href="https://github.com/cerebris/ember-rest">Ember REST</a>, and assets are managed with Rails&#8217; asset pipeline.</p>

<p><a href="http://yehudakatz.com/2011/06/11/using-sproutcore-2-0-with-jquery-ui/">Using SproutCore 2.0 with jQuery UI</a><br />
Yehuda&#8217;s article on using jQuery UI with what was then SproutCore 2.0. Note that, if following along with the code samples, there are a few changes that you will need to make that are pointed out in the comments at the bottom. While useful specifically for people wanting to use jQuery UI, the article is more broadly useful as it serves as a template for anyone who wants to write a bridge between Ember.js and non-bindings-aware JavaScript libraries.</p>

<p>More soon…</p>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2012/02/ember-js-resources/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Dizzying But Invisible Depth</title>
		<link>http://tomdale.net/2012/02/dizzying-but-invisible-depth/</link>
		<comments>http://tomdale.net/2012/02/dizzying-but-invisible-depth/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 06:37:20 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=573</guid>
		<description><![CDATA[Jean-Baptiste Queru&#8217;s remarkable piece on the sheer amount of abstraction mankind has built to be able to load the Google homepage: For non-technologists, this is all a black box. That is a great success of technology: all those layers of complexity are entirely hidden and people can use them without even knowing that they exist [...]]]></description>
			<content:encoded><![CDATA[<p>Jean-Baptiste Queru&#8217;s remarkable piece on the sheer amount of abstraction mankind has built to be able to load the Google homepage:</p>

<blockquote>For non-technologists, this is all a black box. That is a great success of technology: all those layers of complexity are entirely hidden and people can use them without even knowing that they exist at all. That is the reason why many people can find computers so frustrating to use: there are so many things that can possibly go wrong that some of them inevitably will, but the complexity goes so deep that it&#8217;s impossible for most users to be able to do anything about any error.</blockquote>

<p><a href="https://plus.google.com/112218872649456413744/posts/dfydM2Cnepe">Dizzying but invisible depth</a></p>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2012/02/dizzying-but-invisible-depth/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AMD is Not the Answer</title>
		<link>http://tomdale.net/2012/01/amd-is-not-the-answer/</link>
		<comments>http://tomdale.net/2012/01/amd-is-not-the-answer/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 22:50:33 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=548</guid>
		<description><![CDATA[Every so often, we get requests to make Ember.js support AMD (asynchronous module definition). Until today, I had yet to hear anyone articulate why the advantages outweighed the (in my opinion) many disadvantages. Then, James Burke wrote an article called Simplicity and JavaScript modules that has so far done the best job outlining why AMD is [...]]]></description>
			<content:encoded><![CDATA[<p>Every so often, we get requests to make Ember.js support <a href="https://github.com/amdjs/amdjs-api/wiki/AMD">AMD (asynchronous module definition)</a>. Until today, I had yet to hear anyone articulate why the advantages outweighed the (in my opinion) many disadvantages. Then, James Burke wrote an article called <a href="http://tagneto.blogspot.com/2012/01/simplicity-and-javascript-modules.html">Simplicity and JavaScript modules</a> that has so far done the best job outlining why AMD is good. However, I disagree with many of the assumptions and find many of the arguments outright contradictory. So, while James is both smart and I&#8217;m sure good-looking (and I agree with his comments on CommonJS), here are the reasons I think he is wrong about AMD.</p>

<h3>Build Tools Are Okay</h3>

<blockquote>However, for those of us who came from Dojo, requiring a server tool or compile step to just develop in JS was a complication. I&#8217;m going to mangle Alex Russell&#8217;s quote on this, but &#8220;the web already has a compile step. It&#8217;s called Reload&#8221;.</blockquote>

<p>I have a lot of respect for Alex but, if this is his current opinion, he&#8217;s wrong. The app development world of the Dojo era is different from the world of today, and it&#8217;s important that we are driven by current realities rather than stale institutional knowledge. Every serious application development environment in the world has a build step. If you are making a small application, then fine, I agree you don&#8217;t need build tools. But you probably don&#8217;t need AMD or a script loader, either.  If your app is truly simple, you will be fine with adding a few &lt;script&gt; tags to your page. I&#8217;m involved in several large web application projects right now and universally they use a build procedure of some kind. CoffeeScript compilation and minification are two examples of legitimate reasons to have a build step. Packaging your modules is fine too.</p>

<h3>Many HTTP Requests</h3>

<p>AMD expects every module to be contained in a separate file. As web app development gets more rigorous, developers want to be able to organize their files in the same way they might in Ruby or Cocoa. For example, all of the projects I&#8217;m working on easily have hundreds of files. Each view is a separate file, each template is a separate file, each controller is a separate file, and so on. With AMD, each additional file means additional HTTP overhead. But more importantly, many users are now on high-latency but high-bandwidth wireless connections. Minimizing the number of trips to the server is important. James addresses this in his blog post:</p>

<blockquote>Loading individual modules piecemeal is a <em>terrifically</em> inefficient way to built a website. Because of this, there&#8217;s the great RequireJS optimizer, which will turn your modules into ordinary packages.</blockquote>

<p>But wait, I thought we were just arguing that build tools are bad? Here&#8217;s the thing: if your app is simple, you don&#8217;t need build tools <em>or</em> module loading. If your app is more sophisticated, you&#8217;ll need both; so why not let the build tools handle the packaging for you? AMD proponents also argue that serving files individually makes it easier to debug. We did this in the SproutCore 1.0 days and, though it was extremely slow in development (perhaps because our HTTP server was single-threaded), it was effective. However, enough browsers support the sourceURL convention that in our current projects we just include a function like this:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">  <span style="color: #003366; font-weight: bold;">function</span> appendSourceURL<span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> path<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> data <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot; //@ sourceURL=&quot;</span><span style="color: #339933;">+</span>path<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>


<h3>Too Much Ceremony</h3>

<p>AMD requires you to wrap all of your code inside an anonymous function that is passed to the define method:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">define<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'dep1'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'dep2'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>dep1<span style="color: #339933;">,</span> dep2<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">//Define the module value by returning a value.</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p lang="javascript">In my opinion, having to write this out for every file <em>sucks</em>. I prefer to call <code>require</code> for each dependency. Perhaps it&#8217;s a trivial difference, but removing a dependency is as easy as deleting a line and adding a new dependency means adding a new line of code. It&#8217;s less error-prone than editing an array of strings.</p>

<p lang="javascript">You can achieve a similar syntax with AMD, like this:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">define<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
 require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ember.js'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 window.<span style="color: #660066;">MyApp</span> <span style="color: #339933;">=</span> Ember.<span style="color: #660066;">Application</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p>But at that point, why bother with loading a large AMD script loader? We use an <a href="https://github.com/wycats/minispade/blob/master/lib/main.js">implementation of a script loader that is under 50 lines of code</a>.</p>

<h3>The Alternative</h3>

<p>What we&#8217;ve been using for our projects is a system that takes the source code for each file and wraps it as a string, as described by Tobie Langel in his post <a href="http://calendar.perfplanet.com/2011/lazy-evaluation-of-commonjs-modules/">Lazy evaluation of CommonJS modules</a>. All of the source code is downloaded in one HTTP request (great for high-latency 3G connections) and is saved in memory as a string so parsing is fast. Those strings are saved in a hash keyed on each individual file&#8217;s name. If you were to look at our application.js file, you would see something similar to this:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Files <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
Files<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'main.js'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;require(<span style="color: #000099; font-weight: bold;">\&quot;</span>controllers/app_controller.js<span style="color: #000099; font-weight: bold;">\&quot;</span>);&quot;</span><span style="color: #339933;">;</span>
Files<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'controllers/app_controller.js'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;alert(<span style="color: #000099; font-weight: bold;">\&quot;</span>Hello world!<span style="color: #000099; font-weight: bold;">\&quot;</span>);&quot;</span><span style="color: #339933;">;</span></pre></div></div>


<p>The main JavaScript file is executed, and dependencies are resolved at runtime. This allows you to conditionally evaluate code based on the execution environment. For example, imagine you had a file that defined keyboard shortcuts. You could decide not to pay the parsing cost for that file if you detected that you were running on a touch platform.</p>

<p>We also have a system for packaging up many files into a single module, which can be loaded lazily. This helps us get the initial payload within the limits of mobile device&#8217;s cache limits.</p>

<p>The best part of this system is that, as an application developer, there is very little ceremony involved. If I need some functionality, I just place a <code>require</code> statement. If it has already been loaded, the <code>require</code> is a no-op. I make this argument a lot, but going from &#8220;a little friction&#8221; to &#8220;no friction&#8221; often makes the difference between good habits and bad habits. In this case, I can open a new file and start typing code, instead of worrying about setting it up as a module.</p>

<p>AMD has many features, but I think that the extra markup and complex loaders needed to support it outweighs its benefits. Out-of-the-box it is not ready for production, and needs build tools to make it truly useful. If build tools are required anyway, a much simpler solution should fit most developers&#8217; needs.</p>

<p>I am looking forward to your blog post pointing out the flaws in my argument and excoriating me for making a fool of myself in public.</p>

<p><em>A very sincere thank you to James Burke, Tim Branyen and Yehuda Katz for reviewing this post and helping me better understand AMD. Please consider this a <a href="http://www.codinghorror.com/blog/2008/05/strong-opinions-weakly-held.html">strong opinion, weakly held</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2012/01/amd-is-not-the-answer/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Tilde&#8217;s Pairing Setup</title>
		<link>http://tomdale.net/2012/01/tildes-pairing-setup/</link>
		<comments>http://tomdale.net/2012/01/tildes-pairing-setup/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 19:28:50 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=521</guid>
		<description><![CDATA[Yehuda Katz and I spend the majority of our time pair programming on client projects and on our open source projects like Ember.js. As in any profession, it&#8217;s important to be &#8220;foaming at the mouth crazy&#8221; about your tools. Since Tilde moved into our new offices, we&#8217;ve finally put together what I think is our dream [...]]]></description>
			<content:encoded><![CDATA[<p>Yehuda Katz and I spend the majority of our time pair programming on client projects and on our open source projects like Ember.js. As in any profession, it&#8217;s important to be <a href="http://www.randsinrepose.com/archives/2009/11/02/the_foamy_rules_for_rabid_tools.html">&#8220;foaming at the mouth crazy&#8221; about your tools</a>.</p>

<p>Since Tilde moved into our new offices, we&#8217;ve finally put together what I think is our dream setup that I wanted to share.</p>

<p><a href="http://tomdale.net/wp-content/uploads/2012/01/pairing_setup1.jpg"><img class="aligncenter size-large wp-image-525" title="Pairing Setup" src="http://tomdale.net/wp-content/uploads/2012/01/pairing_setup1-1024x768.jpg" alt="" width="500" /></a></p>

<h2>Hardware</h2>

<p>The crown jewel of the setup is a brand new 3.4GHz 27&#8243; iMac with a 256GB SSD and 1TB hard drive. This thing absolutely screams, and is a joy to use. On our last pairing setup (a Mac mini with a 5400rpm hard drive), we would cringe when we had to bootup VMware to test Internet Explorer. On this thing, you can&#8217;t even tell that you&#8217;re running Windows virtualized. It&#8217;s insanely responsive.</p>

<p>We prefer being able to face each other, and modeled our setup after <a href="http://pivotallabs.com/users/jsusser/blog/articles/1505-pairing-tete-a-tete">Josh Susser&#8217;s post about his pairing setup at Pivotal</a>. Sitting side-by-side has always felt awkward to me; and the ability to easily have a face-to-face conversation is critical. This also allows us to more easily deliver high-fives after slaying a particularly hard bug.</p>

<p>We orient our desks at a right angle, and plug an external 27&#8243; Thunderbolt Display into the iMac with mirroring turned on. This allows us both to see the same content at the same resolution. We both get a Bluetooth keyboard, and Yehuda uses a Magic Trackpad while I prefer the Magic Mouse. The ability to have your own space to keep drinks and other personal belongings is a big win. I can also customize the keyboard to my liking, since I prefer mapping Caps Lock to the Control key and Yehuda hates it. When we&#8217;re not pairing, we can use either the Thunderbolt Display or the iMac as external monitors for our laptops. The display also serves as a nice USB hub for charging iPhones or other devices.</p>

<p>Perhaps most critically, we hung the biggest whiteboard we could find on the wall next to our station. There are few problems a good whiteboard diagram can&#8217;t fix.</p>

<h2>Software</h2>

<p>Yehuda and I both use MacVIM with <a href="https://github.com/carlhuda/janus">Janus</a> as our editor. One major point of contention was file navigation: I prefer NERDtree and Yehuda prefers <a href="https://github.com/alloy/macvim">alloy&#8217;s fork of MacVim with a native file browser</a>. (The native file browser drives me absolutely fucking crazy because I can&#8217;t navigate using just the keyboard; I have to pick up the mouse.)</p>

<p>We almost came to blows over this, but now that we have a 27&#8243; display, we agreed to just use both.</p>

<div id="attachment_526" class="wp-caption aligncenter" style="width: 510px"><a href="http://tomdale.net/wp-content/uploads/2012/01/marital_bliss.png"><img class="size-large wp-image-526" title="Marital Bliss" src="http://tomdale.net/wp-content/uploads/2012/01/marital_bliss-1024x552.png" alt="" width="500" height="270" /></a><p class="wp-caption-text">Marital Bliss</p></div>

<p>&nbsp;</p>

<p>We use zsh with <a href="https://github.com/robbyrussell/oh-my-zsh">oh-my-zsh</a>. Our shell displays both the current git branch (if applicable), as well as the current Ruby version. Both of these have saved us countless hours of hair-pulling. We manage Ruby versions with Wayne Seguin&#8217;s indispensable <a href="http://beginrescueend.com/">rvm</a>, the Ruby version manager.</p>

<p><a href="http://tomdale.net/wp-content/uploads/2012/01/terminal.png"><img class="aligncenter size-large wp-image-540" title="terminal" src="http://tomdale.net/wp-content/uploads/2012/01/terminal-1024x672.png" alt="" width="500" /></a></p>

<p>For communcation, we use Propane to hang out in various Campfire rooms and iChat to log on to AIM, where we have separate pair accounts so that there is no feeling of invaded privacy. We use Dropbox and Lion&#8217;s AirDrop feature to shuttle files back and forth, and use the surprisingly powerful speakers in the Thunderbolt Display to do our standups via Skype.</p>

<p>I couldn&#8217;t be happier with our setup. If you haven&#8217;t tried pairing, I recommend it; while it sometimes feels slower, you avoid many of the obvious mistakes that one can make when spending hours in isolation. I also think that the software you write tends to be better if it&#8217;s constantly being sanity-checked by someone else.</p>

<p>If you have your own pairing setup, what improvements would you make to ours?</p>

<p><b>Edit</b>: I forgot the most important component of a successful pairing setup:</p>

<p><a href="http://tomdale.net/wp-content/uploads/2012/01/bar.jpg"><img src="http://tomdale.net/wp-content/uploads/2012/01/bar-1024x768.jpg" alt="" title="Tilde Bar" width="500" class="aligncenter size-large wp-image-544" /></a></p>

<p><b>Edit 2</b>: Updated to clarify that the second display is mirrored.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2012/01/tildes-pairing-setup/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>An Uphill Battle</title>
		<link>http://tomdale.net/2011/05/an-uphill-battle/</link>
		<comments>http://tomdale.net/2011/05/an-uphill-battle/#comments</comments>
		<pubDate>Sat, 21 May 2011 20:46:09 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=444</guid>
		<description><![CDATA[Where is the web&#8217;s Loren Brichter?1 Why does it take big teams, big budgets, and long timelines to deliver web apps that have functionality and UI that approaches that of an iPhone app put together by one or two people? If you&#8217;re a developer who is obsessive about building a quality user experience, you are most likely [...]]]></description>
			<content:encoded><![CDATA[<p>Where is the web&#8217;s Loren Brichter?<sup><a href="http://tomdale.net/2011/05/an-uphill-battle/#footnote_0_444" id="identifier_0_444" class="footnote-link footnote-identifier-link" title="Loren Brichter&amp;#8217;s company, atebits, created both Tweetie for Mac and Tweetie for iOS, which were acquired by Twitter.">1</a></sup> Why does it take big teams, big budgets, and long timelines to deliver web apps that have functionality and UI that approaches that of an iPhone app put together by one or two people?</p>

<p>If you&#8217;re a developer who is obsessive about building a quality user experience, you are most likely to create an iOS application. One reason is that Cocoa is able to operate at a higher level of abstraction than raw web primitives. It means that iOS developers can think more about how their UI or features should work, instead of how they should be implemented. The human brain is like a buffer: at a certain point, every new concept pushes something else off the other end. For web developers, buffer overflow is common as they grapple with cross-browser bugs or APIs that are openly design-by-committee.</p>

<p><strong>The web needs better abstractions</strong>. There are, however, only a limited number of abstractions you can implement in under 5k of code. I&#8217;m sensitive to cultivating an attitude in the community that the only valuable problems worth solving are those that can be done under 5k (or 10k, or 20k, or…). I will take my share of the blame, and admit that many frameworks that tried to take on large problems ended up out-of-touch and crufty.</p>

<p>The web won&#8217;t have a singular answer, and that&#8217;s fine. But we have to avoid fostering a culture where people are afraid to tackle hard problems because they&#8217;ll be seen as architecture astronauts. We shouldn&#8217;t let the mistakes of the past make us timid about learning and moving forward.</p>

<p style="text-align: center;">***</p>

<p>Yesterday on Twitter, I posted:</p>

<blockquote>Just wanted to point out that Backbone is still listed on microjs.com, even though it&#8217;s &gt;5k if you count dependencies.</blockquote>

<blockquote>Which is fine; let&#8217;s just be upfront about the fact that microjs.com is more akin to the cool kids table than a useful directory.</blockquote>

<p>In retrospect, this came off crankier than I intended. Several people contacted me privately (and publicly!) and weren&#8217;t sure why I was making a stink over something that, to them, seemed trivial. And while in the scheme of things it <em>is</em> trivial, I think this arbitrary line in the sand we as a community have drawn is harmful to the future of the web.</p>

<p>I want the web to win. Everywhere.</p>

<p>So I want people to be aware of the abstractions we&#8217;re giving up to hit our 5k target. If some things get included that are over 5k, and other things get rejected that are under the 5k limit, it sends a very mixed message to new developers about what is possible. If we&#8217;re going to emphasize small codebases, let&#8217;s be honest about the limitations that entails.</p>

<p>If we don&#8217;t get our act together soon, proprietary platforms are going to become entrenched. Every new device that comes out is an opportunity that is ours to lose. The community has to figure out how we educate and recruit developers into the web fold. People will disagree with me about the best way to accomplish the task, and that&#8217;s great. But I&#8217;d like to compete on things like developer productivity and finished products, not insinuation that anything over a certain size is inherently unsuitable for the web.</p>

<p>It&#8217;s human nature that once we start assigning labels to things, we think about which side of the label we&#8217;re on. I think that positioning microlibraries as a separate &#8220;thing&#8221; is a bad idea. There are just tools that fall on different sides of the size spectrum.</p>

<p>Writing efficient code is important. But when we decide that certain web abstractions are a bridge too far, we&#8217;re actively discouraging precisely the developers that we need the most. When the next Loren Brichter comes along, I want to be able to say he or she is a web developer.</p>

<p><em>Thanks to Majd Taby and Yehuda Katz for reviewing this post. I tweet as <a href="http://www.twitter.com/tomdale">@tomdale</a> if you&#8217;d like more timely updates.</em></p>
<ol class="footnotes"><li id="footnote_0_444" class="footnote">Loren Brichter&#8217;s company, atebits, created both Tweetie for Mac and Tweetie for iOS, which were acquired by Twitter.</li></ol>]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2011/05/an-uphill-battle/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Imagine a Beowulf Cluster of JavaScript Frameworks</title>
		<link>http://tomdale.net/2011/04/imagine-a-beowulf-cluster-of-javascript-frameworks/</link>
		<comments>http://tomdale.net/2011/04/imagine-a-beowulf-cluster-of-javascript-frameworks/#comments</comments>
		<pubDate>Tue, 12 Apr 2011 06:56:57 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=417</guid>
		<description><![CDATA[Thomas Fuchs recently wrote about the advantages of using JavaScript micro-frameworks: I for one welcome our new micro-framework overlords—small frameworks and libraries that do one thing only, not trying to solve each and every problem, just using pure JavaScript to do it. Easy to mix and match, and to customize to your needs. He also [...]]]></description>
			<content:encoded><![CDATA[<p>Thomas Fuchs recently <a href="http://mir.aculo.us/2011/04/11/i-for-one-welcome-our-new-micro-framework-overlords/">wrote about the advantages of using JavaScript micro-frameworks</a>:</p>

<blockquote>I for one welcome our new micro-framework overlords—small frameworks and libraries that do one thing only, not trying to solve each and every problem, just using pure JavaScript to do it. Easy to mix and match, and to customize to your needs.</blockquote>

<p>He also pans &#8220;full-stack&#8221; frameworks:</p>

<blockquote>These libraries are HUGE, being 100+ kilobytes in code size, and even minified and gzipped they are pretty big. … A whopping 100% of sites or apps using these libraries don’t use all the features they provide.</blockquote>

<p>His argument sounds good, in theory. The idea that I can pick and choose among a number of well-written and focused JavaScript libraries to assemble the ultimate bespoke JavaScript environment seems very enticing indeed.</p>

<p>The golden rule of software, however, is that unless it is designed to work well together, it usually won&#8217;t. Mr. Fuchs has apparently never heard of <a href="http://en.wikipedia.org/wiki/Dependency_hell">dependency hell</a>. Dustin Diaz has done a great job of putting together many of these micro-frameworks with <a href="http://dustindiaz.com/ender">Ender.js</a>, but as a curator, <a href="https://twitter.com/ded/status/55867027650379778">he has to rely on the original author if he wants to make a change</a>.</p>

<p>This attitude also continues the trend of giving developers overwhelming choice. Convention-over-configuration and emphasis on developer ergonomics are key to getting real work done. <em>Of course</em> Mr. Fuchs is able to tell you which JavaScript library will precisely match your requirements—<em>he writes JavaScript libraries in his spare time!</em> For the rest of us, we don&#8217;t really want choice; we just want what&#8217;s best.</p>

<p>If choice was more important than well-tested integration, the majority of attendees at last week&#8217;s CodeConf would have been carrying ThinkPads instead of MacBook Pros. Instead, developers want a <em>happy path</em> that they can be reasonably assured will work well. If it doesn&#8217;t meet their needs, they want the ability to augment or replace the components that make up their integrated system.</p>

<p>Here&#8217;s the reality: As web applications get more complex, developers end up needing all of the miscellaneous nuts and bolts that they thought they would never use. Take <a href="https://app.getflow.com/">Flow</a> for example. Flow is a killer task manager web application built on <a href="http://documentcloud.github.com/backbone/">Backbone.js</a>. Backbone.js often advertises that it is only 3.9kb minified and compressed. How much of Flow&#8217;s nearly 900k of (minified!) JavaScript do you think is the application developers filling in the deficiencies in Backbone?</p>

<p><a href="http://tomdale.net/wp-content/uploads/2011/04/getflow.png"><img class="alignnone size-full wp-image-418" title="Flow's resource usage" src="http://tomdale.net/wp-content/uploads/2011/04/getflow.png" alt="" width="500" /></a></p>

<p><a href="http://tomdale.net/wp-content/uploads/2011/04/getflow.png"></a><a href="http://www.sproutcore.com">SproutCore</a> is often dismissed because of its size. <em>Of course</em> minimizing size is important. But if it takes a megabyte of JavaScript to ship the features you want, better the bulk of that code live in a framework instead of your application. Living in a framework means that it has been reviewed and optimized by an entire community of developers, and improves without any effort on your part. New Twitter currently clocks in at <em>over</em> a megabyte of JavaScript:</p>

<p><a href="http://tomdale.net/wp-content/uploads/2011/04/newtwitter.png"><img class="alignnone size-full wp-image-419" title="New Twitter" src="http://tomdale.net/wp-content/uploads/2011/04/newtwitter.png" alt="" width="500" /></a></p>

<p><a href="http://tomdale.net/wp-content/uploads/2011/04/newtwitter.png"></a>To the best of my knowledge, Twitter is not using any third-party libraries except for Mustache and jQuery. That means that a <em>huge</em> amount of JavaScript was written by Twitter engineers just to provide the framework in which the application runs. This isn&#8217;t stuff specific to Twitter. This is, for example, code that determines how to propagate changes to the DOM when the data model changes via XHR—a problem that <em>all</em> JavaScript developers face.</p>

<p>SproutCore may be big, but it&#8217;s because web applications are getting more complex every day, and we all have a common set of complex problems to solve. Oversimplifying the problem is disingenuous and forces each application to fend for itself. Mr. Fuchs says:</p>

<blockquote>Small code is good code: the fewer lines in your source, the fewer bugs you’ll have, plus it will download and execute faster.</blockquote>

<p>If creating a modern web app requires a megabyte of JavaScript, would you rather write, debug and optimize all of that code yourself?</p>

<p>It&#8217;s time to lay to rest the argument that full-stack libraries are unable or unfit to solve real problems. Instead, they are <em>best</em> suited to tackle the problems faced by modern web app developers. The same criticisms full-stack frameworks receive today are eerily similar to the same criticisms levied at jQuery several years ago. Unless you are planning to discontinue your application in six months, it&#8217;s time to start developing for the future.</p>

<p><em>Thanks to Charles Jolley for reviewing this post. </em><em>I tweet at <a href="http://twitter.com/tomdale">@tomdale</a> if you want more timely updates.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2011/04/imagine-a-beowulf-cluster-of-javascript-frameworks/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>The Future of the View Layer</title>
		<link>http://tomdale.net/2011/03/the-future-of-the-view-layer/</link>
		<comments>http://tomdale.net/2011/03/the-future-of-the-view-layer/#comments</comments>
		<pubDate>Fri, 11 Mar 2011 05:22:54 +0000</pubDate>
		<dc:creator>Tom Dale</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://tomdale.net/?p=358</guid>
		<description><![CDATA[The views expressed below are my own and not those of the SproutCore core team. Recently, Yehuda Katz and I have been making some changes to the SproutCore view layer. We&#8217;ve pulled out basic functionality into a new class called SC.CoreView, and broken the old SC.View (a behemoth) into several files based on what features [...]]]></description>
			<content:encoded><![CDATA[<p><em>The views expressed below are my own and not those of the SproutCore core team.</em></p>

<p>Recently, Yehuda Katz and I have been making some changes to the
SproutCore view layer. We&#8217;ve pulled out basic functionality into a new
class called SC.CoreView, and broken the old SC.View (a behemoth) into
several files based on what features they add. We also introduced
SC.TemplateView, a subclass of SC.CoreView, that allows you to use
<a href="http://handlebars.strobeapp.com/">Handlebars templates</a>. <sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> <sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p>

<p>Changes like these can be scary because they introduce uncertainty, but
I want to assure you that the project is still headed in the same direction; we just have two additional goals:</p>

<ul>
<li>Reduce the learning curve for new developers</li>
<li>Improve load time on low-power, low-bandwidth devices (e.g., iPad and Android tablets)</li>
</ul>

<p>It turns out that these view changes put us on the path towards meeting both goals.</p>

<p>The <code>desktop</code> framework, which can best be described as SproutCore&#8217;s
widget library, is its largest by far. The major reason for its size is
that we have re-implemented almost all desktop controls in JavaScript and HTML.
For example, SproutCore menu items flash when selected,
like they do in Mac OS X, and we have popovers that can anchor to
another on-screen element, like in iOS.</p>

<p>The downside to this sophistication is both an increase in code size and
an increase in cognitive overhead for developers new to SproutCore. In
particular, traditional web developers have a hard time learning how
views work; they are better off reading the <a href="http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CocoaViewsGuide/Introduction/Introduction.html">Cocoa guide to
views</a>
than to read a book on JavaScript and DOM.</p>

<p>Today, when we ask developers to write SproutCore applications, we ask
them to throw away their existing expertise and commit entirely to the
framework. If in six months they decide it won&#8217;t meet their needs, they
have to abandon almost all of their work. And it&#8217;s almost
impossible to test the waters with an existing codebase, since
developers must throw away their entire view layer.</p>

<p>Many developers don&#8217;t want or need native-style controls. They want to
throw together a quick application that still feels like a website.  We
can bring value to these developers, too. While SproutCore&#8217;s view layer
complements the controller and model layers, it doesn&#8217;t require
them&#8212;indeed, the point of MVC is to encapsulate these concerns. If we
can bring the sophistication of the data store and the robustness of
statechart-driven apps to everyone, we should.</p>

<p>Here&#8217;s the thing about templates, though: <em>they&#8217;re a better way of
doing what we&#8217;ve been doing all along.</em></p>

<p>At its core, a SproutCore view is a DOM representation plus a managed
layout. You need to build that DOM representation somehow, which means
either multiple DOM API calls, or lots of string concatenation
operations.</p>

<p>For example, here&#8217;s the render method for SC.RadioView:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">render<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>dataSource<span style="color: #339933;">,</span> context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> theme <span style="color: #339933;">=</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'theme'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> isSelected <span style="color: #339933;">=</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'isSelected'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      width <span style="color: #339933;">=</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'width'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      title <span style="color: #339933;">=</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'title'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      value <span style="color: #339933;">=</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'value'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      ariaLabeledBy <span style="color: #339933;">=</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ariaLabeledBy'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      ariaLabel     <span style="color: #339933;">=</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ariaLabel'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  context.<span style="color: #660066;">setClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    active<span style="color: #339933;">:</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'isActive'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    mixed<span style="color: #339933;">:</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'isMixed'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    sel<span style="color: #339933;">:</span> dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'isSelected'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    disabled<span style="color: #339933;">:</span> <span style="color: #339933;">!</span>dataSource.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'isEnabled'</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">//accessing accessibility</span>
  context.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'role'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'radio'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  context.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'aria-checked'</span><span style="color: #339933;">,</span> isSelected<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>ariaLabel <span style="color: #339933;">&amp;&amp;</span> ariaLabel <span style="color: #339933;">!==</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    context.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'aria-label'</span><span style="color: #339933;">,</span> ariaLabel<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>ariaLabeledBy <span style="color: #339933;">&amp;&amp;</span> ariaLabeledBy <span style="color: #339933;">!==</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    context.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'aria-labelledby'</span><span style="color: #339933;">,</span> ariaLabeledBy<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>width<span style="color: #009900;">&#41;</span> context.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'width'</span><span style="color: #339933;">,</span> width<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  context.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;span class = &quot;button&quot;&gt;&lt;/span&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  context <span style="color: #339933;">=</span> context.<span style="color: #660066;">begin</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'span'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sc-button-label'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  theme.<span style="color: #660066;">labelRenderDelegate</span>.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span>dataSource<span style="color: #339933;">,</span> context<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  context <span style="color: #339933;">=</span> context.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>For those keeping track at home, that&#8217;s 34 lines of code to generate
this:</p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;sc-radio-button mixed&quot;</span> aria-<span style="color: #000066;">checked</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;true&quot;</span> role<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;radio&quot;</span> index<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;0&quot;</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">span</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;button&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">span</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;sc-button-label&quot;</span>&gt;</span>Item1<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></pre></div></div>


<p>And that&#8217;s just to <em>create</em> the DOM representation. Updating it takes
another 27 lines of code, and it&#8217;s not even efficient; if a single
property changes, it re-renders the entire label portion of the control.</p>

<p>Imagine if we could instead tell the radio view to use a template:</p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#123;</span>bindClass <span style="color: #ff0000;">&quot;classNames isActive isMixed isSelected isEnabled&quot;</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#125;</span></span>
<span style="color: #009900;">     <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#123;</span>bindAttr role<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;ariaRole&quot;</span></span>
<span style="color: #009900;">                aria-<span style="color: #000066;">checked</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;ariaChecked&quot;</span></span>
<span style="color: #009900;">                aria-<span style="color: #000066;">label</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;ariaLabel&quot;</span></span>
<span style="color: #009900;">                aria-labelledby<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;ariaLabeledBy&quot;</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#125;</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">span</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;button&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">span</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;sc-button-label&quot;</span>&gt;</span>
    {{renderDelegate &quot;label&quot;}}
  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></pre></div></div>


<p>This is both shorter and easier to understand. But perhaps most
importantly, good abstractions allow us to make optimizations once.
Instead of each view trying (and failing) to optimize DOM access, and in
the process introducing a rat&#8217;s nest of complicated logic, we can move
the complexity to the templating layer and have every view ever written
benefit from it.</p>

<p>We could, for example, use different optimizations for Internet Explorer
and Chrome. Because views are now stating <em>intent</em> instead of atomic DOM
operations, we can choose the fastest path based on the performance
characteristics of the current environment. Decoupling allows
implementers to focus on behavior and appearance, not the intricacies of
DOM.</p>

<p>My point is this: template views are not meant as a replacement for
SC.View and our rich library of controls. In fact, template views can
serve to make desktop-style controls even better. If controls are easier
to implement, more people will make them, and then we all benefit.</p>

<p>Template views <em>are</em> designed to integrate with existing applications,
or to stand on their own if you need them to. As always, it&#8217;s important
to pick the right tool for the job.</p>

<p><center>&#42;&#42;&#42;</center></p>

<p>Yehuda and I have recently made fixes to SC.TemplateView that allow it
to be used inside traditional view hierarchies. An updated prerelease
gem with these changes is in the works, or you can find them in the
master branch on GitHub.</p>

<p>We think there will be a lot of opportunity for existing SproutCore apps
to take advantage of templates.  For example, think of the many modern
Mac OS X applications that use a WebView to integrate HTML content.</p>

<p>If you&#8217;re starting a new SproutCore application, you can decide which
works best for you. If you want a web-style application or a
desktop-style application (or some combination of the two), we want you
to feel like a first-class citizen. And if you opt for desktop-style, we
will work hard to ensure SC.TemplateView works with Greenhouse when it
ships.</p>

<p><em>I will be discussing this and more at the <a href="http://www.meetup.com/sproutcore/events/16508797/">SF SproutCore meetup</a>, Tuesday, March 15.</em></p>

<p><em>Thanks to Chris Swasey, Tyler Keating, Sudarshan Bhat and Peter Wagenet for reviewing this post. I tweet at <a href="http://twitter.com/tomdale">@tomdale</a> if you want more timely updates.</em></p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p><a href="http://blog.sproutcore.com/post/3594199971/introducing-sc-templateview-now-with-tutorial">http://blog.sproutcore.com/post/3594199971/introducing-sc-templateview-now-with-tutorial</a>&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p><a href="http://blog.sproutcore.com/post/3575607410/sproutcore-1-5-pre-4-templateview-is-here">http://blog.sproutcore.com/post/3575607410/sproutcore-1-5-pre-4-templateview-is-here</a>&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://tomdale.net/2011/03/the-future-of-the-view-layer/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.079 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-18 01:34:33 -->

