<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.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:series="http://unfoldingneurons.com/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">

<channel>
	<title>Nettuts+</title>
	
	<link>http://net.tutsplus.com</link>
	<description>Web Development &amp; Design Tutorials</description>
	<lastBuildDate>Sat, 26 May 2012 13:06:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<feedburner:info uri="nettuts" /><image><link>http://nettuts.com</link><url>http://envato.s3.amazonaws.com/rss_images/nettuts.jpg</url><title>NETTUTS</title></image><feedburner:emailServiceId>nettuts</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/NETTUTSVideos" /><feedburner:info uri="nettutsvideos" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Web Development &amp; Design Tutorials</itunes:subtitle><item>
		<title>10 Things I Learned While Interning at YUI</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/fM8Wt3TgzLo/</link>
		<comments>http://net.tutsplus.com/articles/general/10-things-i-learned-while-interning-at-yui/#comments</comments>
		<pubDate>Fri, 25 May 2012 19:54:57 +0000</pubDate>
		<dc:creator>Tilo Mitra</dc:creator>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25229</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25229&amp;c=872571148' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25229&amp;c=872571148' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;For eight months, I had the opportunity to intern with the YUI Team at Yahoo, while I was completing my engineering degree. Today, I&amp;#8217;d like to share the top ten things that I learned from my experience with YUI.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25229"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;A Bit of Background&lt;/h2&gt;
&lt;p&gt;The YUI Team is primarily responsible for the development and maintenance of the &lt;a href="http://www.yuilibrary.com"&gt;YUI Library&lt;/a&gt;. The library is a collection of user-interface components, class management tools, and utilities written in JavaScript and CSS that make it easier for developers to create web applications. Unlike other libraries, YUI is not just about DOM manipulation; it has a rich set of class management tools and a robust event system that makes it easier to develop in JavaScript.&lt;/p&gt;
&lt;p&gt;Apart from that, the YUI Team is also responsible for &lt;a href="http://yuilibrary.com/theater"&gt;YUI Theater&lt;/a&gt;, a very popular resource for web developers, along with a myriad of smaller tools such as YUI Builder, YUI Compressor, YUI Test and more.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My role at the team was to primarily help develop components for the library, although I helped out a little bit with YUI Theater as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;1. &lt;/span&gt;Understanding the Library&lt;/h2&gt;
&lt;p&gt;When I walked into Yahoo on my first day, I had zero real-world experience with YUI. I was familiar with JavaScript, jQuery, HTML/CSS and PHP, but that was basically it when it came to web programming. I&amp;#8217;m sure many of you are or have been in the same boat as me.&lt;/p&gt;
&lt;p&gt;My first task was to learn the syntax and architecture behind YUI3. Fortunately, I had a good understanding of raw JavaScript, and this helped immeasurably. A lot of front-end engineers know certain libraries really well, but many don&amp;#8217;t know how they works under the hood. To build plugins or modules on top of a library (such as YUI3 or jQuery), it&amp;#8217;s useful to have a fundamental understanding about how that library works, and in this case, how JavaScript as a language works.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Having a fundamental understanding of raw JavaScript (no libraries) forces you to understand the language better and makes you a better developer in the long run.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Think about it. Each JavaScript library is different and has its own idiosyncracies. The only commonality is that they are rooted in JavaScript. Doesn&amp;#8217;t it make sense to understand the idiosyncracies of JavaScript first? Take some time out to build something small without using a library. You&amp;#8217;ll be glad you did.&lt;/p&gt;
&lt;h3&gt;Js Fundamentals Links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en/A_re-introduction_to_JavaScript"&gt;A Re-introduction to JavaScript by Mozilla&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://javascript.crockford.com/code.html"&gt;Code Conventions in Javascript by Douglas Crockford&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://net.tutsplus.com/tutorials/javascript-ajax/the-10-javascript-mistakes-youre-making/"&gt;11 JavaScript Mistakes You&amp;#8217;re Making by Andrew Burgess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tutsplus.com/course/javascript-fundamentals/"&gt;JavaScript Fundamentals Course&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;2. &lt;/span&gt;Using Git in a Team&lt;/h2&gt;
&lt;p&gt;The YUI Team relies on Git as their primarily version control system and the project is hosted on &lt;a href="http://www.github.com/yui"&gt;Github&lt;/a&gt;. Previous to my internship at YUI, I used Git for my own small projects, and this generally consisted of the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git pull origin master&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add "&amp;lt;insert a large number file&amp;gt;"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -m "&amp;lt;insert some general comment&amp;gt;"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git push origin master&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;#8217;m sure many of you have done what I just described. Generally, as the project time gets longer, the commits get harder to understand! However, in a large team with a dozen developers, this method breaks down really fast. Firstly, &lt;code&gt;master&lt;/code&gt; in YUI3 (and many other large projects) is considered to be stable code that has been unit-tested, so commits generally do not go there until a later stage. Generally, each developer works on a separate branch and merges into &lt;code&gt;master&lt;/code&gt; once they are confident in their code.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; You don&amp;#8217;t have to be a guru, but understanding the basics of Git (branching, merging, reverting and solving merge conflicts) can go a long way to keeping your repos clean and organized.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A lot of things are possible to do with Git and I&amp;#8217;ve found that, rather than learning them ahead of time, it&amp;#8217;s more useful to research when you need to do something in particular. More importantly, my experience has taught me to be careful when experimenting with Git. It&amp;#8217;s better to ask someone when trying a new command or trying it on a mock repo instead of messing up the commit history of the live repo. :)&lt;/p&gt;
&lt;h3&gt;Git Basics Links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://learn.github.com/p/branching.html"&gt;Basics of Branching and Merging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://andyjeffries.co.uk/articles/25-tips-for-intermediate-git-users"&gt;25 Tips for Intermediate Git Users&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;3. &lt;/span&gt;Modular Architecture for Web Apps&lt;/h2&gt;
&lt;p&gt;Separating code into different JavaScript files to maintain a modular architecture can be painful for new developers. As a result, we often see large JavaScript files with hundreds of lines of code in them.&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
    &amp;lt;script&amp;gt;
        //My entire application's JS right here in one single spot. Uh oh.
    &amp;lt;/script&amp;gt;
    ...
&lt;/pre&gt;
&lt;p&gt;This introduces tight coupling between objects and isn&amp;#8217;t good practice when it comes to object-oriented programming. Even worse, you may have global variables that makes your app fail in unexpected ways. We&amp;#8217;ve all been guilty of this in the past. Luckily, libraries like YUI can help you with this.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; When writing an entire web application in JavaScript, it’s very important to have well-organized code; maintaining a spaghetti-coded project will only cause you headaches and nightmares.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One of the most important aspects of YUI3 is its modular nature. As a developer, you only pull down the code that you need. This reduces coupling, keeps file sizes small, and improves your code&amp;#8217;s readability.&lt;/p&gt;
&lt;p&gt;For instance, you could do this in a file called &lt;code&gt;counter.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
YUI.add(&amp;quot;counter&amp;quot;, function(Y) {

    //Write code specific to my counter object

}, '1.0', {requires: ['node']); //Say what my counter object code needs to run. YUI will pull these in first.
&lt;/pre&gt;
&lt;p&gt;And then in a separate JS file, such as &lt;code&gt;app.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
YUI_config = {
    modules: {
        'counter': { fullpath: 'path/to/counter.js', requires:['node'] }
    }
};

YUI().use('counter', function(Y) { //Pull down my counter module.
    var counter = new Y.Counter({…}); //Create a counter instance
});
&lt;/pre&gt;
&lt;p&gt;Instead of having one big file called &lt;code&gt;app.js&lt;/code&gt;, we&amp;#8217;ve split it up based on functionality into &lt;code&gt;counter.js&lt;/code&gt; and &lt;code&gt;app.js&lt;/code&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;4. &lt;/span&gt;NodeJS and YUI on the Server&lt;/h2&gt;
&lt;p&gt;The growing popularity of NodeJS made me want to start building some stuff with it. Being a front-end engineer, I like being able to use JavaScript on the server. Although NodeJS is not &lt;a href="http://www.quora.com/Node-js/What-is-Node.js-good-for"&gt;suitable for everything&lt;/a&gt;, it&amp;#8217;s worth learning.&lt;/p&gt;
&lt;p&gt;JS on the server does not have the same limitations as client-side JS because there is no DOM, but a library such as YUI can still help you with software architecture on the server &amp;#8211; things such as class and object management, and custom events.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; YUI 3 is not all about DOM manipulation — it also contains a robust set of class/object management tools, not to mention our powerful custom events. All of these tools are immediately useful in server-side programming.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Being on the YUI Team, I was able to explore Dav Glass&amp;#8217; &lt;a href="https://github.com/davglass/nodejs-yui3"&gt;NodeJS-YUI3&lt;/a&gt; module, which wraps up YUI functionality for use in a NodeJS environment. Remember that, apart from web sites, NodeJS is a useful tool for creating command-line utilities as well. Having good software architecture is always a big plus!&lt;/p&gt;
&lt;h3&gt;It comes down to code management&lt;/h3&gt;
&lt;p&gt;If you aren&amp;#8217;t a YUI3 user, I still recommend finding a set of tools to help organize your JavaScript on the server. Due to the inherent async nature of JavaScript and its propensity for callbacks, you need to be careful or you&amp;#8217;ll quickly end up with spaghetti-code.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;5. &lt;/span&gt;Hacking Using YUI&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Stay focused and keep hacking.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hacking is one of my favourite things to do when I am trying to learn something new. When trying to learn a new tool, there&amp;#8217;s nothing like sitting down and building something with it.&lt;/p&gt;
&lt;p&gt;Similar to jQuery, YUI3 has a &lt;a href="http://yuilibrary.com/yui/docs/guides/"&gt;distinct set&lt;/a&gt; of widgets, utilities and CSS frameworks. On one of the Yahoo Hack Days, I had the chance to sit down and try some of these out. As I&amp;#8217;m a fan of cricket, I made a mobile web app called Crictainment. Let me outline some of the parts of YUI that I found to be particularly useful for hacking.&lt;/p&gt;
&lt;div class=tutorial_image style="clear: both;"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2050_yui/crictainment.png" alt="Crictainment mobile web app using YUI" /&gt;&lt;/div&gt;
&lt;h3&gt;Y.ScrollView&lt;/h3&gt;
&lt;p&gt;Hacking a web app using YUI is pretty straightforward. For example, if you want a scrollview that is flickable with your fingers:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
YUI().use(&amp;quot;scrollview&amp;quot;, function(Y) {

    var scrollview = new Y.ScrollView({
        srcNode:&amp;quot;#scrollable&amp;quot;,
        height:&amp;quot;20em&amp;quot;
    });

});
&lt;/pre&gt;
&lt;p&gt;And in the HTML:&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;div id=&amp;quot;scrollable&amp;quot; class=&amp;quot;yui3-scrollview-loading&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;AC/DC&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;Aerosmith&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;Bob Dylan&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;Bob Seger&amp;lt;/li&amp;gt;
    ...
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The scrollview module figures out whether it should be horizontal or vertical based on the width and height of its container. More information on the YUI3 scrollview is &lt;a href="http://yuilibrary.com/yui/docs/scrollview/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Y.Anim&lt;/h3&gt;
&lt;p&gt;Another useful utility when hacking something is the Animation utility. It helps to spruce up your application with some nice animation that leverages CSS on capable browsers, and defaults to JS timer-based animations on older browsers.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var myAnim = new Y.Anim({
    node: '#demo',
    to: {
        width: 0,
        height: 0
    }
});

myAnim.on('end', function() {
    myAnim.get('node').addClass('yui-hidden');
});
&lt;/pre&gt;
&lt;h3&gt;Y.YQL&lt;/h3&gt;
&lt;p&gt;Another really important tool that is great for hacking is &lt;a href="developer.yahoo.com/yql"&gt;YQL&lt;/a&gt; &amp;#8211; Yahoo Query Language. I&amp;#8217;m sure most of you have used it, but for those who haven&amp;#8217;t, think of it as a way to access a whole host of different APIs using a standard syntax. YUI and YQL work really well together through the &lt;a href="http://yuilibrary.com/yui/docs/yql/"&gt;Y.YQL&lt;/a&gt; module. For instance, here we are getting the recent activity from Vimeo:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
YUI().use('yql', function(Y) {

    Y.YQL('select * from vimeo.activity.everyone where username=&amp;quot;basictheory&amp;quot;', function(r) {
        //r now contains the result of the YQL Query
    });

});
&lt;/pre&gt;
&lt;p&gt;Try out this query &lt;a href="http://developer.yahoo.com/yql/console/?q=show%20tables&amp;amp;env=store://datatables.org/alltableswithkeys#h=select%20*%20from%20vimeo.activity.everyone%20where%20username%3D%27basictheory%27"&gt;here&lt;/a&gt;. I use YQL regularly to access different APIs in a consistent manner.&lt;/p&gt;
&lt;p&gt;Regardless of whether you are using YUI, jQuery, or any other library, building something with it is a great way to become familiarized with your development toolbox. When hacking, don&amp;#8217;t worry too much about the technical details &amp;#8211; just set a time limit and just build it!&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;6. &lt;/span&gt;YUI App Framework&lt;/h2&gt;
&lt;p&gt;One of the newer additions to YUI has been the App Framework. It&amp;#8217;s similar to Backbone.js, but with YUI&amp;#8217;s sophisticated event infrastructure under the hood. The App Framework made it easy for me to build MVC-style web applications.&lt;/p&gt;
&lt;p&gt;Just like any other tool, I built something with the App Framework to understand how it worked. Once again, I can&amp;#8217;t stress the benefits of hacking on products. For the App Framework, I built &lt;a href="http://topforty.it"&gt;TopForty&lt;/a&gt; with a friend of mine.&lt;/p&gt;
&lt;div class=tutorial_image&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2050_yui/topforty.png" alt="TopForty web app using YUI App Framework" /&gt;&lt;/div&gt;
&lt;h3&gt;The Model&lt;/h3&gt;
&lt;p&gt;The YUI App Framework is built on the MVC design pattern. Let&amp;#8217;s start with the model. If you aren&amp;#8217;t familiar with MVC, take a look at &lt;a href="http://net.tutsplus.com/tutorials/other/mvc-for-noobs/"&gt;this tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For TopForty, we were able to get a large JSON array of the most talked-about songs from Twitter. Each object in the array looked like this:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
{
    &amp;quot;title&amp;quot;: &amp;quot;PayPhone&amp;quot;,
    &amp;quot;position&amp;quot;: 1,
    &amp;quot;video_id&amp;quot;: &amp;quot;5FlQSQuv_mg&amp;quot;,
    &amp;quot;song_id&amp;quot;: 627,
    &amp;quot;artist&amp;quot;: &amp;quot;Maroon 5&amp;quot;,
    &amp;quot;duration&amp;quot;: 232,
    &amp;quot;images&amp;quot;: […]
}
&lt;/pre&gt;
&lt;p&gt;We wrapped this up in a Y.Model subclass called &lt;code&gt;Y.SongModel&lt;/code&gt;. Here&amp;#8217;s the class definition:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
Y.SongModel = Y.Base.create('songModel', Y.Model, [], {

    initializer: function (config) {
        ...
    }
}, {
    ATTRS: {
        title: {},
        artist: {},
        images: {
            value: []
        },
        nowPlaying: {
           ...
        }
        ...
    }
});
&lt;/pre&gt;
&lt;p&gt;This allowed us to listen for events whenever one of the &lt;code&gt;ATTRS&lt;/code&gt; in the model changed and take appropriate action. For example, if the current song being played was changed:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
//When the model's isPlaying attribute changes, call the handleIsPlayingChange function.
this.model.after('isPlayingChange', this.handleIsPlayingChange, this);
&lt;/pre&gt;
&lt;h3&gt;The View&lt;/h3&gt;
&lt;p&gt;Each model was represented visually by a View, which is essentially just HTML. For TopForty, we had a &lt;code&gt;SongView&lt;/code&gt; that looked something like this:&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;div class=&amp;quot;song yui3-u&amp;quot; id=&amp;quot;songModel_2&amp;quot;&amp;gt;
            &amp;lt;img class=&amp;quot;song-img&amp;quot; src=&amp;quot;...&amp;quot;&amp;gt;
            &amp;lt;div class=&amp;quot;song-desc&amp;quot;&amp;gt;
                &amp;lt;div class=&amp;quot;song-number&amp;quot;&amp;gt;2&amp;lt;/div&amp;gt;
                &amp;lt;div class=&amp;quot;song-movement&amp;quot;&amp;gt;
                    &amp;lt;img class=&amp;quot;movement-icon&amp;quot; src=&amp;quot;...&amp;quot;&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div class=&amp;quot;details&amp;quot;&amp;gt;
                    &amp;lt;h4 class=&amp;quot;song-name&amp;quot;&amp;gt;Turn on the lights&amp;lt;/h4&amp;gt;
                    &amp;lt;p class=&amp;quot;artist-name&amp;quot;&amp;gt;Future&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We wrapped this up in a &lt;code&gt;Y.View&lt;/code&gt; subclass called &lt;code&gt;Y.SongView&lt;/code&gt;. Each View requires a &lt;code&gt;render()&lt;/code&gt; method that is called when displaying the view on the page, and a &lt;code&gt;initializer()&lt;/code&gt; method where events are subscribed. If you want, you can establish a relationship between your view and a Model or Model List instance by attaching event handlers to them in a custom &lt;code&gt;initializer()&lt;/code&gt; method like we see below:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
Y.SongView = Y.Base.create('songView', Y.View, [], {
    initializer: function (config) {
            var model = this.get(&amp;quot;model&amp;quot;);
            model.after('change', this.render, this);
            model.after('destroy', this.destroy, this);
    },
    render: function() {
        ...
    },

    destroy: function() {
        ...
    },

    showSongOverlay: function() {
        ...
    }
},{
    ATTRS: {
        container: Y.one(&amp;quot;#songContainer&amp;quot;)
    }
});
&lt;/pre&gt;
&lt;p&gt;By doing this, we were able to have songview specific methods such as &lt;code&gt;displayNowPlayingIndicator()&lt;/code&gt; and &lt;code&gt;showSongOverlay()&lt;/code&gt; on the &lt;code&gt;Y.SongView&lt;/code&gt; instance rather than as separate functions.&lt;/p&gt;
&lt;h3&gt;The Router&lt;/h3&gt;
&lt;p&gt;The Router, formally known as the Controller, is what makes everything connect and work. Remember that in classical MVC, all user actions traditionally go through the controller. In web apps, the router uses HTML5 history to change URLs and controls the state of the application.&lt;/p&gt;
&lt;p&gt;For example, in TopForty clicking on a song changes the URL to the song&amp;#8217;s ID. The URL change is picked up by the router, which loads the YouTube video for the song in question:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
Y.AppRouter = Y.Base.create('appRouter', Y.Router, [], {
  // Default route handlers inherited by all CustomRouter instances.
  index: function (req) {
    // ... handle the / route, load up the UI, etc.
  },

  loadSongFromUrl: function (req) {
    // ... handle the /song/:songId' route ...
    //Get the youtube video from the model with an id of :songId and play it.
  }
}, {
  ATTRS: {
    // The specific routes that we are interested in listening to:
    routes: {
      value: [
        {path: '/',    callback: 'index'},
        {path: '/song/:songId'', callback: 'loadSongFromUrl'}
      ]
    },
  }
});
&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt; What I learned:&lt;/strong&gt; Leveraging the MVC design pattern can help you create anything from simple non-interactive views to rich applications.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I hope I have been able to give you a taste of what is possible with the YUI App Framework. For a more thorough walkthrough, I recommend the following links. If you aren&amp;#8217;t a fan of the App Framework, I recommend you look into the equivalent jQuery alternatives. &lt;a href="http://documentcloud.github.com/backbone/"&gt;Backbone.js&lt;/a&gt; in particular has a large following with good documentation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://yuilibrary.com/yui/docs/app/"&gt;YUI App Framework User Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ericf/photosnear.me"&gt;Github Repo of a YUI App Framework Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.slideshare.net/eferraiuolo/app-framework-youve-been-wanting-this"&gt;Slides from App Framework YUIConf Talk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;7. &lt;/span&gt;Test Driven Development and YUI Test&lt;/h2&gt;
&lt;p&gt;For developers, writing code is often the easy and fun part. The hard part is figuring out how old, buggy code works and trying to fix past errors. To minimize this, a lot of organizations including Yahoo emphasize the importance of Test Driven Development (TDD). With TDD, you write the tests first, then add the functionality until all your tests pass. Want to add a new feature? Write a new test, then code the feature.&lt;/p&gt;
&lt;p&gt;I was new to TDD when I joined the YUI team. Unfortunately, JS does not have the best testing suite. User interactions in particular are hard to test. Furthermore, we have to test in all the major browsers.&lt;/p&gt;
&lt;p&gt;One of the primary ways we conduct unit-testing is through &lt;a href="http://yuilibrary.com/yui/docs/test/"&gt;YUI Test&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Following test-driven development principles makes you more productive as a programmer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;YUI Test is a complete testing framework for JavaScript and Web applications. You can use the simple JavaScript syntax to write unit tests that can be run in web browsers or on the command line, as well as functional tests to be run in web browsers.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s how you set it up:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
// Create a new YUI instance and populate it with the required modules.
YUI().use('test', function (Y) {
    // Test is available and ready for use. Add implementation
    // code here.

});
&lt;/pre&gt;
&lt;p&gt;Now, we can start writing some unit tests!&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var testCase = new Y.Test.Case({

    name: &amp;quot;TestCase Name&amp;quot;,

    //---------------------------------------------
    // Setup and tear down
    //---------------------------------------------

    setUp : function () {
        this.data = { name : &amp;quot;Tilo&amp;quot;, age : 23 };
    },

    tearDown : function () {
        delete this.data;
    },

    //---------------------------------------------
    // Tests
    //---------------------------------------------

    testName: function () {
        Y.Assert.areEqual(&amp;quot;Tilo&amp;quot;, this.data.name, &amp;quot;Name should be 'Tilo'&amp;quot;);
    },

    testAge: function () {
        Y.Assert.areEqual(23, this.data.age, &amp;quot;Age should be 23&amp;quot;);
    }
});
&lt;/pre&gt;
&lt;p&gt;YUI Test supports equality assertions (&lt;code&gt;areEqual()&lt;/code&gt;) which uses &lt;code&gt;==&lt;/code&gt;, sameness assertion (&lt;code&gt;areSame()&lt;/code&gt;) which uses &lt;code&gt;===&lt;/code&gt;, special value assertions such as &lt;code&gt;isFalse()&lt;/code&gt;, &lt;code&gt;isNotUndefined()&lt;/code&gt;, mock objects and more.&lt;/p&gt;
&lt;p&gt;After writing our tests, we can run it as shown below. The results of the test can be outputted as XML, JSON, jUnitXML, or TAP.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
Y.Test.Runner.add(testCase);
Y.Test.Runner.run();
&lt;/pre&gt;
&lt;h3&gt;Don&amp;#8217;t forget to test, regardless of what you use.&lt;/h3&gt;
&lt;p&gt;If you don&amp;#8217;t use YUI Test, that&amp;#8217;s fine. However, I want to stress the importance of testing your code. I&amp;#8217;m guilty even today of writing code without writing tests and it&amp;#8217;s probably okay if it&amp;#8217;s your own small personal project. All of us cut corners sometime. However, if you&amp;#8217;re programming for a client or an organization, following TDD principles will save you (and your clients) from a headache.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;8. &lt;/span&gt;Minifying and Linting Your JavaScript&lt;/h2&gt;
&lt;p&gt;Serving up JavaScript files without any minification or lint step can be risky. Minification can often compress the file-size by over 30%, making your page load faster for the end-user. Linting is a good way to ensure your JavaScript follows good coding practices so that errors are minimized.&lt;/p&gt;
&lt;p&gt;During my time at Yahoo, we used &lt;a href="http://yuilibrary.com/projects/yuicompressor/"&gt;YUI Compressor&lt;/a&gt; and &lt;a href="http://yuilibrary.com/projects/builder/"&gt;YUI Builder&lt;/a&gt; to compress and build our code. The build step includes concatenation and linting through &lt;a href="http://www.jslint.com/"&gt;JSLint&lt;/a&gt;. I&amp;#8217;m sure most of you have used JSLint at some stage, and I do believe it helps improve your coding style.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Ask yourself if a certain practice reduce your possibility of errors and if so, follow it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, I&amp;#8217;m not going to talk in depth about YUI Compressor and Builder because those may not be the tools of your choice. Usually for my own projects, I use the &lt;a href="https://github.com/reid/node-jslint"&gt;JSLint NPM Module&lt;/a&gt; to check my code.&lt;/p&gt;
&lt;p&gt;What I want to stress on is the need to perform these steps prior to pushing code out to production. As JavaScript does not have a compilation step, many developers are accustomed to pushing their JavaScript out to production, comments and all included. Again, this is okay for small projects, but perhaps you should consider minifying and linting your code to ensure users get the best experience.&lt;/p&gt;
&lt;h3&gt;Additional Reading&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://net.tutsplus.com/tutorials/javascript-ajax/meeting-grunt-the-build-tool-for-javascript/"&gt;Grunt, The Build Tool for JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://net.tutsplus.com/tutorials/tools-and-tips/how-to-use-the-nettuts-phing-build-script/"&gt;Phing Build Script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/reid/node-jslint"&gt;JSLint NPM Module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://yuilibrary.com/projects/builder/"&gt;YUI Builder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://yuilibrary.com/projects/yuicompressor/"&gt;YUI Compressor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;9. &lt;/span&gt;Coding with the User in Mind&lt;/h2&gt;
&lt;p&gt;The YUI Team has a great following of friendly, active, and knowledgable developers just like most large open-source projects. As developers working on open-source software, I learned that I can&amp;#8217;t sit under a rock and code all day, even if I want to. Developing is as much about writing code as it is about making sure the code you write is actually helping someone solve a problem.&lt;/p&gt;
&lt;p&gt;This took me a while to learn, but it&amp;#8217;s an important lesson. When writing software, the goal isn&amp;#8217;t to use the coolest technology or the latest stack or the hottest language. It&amp;#8217;s about the user. When writing OSS, the users are often other developers who build on top of your product. Small things such as weekly updates, tweets, and IRC communication can actually help you more than hours of coding.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; It&amp;#8217;s not about the technology or the stack or the language, it&amp;#8217;s about the user.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my first month of interning at YUI, I wrote about 500 lines of code which I had to scrap because most of it was repetitive and did not address the end goal. I was guilty of coding too early without figuring out the requirements of the project. A good rule is to spend a third of your time gathering requirements, a third of your time writing tests and the final third implementing your software.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;10. &lt;/span&gt;&amp;#8220;When all you have is a hammer, everything looks like a nail.&amp;#8221;&lt;/h2&gt;
&lt;p&gt;I want to conclude by sharing the most important thing that I think I learned in my internship. I consider it to be more important than any technical knowledge that I gained. By working on a library that is not the most popular, I realized the importance of diversifying my skills and being flexible as a developer. I&amp;#8217;ve seen how much work it takes to maintain an open-source project and have gained a lot of respect for everyone who release their well-written code for free.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt; &lt;strong&gt;What I learned:&lt;/strong&gt; Choose a library because it&amp;#8217;s the right one for the job, not because it&amp;#8217;s your favourite. Understand that different pieces of software serve different purposes, and sometimes understanding the difference is tough.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/eZAHAEjhacfiBMpsB04aBObt0sc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eZAHAEjhacfiBMpsB04aBObt0sc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/eZAHAEjhacfiBMpsB04aBObt0sc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eZAHAEjhacfiBMpsB04aBObt0sc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=fM8Wt3TgzLo:0nq-wBim-jg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=fM8Wt3TgzLo:0nq-wBim-jg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=fM8Wt3TgzLo:0nq-wBim-jg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=fM8Wt3TgzLo:0nq-wBim-jg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=fM8Wt3TgzLo:0nq-wBim-jg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=fM8Wt3TgzLo:0nq-wBim-jg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=fM8Wt3TgzLo:0nq-wBim-jg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=fM8Wt3TgzLo:0nq-wBim-jg:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/fM8Wt3TgzLo" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/articles/general/10-things-i-learned-while-interning-at-yui/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/articles/general/10-things-i-learned-while-interning-at-yui/</feedburner:origLink></item>
		<item>
		<title>Coda 2: Reviewed</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/hirPYWLLtiU/</link>
		<comments>http://net.tutsplus.com/articles/reviews/coda-2-review/#comments</comments>
		<pubDate>Thu, 24 May 2012 15:00:38 +0000</pubDate>
		<dc:creator>Jeffrey Way</dc:creator>
				<category><![CDATA[Reviews]]></category>
		<category><![CDATA[coda]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[panic]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25120</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25120&amp;c=358518988' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25120&amp;c=358518988' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;Well, it happened; Panic &lt;a href="http://panic.com/coda"&gt;finally released&lt;/a&gt; the long-awaited version two of their popular code editor, Coda. But does it live up to the hype? Well, that depends on what type of coder you are. Read the full review after the jump!&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25120"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/editor-overview.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;The Good&lt;/h2&gt;
&lt;h3&gt;It&amp;#39;s Beautiful&lt;/h3&gt;
&lt;p&gt;When Panic initially unveiled the tour video for their new editor, I was taken aback. The massive file icons only appeal to a very specific type of coder &amp;#8211; and I&amp;#39;m not that person. I, as well as many others, found them to be considerably unattractive. Perhaps they&amp;#39;d be appealing, if you exclusively work on static designs, but as someone who stares at an image-less, black background for the better part of each day, these icons only take up space.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/no-thanks.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;Luckily, they can easily be reduced to simple text, at which point the editor becomes infinitely more attractive. The icons are a gimmick.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/better.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;h3&gt;Helpers&lt;/h3&gt;
&lt;p&gt;Clearly, Coda is playing to its core audience: PHP developers. While you can certainly code in any language, PHP receives the bells and whistles. &lt;/p&gt;
&lt;p&gt;As a PHP developer myself, I won&amp;#39;t deny that &amp;quot;&lt;em&gt;WAT&lt;/em&gt;&amp;quot; is scattered throughout the language. Even after years and years, I still frequently refer to the PHP.net documentation to remember which order a function&amp;#39;s parameters should be passed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do I set the haystack as the first or second parameter, when using &lt;code&gt;stristr&lt;/code&gt;?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is one area where Coda shines. It provides instant documentation in the sidebar as you type.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/docs.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;What&amp;#39;s unfortunate is that this feature is limited to, essentially, front-end developers: HTML, CSS, JavaScript, and PHP. Why?&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/css-docs.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;Nonetheless, it&amp;#39;s a helpful resource, though I&amp;#39;ll note that, despite the fact that Panic lists JavaScript as being supported, it only offers to link me to the book documentation. A bug perhaps?&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/javascript.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;h3&gt;Clippings&lt;/h3&gt;
&lt;p&gt;Coda&amp;#39;s native clippings feature has received a substantial upgrade as well. Rather than the awkward floating bar from Coda 1, the new version rests as its own panel in the sidebar.&lt;/p&gt;
&lt;p&gt;Notable additions include multiple (tab separated) insertion points, and the ability to assign both tab triggers and keyboard shortcuts.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/clippings.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/clipping-add.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;h3&gt;Sites&lt;/h3&gt;
&lt;p&gt;The standard &amp;quot;Sites&amp;quot; layout is back in Coda 2, which allows you to assign either local or remote directories to one click icons. No notes here; it&amp;#39;s helpful, and the new ability to group sites into &amp;#8220;lists&amp;#8221; (or categories) is very much welcomed.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/sites.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;h3&gt;CSS Helpers&lt;/h3&gt;
&lt;p&gt;In Coda 1, the CSS GUI was available via its own tab, or panel; however, with this new version, it&amp;#39;s baked into the editor. For instance, as you type &lt;code&gt;background&lt;/code&gt;, the option to use a GUI to create a gradient will be provided, though I must admit that setting values and percentages wasn&amp;#8217;t overly intuitive.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/gradient.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: did you notice in the image above that Coda only adds a single Webkit prefix? Yeah, we&amp;#39;ll cover that shortly! :/&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This same functionality is available for other properties too, such as &lt;code&gt;box-shadow&lt;/code&gt; and &lt;code&gt;padding&lt;/code&gt;.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/box-shadow.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;Honestly, these aren&amp;#39;t features that I&amp;#39;d ever imagine using; they&amp;#39;d only slow me down. But still, for newcomers, I&amp;#39;m sure they&amp;#39;ll prove to be helpul.&lt;/p&gt;
&lt;h3&gt;Quick Open&lt;/h3&gt;
&lt;p&gt;It&amp;#39;s nothing new, but, if you need to quickly switch between files, you can press &lt;code&gt;Control + Q&lt;/code&gt;, and type in the name of the file. It&amp;#39;s not nearly as fast (or responsive) as Sublime Text&amp;#39;s implementation, but will get the job done.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/quick-open.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;h3&gt;Built-In Transmit&lt;/h3&gt;
&lt;p&gt;The popular &lt;a href="http://panic.com/transmit/"&gt;Transmit&lt;/a&gt; engine is essentially baked into the editor. This provides you with a full file browser for, not only your local files, but also through FTP, SFTP, WebDAV, and S3.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/transmit.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;This is a huge plus for some, though, for me, I don&amp;#39;t remember the last time that I uploaded files to my server with (S)FTP. Still a nifty feature, though, and the ability to publish a project with a keystroke is handy!&lt;/p&gt;
&lt;h3&gt;Terminal&lt;/h3&gt;
&lt;p&gt;Introduced in the first release of Coda, the Terminal panel is back. If you&amp;#8217;re not the type of coder who has Terminal open at all times, accessible through a keyboard shortcut, then this will be a welcomed feature.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/terminal.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;The Bad&lt;/h2&gt;
&lt;h3&gt;Multiple Cursors&lt;/h3&gt;
&lt;p&gt;Really? No multiple cursor support? Coda provides a &amp;quot;block edit&amp;quot; functionality, but it&amp;#39;s confusing, and not nearly as intuitive as Sublime Text&amp;#39;s implementation. &lt;/p&gt;
&lt;p&gt;In this editor&amp;#39;s opinion, it was a massive mistake to not make multiple cursor support a top priority. I can&amp;#39;t imagine using an editor that doesn&amp;#39;t give me this ability.&lt;/p&gt;
&lt;h3&gt;Odd CSS Support&lt;/h3&gt;
&lt;p&gt;From a distance, Coda&amp;#39;s CSS support appears to be fantastic. Auto-completion for the new CSS3 properties, a GUI for creating gradients and box-shadows, etc. What more could you want?&lt;/p&gt;
&lt;p&gt;Well, yes that would be true, if those implementations were flawless &amp;#8211; but they&amp;#39;re not. For example, remember the nifty documentation functionality that I noted above?&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/transform.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;It&amp;#39;s very helpful…and limiting at the same time. You might be surprised to find that, if I type the official &lt;code&gt;transform&lt;/code&gt; property, nothing shows up in the sidebar (&lt;em&gt;there&amp;#39;s also no auto-completion for the property&lt;/em&gt;). The documentation only registers if I specificially use &lt;code&gt;-webkit-transform&lt;/code&gt;. Yep, the official version doesn&amp;#39;t work &amp;#8211; and neither does &lt;code&gt;-moz-transform&lt;/code&gt; (or any of the other versions, for that matter).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh, and as for Opera and Microsoft prefixes (&lt;code&gt;-o&lt;/code&gt; and &lt;code&gt;-ms&lt;/code&gt;, respectively), you can forget about it. Zero auto-completion support. They might as well not even exist.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Webkit Love Affair&lt;/h4&gt;
&lt;p&gt;There&amp;#39;s no denying that Coda&amp;#39;s Webkit-based support is fantastic. It makes sense; the live preview uses the Webkit engine, so they need to ensure that the gradients (and other CSS3 properties) that the GUI produces will render correctly. &lt;/p&gt;
&lt;p&gt;But, particularly when considering the huge debates that have centered around CSS and Webkit in the last half year, Panic&amp;#39;s decision to seemingly endorse Webkit-exclusive CSS3 properties is a terrible one. Why will it auto-complete &lt;code&gt;-webkit-animation&lt;/code&gt;, but not any of the others (&lt;code&gt;ms&lt;/code&gt;, &lt;code&gt;o&lt;/code&gt;, &lt;code&gt;moz&lt;/code&gt;)? Why does it render a Webkit gradient, but not for the other vendors?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When questioned (on Twitter), Panic noted that it&amp;#39;s incredibly simple to manually add the other prefixes. True; no one is denying that. But why should we have to? Do it for us. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If convenience were the only downside, that would be one thing, but the problem is that their decision to only provide Webkit generation and auto-completion endorses the notion (especially for newcomers) that it&amp;#39;s okay to tailor designs specifically for one engine. &lt;em&gt;Note: a smattering of Mozilla prefixes are provided, but not nearly as many.&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;I Wish…&lt;/h4&gt;
&lt;p&gt;If, behind the scenes, Coda would maintain a list of every CSS3 property, along with its required prefixes, that would be huge. Don&amp;#39;t make me memorize whether or not Microsoft now provides its own prefix for gradient support. Be a good role model, and do it for me. Sheesh, don&amp;#39;t make me build a tool, like &lt;a href="http://prefixr.com"&gt;Prefixr&lt;/a&gt;, to get around this.&lt;/p&gt;
&lt;h3&gt;Git&lt;/h3&gt;
&lt;p&gt;Git integration in Coda 2 is certainly not a minus, but more of an &amp;quot;ehh.&amp;quot; The previous version of Coda provided Subversion support (while the community moved to Git). So, sure, adding a UI for Git was a smart move.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/git-integration.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;It very well might be helpful to those who aren&amp;#39;t entirely comfortable in the Terminal, but, still, I wonder how many of these folks are truly using version control. Do they understand what a branch, stage, or commit is? My instinct is that, if you do, then you&amp;#39;ll absolutely prefer to perform these sorts of commands in the Terminal &amp;#8211; likely using your own custom aliases to speed things up. &lt;/p&gt;
&lt;p&gt;Nonetheless, it&amp;#39;s a feature that might be helpful to some &amp;#8211; just not me.&lt;/p&gt;
&lt;h3&gt;Command Palette&lt;/h3&gt;
&lt;p&gt;Considering the fact that Sublime Text 2, in barely a year, has become the golden editor amongst web developers, you would think that Coda might adopt some of the most touted features in that editor.&lt;/p&gt;
&lt;p&gt;Why isn&amp;#39;t there a helpful command palette that allows me to specify which action to execute with text? I can&amp;#39;t always remember the keyboard shortcut for creating a split; why can&amp;#39;t I pull up the command palette, and type &amp;quot;split&amp;quot;? &lt;/p&gt;
&lt;p&gt;At this point, I consider a command palette to be essential in my workflow, yet Coda is missing one entirely.&lt;/p&gt;
&lt;h3&gt;Installing Plugins&lt;/h3&gt;
&lt;p&gt;We&amp;#39;re still in the early days of Coda 2; as such, there currently aren&amp;#39;t any plugins available on Panic&amp;#39;s website. Hopefully, once some are released, there will be an easy, &lt;a href="http://wbond.net/sublime_packages/package_control"&gt;Package-Control&lt;/a&gt;-esque method for installing them. Please don&amp;#39;t make me manually download and install these. &lt;/p&gt;
&lt;p&gt;In Sublime Text, if I want CoffeeScript syntax highlighting, I can literally have it in ten seconds, without leaving the editor. Will Coda provide this same convenience? My instincts point to &amp;quot;no,&amp;quot; which is not a good sign. The success of an editor has more to do with the community&amp;#8217;s involvement than anything else. &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The success of an editor has more to do with the community&amp;#8217;s involvement than anything else.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3&gt;Vi-Mode Option&lt;/h3&gt;
&lt;p&gt;Remember when I noted that Coda was made for a very specific type of coder? Yeah, well that type of coder likely doesn&amp;#39;t use Vim (or Git-based deployment). For me, though, it&amp;#39;s the difference between using Coda and not. I&amp;#39;m heavily dependent upon these keyboard commands, but Coda has left me in the dark. Why? Sublime Text offers Vi (Vintage) support; even &lt;a href="http://chocolatapp.com/"&gt;Chocolat&lt;/a&gt; does. &lt;/p&gt;
&lt;p&gt;I&amp;#39;d imagine that, at some point in the near future, support will be provided through a plugin, but, nonetheless, when considering the resurgence of Vim in the last few years, shouldn&amp;#8217;t support should be baked in as an option? Maybe so, maybe not; the truth is that the huge majority of Coda users have no interest in this feature, so I won&amp;#8217;t knock Coda too much for this! &lt;/p&gt;
&lt;h3&gt;Only Four Color Schemes&lt;/h3&gt;
&lt;p&gt;I grant you that this is petty, but why does Coda only provide four color schemes for the editor? Why not offer a dozen or so? We coders love our themes, but will now have to resort to scouring the web for custom skins. Or, when considering the fact that &lt;a href="http://ethanschoonover.com/solarized"&gt;Solarized&lt;/a&gt; is one of the most popular, cross-editor themes on the web, why not provide that as a built-in choice? Chocolat does.&lt;/p&gt;
&lt;p&gt;Admittedly, things like this are small annoyances, but, still, they&amp;#39;re just that… annoying.&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/color-schemes.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Update &amp;#8211; &lt;/strong&gt;&lt;a href="http://justinhileman.info/coda-colors/"&gt;here&amp;#8217;s a plugin&lt;/a&gt; that provides lots of alternative color scheme options.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3&gt;A Great Sidebar&amp;#8230;But&lt;/h3&gt;
&lt;p&gt;Clearly, Panic spent a great deal of time on the new sidebar functionality. With all of these helpful features, though, why I am limited to just one view at a time? Maybe I want a file browser on top, and the documentation viewer below? It would be far more convenient if I could stack these panels.
&lt;/p&gt;
&lt;div class=tutorial_image&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/free-space.jpg" alt="Free space"&gt;&lt;/div&gt;
&lt;h3&gt;Configurability&lt;/h3&gt;
&lt;p&gt;Sublime Text is sometimes criticized because its configuration options page is essentially a JavaScript object.&lt;/p&gt;
&lt;div class=tutorial_image&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/st2.jpg"&gt;&lt;/div&gt;
&lt;p&gt;The irony is that I consider this to be one of its best features! I have control over everything! Need to change the tab-width, font-size, or a keyboard shortcut? Easy &amp;#8211; it takes five seconds. What about on a per-file basis? That&amp;#8217;s doable too. With Coda, though, I virtually have no clue how to configure it to my preferences &amp;#8211; beyond the basic settings that are provided in the Preferences pane.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;blockquote class=pullquote&gt;&lt;p&gt;The updates aren&amp;#8217;t indicative of today&amp;#8217;s modern developer.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;As I proof this article, I realize that it has come across as somewhat critical. The truth is that Coda 2 is a solid editor &amp;#8211; much better than its predecessor. While it does have some bugs, it was just released. Give the amazing Panic team time to listen to community input and release updates/patches. And, certainly, missing functionality can often be provided, via plugins.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m only capable of reviewing an editor based upon on my own needs. Personally, I&amp;#39;m most concerned with speed, convenience, and Vi support. Instead of Panic focusing on what will make me more efficient at my job, it sort of feels as if they&amp;#8217;ve tacked on a lot of eye candy that doesn&amp;#8217;t necessarily help me much. The updates also aren&amp;#8217;t indicative of today&amp;#8217;s modern developer. Where is Less, HAML, or CoffeeScript syntax highlighting? So yes, it&amp;#8217;s a solid editor, but, at the same time, it&amp;#8217;s not one that was tailored for more serious developers.&lt;/p&gt;
&lt;p&gt;When considering Coda&amp;#39;s stand-out features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;File Icons -&lt;/strong&gt; It&amp;#8217;s a gimmick; do people really want massive file icons?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FTP Integration -&lt;/strong&gt; Helpful, but in a modern world, where we deploy websites and applications with Git (whether to Heroku or PHPFog), I&amp;#39;ll very rarely make use of it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in MySQL -&lt;/strong&gt; Again, helpful, but you&amp;#39;ll likely find yourself resorting to more powerful dedicated apps, such as &lt;a href="http://www.sequelpro.com/"&gt;Sequel Pro&lt;/a&gt; or &lt;a href="http://www.araelium.com/querious/"&gt;Querious&lt;/a&gt;. It feels tacked on for eye candy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git Support -&lt;/strong&gt; I&amp;#39;ll stick with Terminal. You likely will too. (But hey, Coda has a built-in Terminal panel.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wish that they had instead focused more on speed &amp;#8211; not necessarily the speed of the editor, but the speed of my workflow. &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;How can I accomplish my daily tasks more quickly?&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;From this perspective, Coda 2 doesn&amp;#8217;t provide anything new.&lt;/p&gt;
&lt;p&gt;While I&amp;#39;ve only had a day with Coda, I must admit that something feels a bit…off. It doesn&amp;#39;t feel as intuitive as I would have expected from Panic. Frequently, I find myself confused over how to execute simple operations. &amp;quot;Oh, I have to double-click to open this file.&amp;quot; There&amp;#39;s also no denying that the following is initially very confusing:&lt;/p&gt;
&lt;div class='tutorial_image'&gt;&lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2048_CodaReview/confusing.jpg' alt='image' title='' border='0'&gt;&lt;/div&gt;
&lt;p&gt;So we have a sidebar of files, then another panel in the middle for files, and then, lastly, remote files. This is what I was greeted to after opening Coda for the first time.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve since learned that you have to get away from the notion that the traditional sidebar is specifically for displaying files. In the image above, it just happens to be set to the &amp;quot;Files&amp;quot; tab, which accounts for the doubled-files issue. Nonetheless, it took me a moment to come to grips with this. &lt;/p&gt;
&lt;h3&gt;Will I Switch to Coda 2?&lt;/h3&gt;
&lt;p&gt;There&amp;#8217;s this part of me that wants to use Coda. It&amp;#8217;s beautiful and feels modern. But, then again, the simple fact is that I&amp;#8217;m far more efficient in Sublime Text 2. After years of waiting, I was hoping for more. Bells and whistles are great,  but, when you get down to it, there&amp;#8217;s nothing overly innovative here. But that&amp;#8217;s just me; what do you think?&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;You might be wondering why I haven&amp;#8217;t mentioned the new Air Preview feature. Well, I&amp;#8217;d very much like to, but haven&amp;#8217;t yet been able to get it to work. I&amp;#8217;ll update this article once I do!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-7crzrL26WCIf6VEbyxZg0FIfyk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-7crzrL26WCIf6VEbyxZg0FIfyk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-7crzrL26WCIf6VEbyxZg0FIfyk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-7crzrL26WCIf6VEbyxZg0FIfyk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=hirPYWLLtiU:Gyu_mKWf454:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=hirPYWLLtiU:Gyu_mKWf454:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=hirPYWLLtiU:Gyu_mKWf454:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=hirPYWLLtiU:Gyu_mKWf454:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=hirPYWLLtiU:Gyu_mKWf454:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=hirPYWLLtiU:Gyu_mKWf454:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=hirPYWLLtiU:Gyu_mKWf454:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=hirPYWLLtiU:Gyu_mKWf454:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/hirPYWLLtiU" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/articles/reviews/coda-2-review/feed/</wfw:commentRss>
		<slash:comments>203</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/articles/reviews/coda-2-review/</feedburner:origLink></item>
		<item>
		<title>3 Key Software Principles You Must Understand</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/y3EAv29KUd8/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/3-key-software-principles-you-must-understand/#comments</comments>
		<pubDate>Wed, 23 May 2012 15:57:55 +0000</pubDate>
		<dc:creator>Chris Peters</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25161</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25161&amp;c=1681941185' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25161&amp;c=1681941185' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;If you&amp;#8217;re in software development, new techniques, languages and concepts pop up all of the time. We all feel those nagging doubts every now and then: &amp;#8220;can I keep up with the changes and stay competitive?&amp;#8221; Take a moment, and sum a line from my favourite movie, Casablanca: &amp;#8220;The fundamental things apply, as time goes by.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25161"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;What&amp;#8217;s true for love, is true for code.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
What&amp;#8217;s true for love, is true for code. The fundamental things will always apply. If you have an understanding of the underlying ideas of software development, you will quickly adjust to new techniques. In this tutorial, we will discuss three basic principles and mix them with many more. They provide a powerful way of managing the complexity of software. I&amp;#8217;ll share some of my personal opinions and thoughts, which, hopefully, will prove useful when it comes to applying them to code and real-world projects.
&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;Principle &amp;#8211; &lt;/span&gt;Don&amp;#8217;t Repeat Yourself&lt;/h2&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;A basic strategy for reducing complexity to managable units is to divide a system into pieces.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
This principle is so important to understand, that I won&amp;#8217;t write it twice! It&amp;#8217;s commonly referred to by the acronym, DRY, and came up in the book &lt;em&gt;&lt;a href="http://www.amazon.com/gp/product/020161622X/ref=as_li_ss_tl?ie=UTF8&amp;#038;tag=nett02-20&amp;#038;linkCode=as2&amp;#038;camp=1789&amp;#038;creative=390957&amp;#038;creativeASIN=020161622X"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;/em&gt;, by Andy Hunt and Dave Thomas, but the concept, itself, has been known for a long time. It refers to the smallest parts of your software.&lt;/p&gt;
&lt;p&gt;
When you are building a large software project, you will usually be overwhelmed by the overall complexity. Humans are not good at managing complexity; they&amp;#8217;re good at finding creative solutions for problems of a specific scope. A basic strategy for reducing complexity to managable units is to divide a system into parts that are more handy. At first, you may want to divide your system into components, where each component represents its own subsystem that contains everything needed to accomplish a specific functionality.
&lt;/p&gt;
&lt;p&gt;For example, if you&amp;#8217;re building a content management system, the part that is responsible for user management will be a component. This component can be divided into further subcomponents, like role management, and it may communicate with other components, such as the security component.&lt;/p&gt;
&lt;p&gt;As you divide systems into components, and, further, components into subcomponents, you will arrive at a level, where the complexity is reduced to a single responsibility. These responsibilities can be implemented in a class (we assume that we&amp;#8217;re building an object-oriented application). Classes&lt;br /&gt;
contain  methods and properties. Methods implement algorithms. Algorithms and &amp;#8211; depending on how obsessive we want to get &amp;#8211; subparts of&lt;br /&gt;
algorithms are calculating or containing the smallest pieces that build your business logic.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The DRY principle states that these small pieces of knowledge may only occur exactly once in your entire system.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;They must have a single representation within it.
&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Note the difference between the &lt;em&gt;piece of knowledge&lt;/em&gt;, and its &lt;em&gt;representation&lt;/em&gt;. If we&amp;#8217;re implementing the database connection in our CMS, we will have a code snippet that will initalize the database driver, pass the credentials, and save a reference to the connection in a variable. The code snippet is part of the knowledge, it&amp;#8217;s about &lt;em&gt;how something is achieved&lt;/em&gt;. The variable with the reference to the connection is the representation of that knowledge &amp;#8211; and this can be used by other parties. If the database credentials change, we will have to change the snippet &amp;#8211; not its representation.
&lt;/p&gt;
&lt;p&gt;
In a perfect application, every small piece of business logic encapsulates its knowledge in a representation, namely a variable or a class property.&lt;br /&gt;
This variable itself is encapsulated in a class that can be described as a representation of a responsibility. The class is encapsulated in a component that can be described as a representation of functionality.&lt;/p&gt;
&lt;p&gt;This can be proceeded until we reach the top level of our software project &amp;#8211; that is, a stack of representations with increasing complexity. This way of looking at the complexity of software is called modular architecture, and DRY is an important part of it.
&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2047_softwarePrinciples/dry.png" border="0" /&gt;
&lt;div&gt;Software architecture is about managing complexity.&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Achieving DRYness&lt;/h3&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;DRY is a philosophy that packages logic into representations.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
There are many ways of achieving DRYness. Hunt and Thomas suggested (among other things) code generators and data transforming. But, essentially, DRY is a philosophy that packages logic into representations.
&lt;/p&gt;
&lt;p&gt;
As every part of your application can be seen as representation, every part exposes specific fragments of your underlying logic: The user management exposes access to registered users of the CMS, the user class represents a single user and exposes his properties (like the username). It retrieves the properties, via the representation of the database.&lt;/p&gt;
&lt;p&gt;DRY and modular architecture require good planning. To achieve a representational hierachy from bottom-up, divide your application in a hierarchy of logically separated smaller parts and let them communicate with each other. If you have to manage larger projects, organizing them into components and using DRY within the components is a good idea. Try to apply the following rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make a visual hierarchy of your software application and map the main components to it. Complex projects may require a dedicated map for each component.&lt;/li&gt;
&lt;li&gt;If you&amp;#8217;re arriving at a level of connected responsibilities, you may want to switch to UML diagrams (or similar).&lt;/li&gt;
&lt;li&gt;Before writing a chunk of code, name its hierarchy in your software project. Define what it&amp;#8217;s representing, and be sure you know its role in the surrounding component.&lt;/li&gt;
&lt;li&gt;Define what the representation should expose to other parties (like functions to execute SQL in a database driver) and what it should hide (like the database credentials).&lt;/li&gt;
&lt;li&gt;Ensure that representations do not rely on representations of another complexity level (like a component that relies on a class in another component).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The database driver is a simplified example, as there are many more layers involved in the real world (such as a specific database abstraction layer), and there is much more you can do to encapsulate logic &amp;#8211; especially diving into design patterns. But even if you&amp;#8217;ve just started with coding, there&amp;#8217;s one thing to keep in mind:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;When you find yourself writing code that is similiar or equal to something you&amp;#8217;ve written before, take a moment to think about what you&amp;#8217;re doing and don&amp;#8217;t repeat yourself.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
In the real world, applications that are a 100% DRY are hard, if not impossible, to achieve. However, applications that are unDRY to an unacceptable degree &amp;#8211; and therefore hard to maintain &amp;#8211; are quite common. Hence, it&amp;#8217;s not surprising to learn that more than 50% of all software projects fail &amp;#8211; if you&amp;#8217;re taking a look at the code. &lt;/p&gt;
&lt;p&gt;
Many people tend to think that bad code is produced by bad coders. In my experience, this is very much an exception. More often than not, bad code is produced by bad account managers and an overall misconfiguration of process management in companies.
&lt;/p&gt;
&lt;blockquote class="pullquote pqRight"&gt;&lt;p&gt;Bad code is rarely produced by bad coders.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;An Example&lt;/h3&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;DRYness is achieved by good planning.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
As an example, say you&amp;#8217;re hired as a technical consultant by a company that has problems with code quality and maintenance. You review the source and you see hacks and code duplication &amp;#8211; the code is not DRY. This is a symptom of bad code quality, it&amp;#8217;s not the reason. If you take a look at the version control system &amp;#8211; aka the history of the code &amp;#8211; chances are that you may find hacks that were introduced at times near deadlines and milestones. Take the time to review what changes are made, and you will likely be confronted with a change in requirements.
&lt;/p&gt;
&lt;p&gt;As noted above, DRYness is achieved by good planning. Forced changes on a tough deadline are forcing developers to implement dirty solutions. Once the code is compromised, the principle of DRY is likely to be sacrificed completely upon further changes.
&lt;/p&gt;
&lt;p&gt;
There&amp;#8217;s a reason why the most successful corporations in the IT business were founded by people with very good technical understanding &amp;#8211; or even coders themself: Bill Gates, Mark Zuckerberg, Steve Wozniak, Steve Jobs, Larry Page, Sergey Brin and Larry Ellison know (or knew) what efforts are needed to implement something. Contrary, many companies tend to lay the requirements for engineering into the hands of account managers, and the conceptual part in the hands of business consultants&amp;#8230;&lt;strong&gt;people who have never implemented anything.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;Hence, many technical concepts work only in Powerpoint, Photoshop, and on 27&amp;#8243; widescreen displays. This may have been a successful approach in the days of, more or less, static websites, but it&amp;#8217;s not nowadays &amp;#8211; with interactive applications on multiple devices. Because coders are the last in the line, they are the ones who have to apply quick fixes on errors in the concept. If this is accompanied by an account manager, who can&amp;#8217;t stand up to a client that likes to make last-minute changes, plans are thrown in the garbage, and something quick and dirty is implemented. The code becomes unDRY.
&lt;/p&gt;
&lt;p&gt;
This example is a bit extreme (nevertheless, I have witnessed such scenarios), but it demonstrates that DRY is a theoretical concept, which is challenged by various parties in the real world. If you&amp;#8217;re working in a company that forces you to work in this manner, you might suggest some changes to the process (like introducing technical expertise at an earlier stage of technical projects). &lt;/p&gt;
&lt;p&gt;If you have a hands-off approach, keep reading! The &lt;em&gt;You ain&amp;#8217;t gonna need it&lt;/em&gt; principle will come to the rescue.
&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;Principle &amp;#8211; &lt;/span&gt;Keep it Simple Stupid&lt;/h2&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;The simplest explanation tends to be the right one.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
In the late 19th century, physicists struggled to explain how gravity, magnetism and optics interact, when it comes to large distances &amp;#8211; like the distances in our solar system. Hence, a medium named aether was postulated. It was said, that light is traveling through this medium, and that it&amp;#8217;s responsible for effects that couldn&amp;#8217;t be explained otherwise. Through the years, the theory was expanded with assumptions that adjusted the aether postulate to the results of experiments. Some assumptions were arbitrary, some introduced other problems, and the whole theory was quite complex.
&lt;/p&gt;
&lt;p&gt;
An employee of the swiss patent office, Albert Einstein, suggested to get rid of the whole aether theory when he introduced a simple, yet revolutionary idea: All the oddness in calculating with large distances would fade away if we&amp;#8217;d accept that time is not a constant; it&amp;#8217;s relative. This incredibly of out-of-the-box thinking to come to the simplest explanation with the fewest assumptions to select between competing scenarios is referred to as &lt;em&gt;Ockhams&amp;#8217;s Razor&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;There are similar concepts in many areas. In software development (and others), we refer to it as KISS. There are many variants for this acronym, but they all mean that you should strive for the simplest way of doing something.
&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2047_softwarePrinciples/Einstein1921_by_F_Schmutzer_2.jpg" border="0" /&gt;
&lt;div&gt;Substantial progress in the history of mankind was achieved by lateral thinkers.&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;HTTP&lt;/h3&gt;
&lt;p&gt;The &lt;em&gt;Hypertext Transfer Protocol&lt;/em&gt; is widely considered to be a perfect example for a simple solution: designed to transfer hypertext based documents, it is the backbone of highly interactive and desktop-esque applications nowadays. Maybe we have to find solutions for limitations in the protocol, and maybe we have to replace it someday. However, status quo is: based on a few request methods (like GET and POST), status codes and plain text arguments, HTTP has proved to be flexible and robust. That&amp;#8217;s why HTTP has been repeatedly pushed to the limits by web developers &amp;#8211; and is still standing.&lt;/p&gt;
&lt;p&gt;
We take this approach for granted, but the history of software development and standardization is full of overly complex and half-baked solutions. There&amp;#8217;s even a dedicated made-up word for it: bloatware. Software like this is also described to be &lt;em&gt;DOD&lt;/em&gt;, dead on arrival. I have a theory that is very similar to my theory of unDRY code, when it comes to bloatware &amp;#8230; However, the success of the internet can be described as a success of simple, yet efficent solutions.
&lt;/p&gt;
&lt;p&gt;
So what&amp;#8217;s required to come to the simplest solution possible? It all comes down to maintainability and comprehensibility in software development. Hence, KISS kicks in during the phase of requirements engineering. When you think about how to transform a client&amp;#8217;s requirements to implementable components, try to identify the following parts:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functionality that has an inappropriate ratio between benefit and efforts.&lt;/li&gt;
&lt;li&gt;Functionality that is highly dependent on other functionality.&lt;/li&gt;
&lt;li&gt;Functionality that is likely to grow in complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;There are many people involved in the conceptual process, who do not have the technical expertise to make a reliable cost-benefit analysis&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I was once working on a project, where the client wanted to import Excel spreadsheets into his crew management software. This was a clear match. Excel is a proprietary software with a complex document format. The format is complex, because it&amp;#8217;s feature-rich: You can add graphs and other things to it &amp;#8211; features that were not needed by the client. He was simply interested in the numbers. Thus, implementing the Excel import would require the implementation of a lot of unnecessary functionality. On top of that, there are multiple versions of Excel versions, and Microsoft fires off another release each year. This would have been hard to maintain, and it comes with additional costs in the future.&lt;/p&gt;
&lt;p&gt;We ended up implementing a comma-separated-value import. This was done with a few lines of code. The overhead of the data was really small (compare an Excel sheet to it&amp;#8217;s CSV equivalent) and the solution was maintainable and future-proofed. Excel was ready to export CSV anyway (as well as other programs that the client might want to use in the future). Since the solution was low-priced as well, it was a good application of the KISS principle.&lt;/p&gt;
&lt;p&gt;To sum up: try to think out-of-the box if a task looks complicated to you. If someone is explaining to you his requirements, and you&amp;#8217;re thinking that it&amp;#8217;ll be tough and complex to implement, you&amp;#8217;re right under almost any circumstances. While some things are just that &amp;#8211; hard to implement &amp;#8211; overcomplicated solutions are quite usual. This is the case because there are many people involved in the conceptual process, who do not have the technical expertise to make a reliable cost-benefit analysis. Hence, they don&amp;#8217;t see the problem. Double-check the requirements whether they are really stripped down to the essence that the client needs. Take the time to discuss critical points and explain why other solutions might be more suitable.
&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;span&gt;Principle &amp;#8211; &lt;/span&gt;You &amp;#8220;Ain&amp;#8217;t Gonna Need It&lt;/h2&gt;
&lt;blockquote class="pullquote pqRight"&gt;
&lt;p&gt;Coding is about building things.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
When Google+ launched, Mark Zuckerberg &amp;#8211; founder of Facebook &amp;#8211; was one of the first who created an account in the social network that was aiming to take his own down. He added just one line to the &lt;em&gt;About me&lt;/em&gt; section: &amp;raquo;I&amp;#8217;m building things.&amp;laquo;. I honestly think that this is a brilliant sentence, because it describes the pure essence of coding in a few simple words. Why did you decide to become a coder? Enthusiasm for technical solutions? The beauty of efficiency? Whatever your answer is, it may not be &lt;em&gt;&amp;raquo;building the 1.000.001th corporate website with standard functionality&amp;laquo;&lt;/em&gt;. However, most of us are making money that way. No matter where you are working, you&amp;#8217;ll likely be confronted with boring and repetitive tasks every now and then.
&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;80% of the time spent on a software project is invested in 20% of the functionality.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
The &lt;em&gt;You ain&amp;#8217;t gonna need it&lt;/em&gt; principle (YAGNI) deals with these tasks. It basically translates to: If it&amp;#8217;s not in the concept, it&amp;#8217;s not in the code. For example, it&amp;#8217;s a common practice to abstract the database access in a layer that handles the differences between various drivers, like MySQL, PostgreSQL and Oracle. If you&amp;#8217;re working on a corporate website that is hosted on a LAMP stack, on a shared host, how likely is it that they will change the database? Remember that the concept was written with budget in mind. &lt;/p&gt;
&lt;p&gt;
If there&amp;#8217;s no budget for database abstraction, there&amp;#8217;s no database abstraction. If the unlikely event of a database change does occur, it&amp;#8217;s a natural thing to charge for the change request.&lt;/p&gt;
&lt;p&gt;
You may have noticed the difference between &lt;em&gt;You ain&amp;#8217;t gonna need it&lt;/em&gt; and &lt;em&gt;DRY&lt;/em&gt;-driven modular architectures: The latter is reducing complexity by dividing a project into manageable components, while the former is reducing complexity by reducing the number of components. YAGNI is similar to the &lt;em&gt;KISS&lt;/em&gt; principle, as it strives for a simple solution. However, KISS strives for a simple solution by trying to implement something as easily as possible; YAGNI strives for simplicity by not implementing it at all! &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Theodore Sturgeon&lt;/em&gt;, an American sci-fi author, stated the law: &lt;em&gt;&amp;raquo;ninety percent of everything is crap&amp;laquo;&lt;/em&gt;. This is a very radical approach, and not overly helpful in real-world projects. But keep in mind that &amp;#8220;crap&amp;#8221; can be very time consuming. A good rule of thumb is: roughly 80% of the time spent on a software project is invested in 20% of the functionality. Think about your own projects! Everytime I do, I am surprised by the accuracy of the 80:20 rule.
&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2047_softwarePrinciples/8020.png" border="0" /&gt;
&lt;div&gt;80% of the time spend on a software project is invested in 20% of the functionality.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
If you&amp;#8217;re in a company that is notorious for tight deadlines and imprecise concepts, this is a powerful strategy. You won&amp;#8217;t be rewarded for implementing a database abstraction layer. Chances are that your boss does not know what a database abstraction layer even is.
&lt;/p&gt;
&lt;p&gt;
While this concept may sound simple, it can be hard to differ the necessary from the unnecessary parts. For example, if you&amp;#8217;re comfortable with a library or a framework that uses database abstraction, you won&amp;#8217;t save much time in dumping it. The key concept is another way of looking  at software: we&amp;#8217;re trained to write future-proof and maintainable software. This means that we are trained to think ahead. What changes may occur in the future? This is critical for bigger projects, but overhead for smaller ones. Don&amp;#8217;t think into the future! If a small corporate website does fundamental changes, they may have to start from scratch. This is not a significant problem compared to the overall budget.
&lt;/p&gt;
&lt;h3&gt;Planning a Project&lt;/h3&gt;
&lt;p&gt;When you&amp;#8217;re preparing your to-do list for a project, consider the following thoughts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Achieve lower complexity by reducing the level of abstraction.&lt;/li&gt;
&lt;li&gt;Separate functionality from features.&lt;/li&gt;
&lt;li&gt;Assume moderate non-functional requirements.&lt;/li&gt;
&lt;li&gt;Identify time consuming tasks and get rid of them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;#8217;s go a little bit into detail! I already provided an example for the first item in the list: don&amp;#8217;t wrap a database driver around a database abstraction layer. Be suspicious of everything that adds complexity to your software stack. Notice that abstraction is often provided by third party libraries. For example &amp;#8211; depending on your programming language -, a persistence layer, like Hibernate (Java), Doctrine (PHP) or Active Record (Ruby) comes with database abstraction and object-relational mapping. Each library adds complexity. It has to be maintained. Updates, patches and security fixes have to be applied.&lt;/p&gt;
&lt;p&gt;We implement features everyday, because we anticipate them to be useful. Hence, we think ahead and implement too much. For example, many clients want to have a mobile website. Mobile is a term of wide comprehension; it&amp;#8217;s not a design decision. It&amp;#8217;s a use case! People who are using a mobile website are, well, mobile. That means they may want to access other information or functionality than a user who visits the site laid back at his desktop. Think of a cinema site: Users on the bus will likely want to access the starting time of upcoming movies, not the 50 MB trailer.&lt;/p&gt;
&lt;blockquote class="pullquote pqRight"&gt;
&lt;p&gt;Bad concepts can often be identified by the lack of non-functional requirements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; With an appropriate budget, you would perform a dedicated analysis of the requirements for mobile. Without this analysis, you will simply provide the same information as is on the desktop site. This will be just fine for many circumstances! Because mobile browsers are very clever in adjusting desktop sites to their display, a radical YAGNI approach might be to not write a mobile site at all!
&lt;/p&gt;
&lt;p&gt;Non-functional requirements do not describe behaviour of a software, they describe additional properties that can be used to judge the quality of software. Since describing software quality presumes knowledge about software, bad concepts can often be identified by the lack of non-functional requirements.  Maintainability, level of documentation, and ease of integration are examples for non-functional requirements. Non-functional requirements should be measurable. Hence, &lt;em&gt;&amp;raquo;The page should load fast.&amp;laquo;&lt;/em&gt; is too inconcrete, &lt;em&gt;&amp;raquo;The page should load in two seconds max during an average performance test.&amp;laquo;&lt;/em&gt; is very concrete and measurable. If you want to apply the YAGNI principle, assume moderate non-functional requirements if they are not mentioned in the concept (or if they are mentioned, but inconcrete). If you are writing the non-functional requirements yourself, be realistic: A small corporation with 20-50 page visits a day does not require three days of performance tweaking &amp;#8211; as the page should load fast enough because the server is not busy. If the corporation can increase the number of daily visits, a better server or hosting package shouldn&amp;#8217;t be too expensive.
&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;Last, but not least, remember the 80:20 rule-of-thumb!&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Last, but not least, remember the 80:20 rule-of-thumb! We have to identify the time consuming parts. If a part is absolutly necessary, you have to implement it. The question should be: how will you implement it? Does it have to be the latest framework with a small community? Do you need to switch to the just-released version of a library if the documentation is not up to date? Should you use the new CMS, when not all extensions are available? How much research will be necessary to do so? &lt;em&gt;&amp;raquo;That&amp;#8217;s the way we have always done it.&amp;laquo;&lt;/em&gt; is not an exciting approach, but it&amp;#8217;ll get the job done without surprises.
&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s important to understand that all of this does not mean that you can start writing dirty code with hacks along the way! You&amp;#8217;re writing a lightweight application, not a messy one! However, &lt;em&gt;You ain&amp;#8217;t gonna need it&lt;/em&gt; is a practical approach. If it would cause many lines of code to reduce a few lines of code duplicates, I personally think that you may relate efforts to budget and some unDRYness is ok. It&amp;#8217;s a small application. Hence, the added maintenance complexity is acceptable. We&amp;#8217;re in the real-world.
&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s come back to the inital thought: we like building things. When Beethoven wrote the &lt;em&gt;Diabelli Variations&lt;/em&gt;, it was contract work. I don&amp;#8217;t think he made compromises on budget. He ran the extra mile, because he did not want to write average music; he wanted to write a perfect composition. &lt;/p&gt;
&lt;p&gt;I&amp;#8217;m certainly not implying that we&amp;#8217;re all geniuses, and that our brilliance should shine through every line of code, but I like to think of software architecture as compositions. I&amp;#8217;m a passionate developer, because I want to build perfect compositions, and I want to be proud of the things I&amp;#8217;m building. &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;If you want to be an experienced and business-proofed developer, you have to master the &lt;em&gt;You ain&amp;#8217;t gonna need it&lt;/em&gt; principle. If you want to keep your passion, you have to fight against it every now and then.&lt;/p&gt;&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Software principles are a way of looking at software. To me, a good principle should be based on a simple concept, but it should evolve to a complex construct of ideas when confronted with other techniques and philosophies. What are your favourite software principles?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pxi-9J8xduTk_sEFDjWUm3QgJT4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pxi-9J8xduTk_sEFDjWUm3QgJT4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pxi-9J8xduTk_sEFDjWUm3QgJT4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pxi-9J8xduTk_sEFDjWUm3QgJT4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=y3EAv29KUd8:IRWKhUaYsOA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=y3EAv29KUd8:IRWKhUaYsOA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=y3EAv29KUd8:IRWKhUaYsOA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=y3EAv29KUd8:IRWKhUaYsOA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=y3EAv29KUd8:IRWKhUaYsOA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=y3EAv29KUd8:IRWKhUaYsOA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=y3EAv29KUd8:IRWKhUaYsOA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=y3EAv29KUd8:IRWKhUaYsOA:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/y3EAv29KUd8" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/3-key-software-principles-you-must-understand/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/tools-and-tips/3-key-software-principles-you-must-understand/</feedburner:origLink></item>
		<item>
		<title>SSH: What and How</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/CBDYIApMmps/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/ssh-what-and-how/#comments</comments>
		<pubDate>Tue, 22 May 2012 21:10:32 +0000</pubDate>
		<dc:creator>Jonathan Cutrell</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[terminal]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25138</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25138&amp;c=137393456' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25138&amp;c=137393456' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;Many web developers use SSH (&amp;#8220;Secure Shell&amp;#8221;) on a daily basis to manage their servers, back up files, work remotely, and a myriad of other tasks. Today, I&amp;#8217;ll explain what SSH is, do a brief history review, and, lastly, teach you how to set it up on your remote server or even your local network. Let&amp;#8217;s get started!&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25138"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;A Starting Explanation&lt;/h2&gt;
&lt;p&gt;
If you&amp;#8217;re reading this, it&amp;#8217;s likely that you&amp;#8217;re at least somewhat acquainted with Terminal (or on Windows, something like Cygwin). If so, then you will understand this quick functional explanation of SSH.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;SSH is essentially using a network connection to get into Terminal on another computer.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If you aren&amp;#8217;t familiar with Terminal, there are a &lt;a href="http://net.tutsplus.com/articles/web-roundups/10-terminal-commands-that-will-boost-your-productivity/"&gt;lot of explanations&lt;/a&gt; and beginner&amp;#8217;s guides to Terminal, both here on Nettuts+ and elsewhere. The power of SSH is reliant on its simplicity; by offering you access to the Terminal of another machine, SSH cuts to the chase and gives you full control over a remote machine. If you understand the power of Terminal and its direct connection to the inner workings of your local machine, then you understand the power of SSH!
&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;A Brief History&lt;/h2&gt;
&lt;p&gt;SSH was developed in its infant state in 1995. The primary developer, Tatu Ylonen, developed it as the first secure way to administrate a remote UNIX system. Previous to SSH, the only tools that existed sent information like passwords in clear text. &lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;So, How Do I Use It?&lt;/h2&gt;
&lt;p&gt;There are a million guides out there on how to get set up with SSH. We will specifically cover one method today. First things first, you&amp;#8217;ll want to make sure you have SSH on your system.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mac &amp;#8211; &lt;/strong&gt;A version of OpenSSH comes preinstalled.
&lt;li&gt;&lt;strong&gt;Windows &amp;#8211; &lt;/strong&gt;Follow a guide &lt;a href="http://pigtail.net/LRP/printsrv/cygwin-sshd.html"&gt;like this one&lt;/a&gt; or &lt;a href="http://inside.mines.edu/~gmurray/HowTo/sshNotes.html"&gt;this one&lt;/a&gt; to get Cygwin and the &amp;#8220;openssh&amp;#8221; package installed.
&lt;li&gt;&lt;strong&gt;Linux &amp;#8211; &lt;/strong&gt;OpenSSH is highly likely to be installed already, but if it isn&amp;#8217;t, you can follow &lt;a href="http://inside.mines.edu/~gmurray/HowTo/sshNotes.html"&gt;the same guide&lt;/a&gt; to get it installed.
&lt;/ul&gt;
&lt;p&gt;To determine if SSH is installed, run &lt;code&gt;`which ssh`&lt;/code&gt;. If Terminal returns something along the lines of &lt;code&gt;/usr/bin/ssh&lt;/code&gt;, then you&amp;#8217;re good to go! Otherwise, follow one of these guides to get it installed.
&lt;/p&gt;
&lt;p&gt;In this article, I will assume the version you are using is OpenSSH; there are some configuration differences that depend on your version of SSH. We will be explaining how to set up a Mac to connect to a MediaTemple server through a single SSH command. Once you have SSH installed on your machine, you will need to make sure your target host has SSH enabled. SSH runs over port 22 by default; you can use a command line tool like &lt;code&gt;nmap&lt;/code&gt; to ping your server to determine if port 22 is accepting incoming connections, like this:&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
sudo nmap -sS hostname.com
&lt;/pre&gt;
&lt;p&gt;Of course, you probably have access to the administrative interface for the server. Make sure you look through the options and enable SSH. On a Mediatemple server, this configuration is located under the Server Control panel. Mediatemple SSH is accessible by using root@primarydomain.com. You can add users to the account, but for the sake of keeping things simple, we will use root@primarydomain.com.&lt;/p&gt;
&lt;p&gt;Once SSH is enabled (and you have set a root password in your server admin), you can run the following line to SSH into your server.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
	ssh root@primarydomain.com
	&lt;/pre&gt;
&lt;p&gt;&amp;#8230;where primarydomain.com is your MediaTemple primary domain. You will then be prompted for your password (which is the root password you set in the control panel). If you are not using MediaTemple, you can SSH directly to the IP address of your server as well.&lt;/p&gt;
&lt;p&gt;If using shared hosting, it is likely that you will not be logging in as root. Instead, you will log in with a user account name. For example, if you are using a service like Site5, you may log in with a username at a subdomain, like this:&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
	ssh username@malta.site5.com
	&lt;/pre&gt;
&lt;p&gt;	Ultimately, these configurations will depend on your specific web server company. Refer to your host&amp;#8217;s documentation for more information.&lt;/p&gt;
&lt;p&gt;Once you are &amp;#8220;shelled in&amp;#8221;, you can execute commands and traverse the file system within Terminal. Depending upon on your level of access, you may be able to install things on your server using apt-get or wget commands. You can manage your Apache server, edit configuration files with a Terminal-based text editor, view error logs, clear caches, view files directly on a server to make sure they are the correct version, and plenty of other lower-level system administration tasks. Now, what if you wanted to do &lt;em&gt;more, faster&lt;/em&gt; with SSH?&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;How Do I Use It&amp;#8230; Better?&lt;/h2&gt;
&lt;p&gt;There are a ton powerful things that SSH opens you up to. We will skip a few of them (as quite a few are more sysadmin-related, like tunneling). But we will go over a few useful tricks.&lt;/p&gt;
&lt;h3&gt;Super-quick Log-in&lt;/h3&gt;
&lt;p&gt;You&amp;#8217;re thinking to yourself, &amp;#8220;seems like there should be a faster way to do this.&amp;#8221; You&amp;#8217;re right. And there is. Instead of having to remember your domain, password, and username for every server, you can set up a few configurations that will allow you to speed up the process to something along these lines.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
	ssh myserver
	&lt;/pre&gt;
&lt;p&gt;With the right configuration, you could run this, and without having to enter any passwords, IP addresses, or long domain names, you&amp;#8217;re in! Again, we will assume you are logging into a MediaTemple server. First, we will generate &lt;em&gt;ssh keys&lt;/em&gt;. This is basically a set of encrypted keys that live in &lt;code&gt;~/.ssh&lt;/code&gt; on your local machine. You have a &amp;#8220;public&amp;#8221; key and a &amp;#8220;private&amp;#8221; key. So, first things first, open a new Terminal window and create the .ssh folder in your home directory.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
	mkdir ~/.ssh
&lt;/pre&gt;
&lt;p&gt;Next you will generate your keys with the following line. (This comes directly from MediaTemple&amp;#8217;s documentation.)&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
	ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -C &amp;quot;Comment about your key goes here.&amp;quot;
&lt;/pre&gt;
&lt;p&gt;This line will generate an ssh key of type rsa, with 2048 bits (for security), at the file location specified, with the comment specified. You will be promprted for a password, but it isn&amp;#8217;t mandatory or necessary; not providing a password will enable you to automatically log in. The RSA type is for SSH protocol version 1. Type DSA is for protocol version 2. Check with your web server to find out which version they are using. Once your keys are generated, you will then run this to make sure your SSH configurations are set to the right permissions.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
chmod 700 ~/.ssh &amp;amp;&amp;amp; chmod 600 ~/.ssh/*
&lt;/pre&gt;
&lt;p&gt;Next, you will upload your public key to your server. There are quite a few ways to do this; this way comes from MediaTemple&amp;#8217;s docs as well.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
cat ~/.ssh/id_rsa.pub | ssh root@example.com 'cat - &amp;gt;&amp;gt; ~/.ssh/authorized_keys'
&lt;/pre&gt;
&lt;p&gt;This code is echoing your id_rsa.pub through a `|` (pipe) into the next command, which is an SSH into root@example.com, where you will run an echo and concatenation of what you piped in the first command. It sounds a bit complicated, so there are a few alternative ways to handle this. Essentially, you are going to want no line breaks and your public key on its own line in a file, called &lt;code&gt;authorized_keys&lt;/code&gt; on your server in the ~/.ssh/ directory. So, if this is the first or only key you want on your server, you could run this command to copy it directly to that location.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
scp ~/.ssh/id_rsa.pub root@example.com:.ssh/authorized_keys
&lt;/pre&gt;
&lt;p&gt;This line is essentially saying, &amp;#8220;copy this first file through SSH to the server at this location relative to my current home directory.&amp;#8221;&lt;/p&gt;
&lt;p&gt;Once your authorized_keys contains your public key, you can attempt to login to the server with ssh username@example.com. If you put your public key in the root user directory&amp;#8217;s SSH configuration files, you will be able to login directly to root. You will be asked about a rsa fingerprint; go ahead and allow this action. It adds the server you are connecting to to a known_hosts file. This file can be used for a lot of different things, but particularly to secure yourself against what is called a &amp;#8220;man-in-the-middle&amp;#8221; attack. If you&amp;#8217;d like to read a little more about this, check out &lt;a href="http://www.jfranken.de/homepages/johannes/vortraege/ssh1_inhalt.en.html#ToC17"&gt;this explanation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you can successfully log into your server, as if you had entered a password, your keys are working properly. The next step is to add a couple of lines for a shortcut to a configuration file on your machine . Open ~/.ssh/config in your favorite text editor (create it if it doesn&amp;#8217;t exist) and add the following:&lt;/p&gt;
&lt;pre class="brush: plain; title: ; notranslate"&gt;
Host shortname
HostName somehost.com
User username
&lt;/pre&gt;
&lt;p&gt;Where &amp;#8220;shortname&amp;#8221; is a nickname for the server you want to log into. For instance, &amp;#8220;Host myserver&amp;#8221; would allow me to do &lt;code&gt;ssh myserver&lt;/code&gt;. The HostName is your server location, and of course the User is your username. You may have &lt;code&gt;User root&lt;/code&gt; at this spot. Once this file is saved, you should be able to run a simple command to log into your server, like this:&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
ssh shortname
&lt;/pre&gt;
&lt;/p&gt;
&lt;h3&gt;Git Without a Hub&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Please Note: this section requires a bit of familiarity with &lt;a href="http://net.tutsplus.com/tutorials/other/easy-version-control-with-git/"&gt;Git&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can use SSH to set up your own Git repos on your server! This is useful for companies who don&amp;#8217;t want to expose their code on GitHub for whatever reason, and it&amp;#8217;s great to be able to push directly from a local machine to a Git repo on your own server.&lt;/p&gt;
&lt;p&gt;To set this up, make sure Git is installed on both the host and your local machine. You may have to go through your web server company to have Git installed. Next, run &lt;code&gt;git init&lt;/code&gt; on your server in the location that you want your Git repo to be. Of course, you can do this a hundred different ways, but if you prefer to not have a bare repository, you can use branches to push to from your local machine. Here is a common workflow.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;
	ssh user@example.com
	cd /path/to/repo
	git init
	git checkout -b staging
	git checkout master
	# disconnect from shell session using ctrl-d
	cd /local/repo
	git init
	git add .
	git commit -am &amp;quot;some message&amp;quot;
	git remote add origin user@example.com:/path/to/repo
	git checkout -b staging
	git push origin staging
	ssh user@example.com
	cd /path/to/repo
	git merge staging
&lt;/pre&gt;
&lt;p&gt;Essentially what is happening here is you are logging into the server, changing to the desired repo path, creating a repository and adding a &amp;#8220;staging&amp;#8221; branch which you can push to from your local machine. Then, you are creating your local repo and a corresponding &amp;#8220;staging&amp;#8221; branch on your local machine, and adding files to track to the repo. Next comes an initial commit. You are then adding the remote repository as an alias of &amp;#8220;origin&amp;#8221;. Next, you are pushing the local staging branch to the &amp;#8220;origin&amp;#8221; alias&amp;#8217;s staging branch. Finally, you are ssh&amp;#8217;ing back into the server and merging the &amp;#8220;staging&amp;#8221; branch with the default &amp;#8220;master&amp;#8221; branch.&lt;/p&gt;
&lt;h3&gt;SFTP &gt; FTP&lt;/h3&gt;
&lt;p&gt;You can also use SSH-powered FTP (file transfer protocol), which is essentially a more secure (encrypted) version of FTP that runs over port 22 (rather than the default FTP port 21). Most FTP clients support SFTP as well. &lt;a href="http://filezilla-project.org/"&gt;FileZilla&lt;/a&gt; (for Windows) and &lt;a href="http://fetch.en.softonic.com/mac/download"&gt;Fetch&lt;/a&gt; (for Mac) are two popular (and free) SFTP/FTP clients.&lt;/p&gt;
&lt;h3&gt;Easy Access to Your Server Almost Anywhere&lt;/h3&gt;
&lt;p&gt;As long as you are around a computer that is connected to the internet, has a Terminal, and has SSH installed (any Mac connected to WiFi, for instance), you can get access to your server, via SSH. That&amp;#8217;s the best part. You don&amp;#8217;t require any configuration (assuming you haven&amp;#8217;t set up any restrictions that &lt;em&gt;require&lt;/em&gt; a matching pubkey), you can log in with your username and password from practically anywhere. There are even SSH clients for iOS and other mobile devices. This is a very powerful feature of SSH that is only paralleled in portability by browser-based applications.&lt;/p&gt;
&lt;h3&gt;A Local Code Repo&lt;/h3&gt;
&lt;blockquote class=pullquote&gt;&lt;p&gt;Hopefully you can see the power of SSH in a daily development cycle.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Let&amp;#8217;s imagine that you and a few buddies are working on some code together. Let&amp;#8217;s also say you have a local computer that you have full control over that you use as a development LAMP server with a few VM&amp;#8217;s installed on it. You can use SSH locally to move files to and from your computer and the development machine. You can even set up a local Git (or svn, or Mercurial) repo, powered by SSH to keep everything in check. Perhaps you could even make the development machine the only machine that is connected to the remote server via SSH, so that the code &lt;em&gt;has&lt;/em&gt; to go through a specific staging process before it can be put into production. The backbone of all of these actions is SSH!&lt;/p&gt;
&lt;p&gt;Hopefully you can see the power of SSH in a daily development cycle, especially for teams using version control. As I noted previously, there is plenty of documentation and a myriad of other network-level tools based on or reliant upon SSH that will give you more control and power over your development process and your server. Who knows? Maybe, one day, you could double as a sysadmin after all!&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Some Other Helpful Links&lt;/h2&gt;
&lt;p&gt;Here are some other helpful links to get you started with SSH. It&amp;#8217;s been around for a while, so there is plenty of documentation floating around.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.openssh.com/manual.html"&gt;The official OpenSSH manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.linuxjournal.com/article/4412?page=0,0"&gt;Linux Journal&amp;#8217;s introduction to SSH&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1DdP9q7YfDzaX3N9q99AtC_wr00/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1DdP9q7YfDzaX3N9q99AtC_wr00/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1DdP9q7YfDzaX3N9q99AtC_wr00/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1DdP9q7YfDzaX3N9q99AtC_wr00/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=CBDYIApMmps:Ls6186ZklbE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=CBDYIApMmps:Ls6186ZklbE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=CBDYIApMmps:Ls6186ZklbE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=CBDYIApMmps:Ls6186ZklbE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=CBDYIApMmps:Ls6186ZklbE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=CBDYIApMmps:Ls6186ZklbE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=CBDYIApMmps:Ls6186ZklbE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=CBDYIApMmps:Ls6186ZklbE:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/CBDYIApMmps" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/ssh-what-and-how/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/tools-and-tips/ssh-what-and-how/</feedburner:origLink></item>
		<item>
		<title>Diving into CanJS</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/kA1zFDDzUPI/</link>
		<comments>http://net.tutsplus.com/tutorials/javascript-ajax/diving-into-canjs/#comments</comments>
		<pubDate>Mon, 21 May 2012 19:10:54 +0000</pubDate>
		<dc:creator>Curtis Cummings</dc:creator>
				<category><![CDATA[JavaScript & AJAX]]></category>
		<category><![CDATA[canjs]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25105</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25105&amp;c=1856585471' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25105&amp;c=1856585471' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;If you haven&amp;#8217;t heard, there&amp;#8217;s a new kid in town: &lt;a href="http://canjs.us/"&gt;CanJS&lt;/a&gt;. What better way to dive into what this new framework offers than to build a contacts manager application? When you&amp;#8217;re done with this three-part series, you&amp;#8217;ll have all the tools you need to build your own JavaScript applications!&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25105"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Choosing the Right Tool&lt;/h2&gt;
&lt;p&gt;Building a JavaScript application without the right tools is difficult. While jQuery is great at what it does, a DOM manipulation library doesn&amp;#8217;t provide any infrastructure for building applications. This is specifically why you need to use a library, like CanJS.&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;
&lt;p&gt;&lt;a href="http://canjs.us/"&gt;CanJS&lt;/a&gt; is a lightweight MVC library that gives you the tools you need to build JavaScript apps. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CanJS is a lightweight MVC library that gives you the tools you need to build JavaScript apps. It provides all the structure of the MVC (Model-View-Control) pattern, templates with live binding, routing support and is &lt;a href="http://bitovi.com/blog/2012/04/zombie-apocolypse.html"&gt;memory safe&lt;/a&gt;. It supports jQuery, Zepto, Mootools, YUI, Dojo and has a rich set of extensions and plugins.&lt;/p&gt;
&lt;p&gt;In part one, you will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a Control and View (client-side template) to display contacts&lt;/li&gt;
&lt;li&gt;Represent data using Models&lt;/li&gt;
&lt;li&gt;Simulate ajax responses using the fixtures plugin&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Excited? You should be! Now let&amp;#8217;s get coding.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Setting Up Your Folders And HTML&lt;/h2&gt;
&lt;p&gt;You&amp;#8217;ll need to create a folder for your application. Inside this folder, you need four sub-folders: &lt;code&gt;css&lt;/code&gt;, &lt;code&gt;js&lt;/code&gt;, &lt;code&gt;views&lt;/code&gt; and &lt;code&gt;img&lt;/code&gt;. Your folder structure should look like this when you&amp;#8217;re done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;contacts_manager
&lt;ul&gt;
&lt;li&gt;css&lt;/li&gt;
&lt;li&gt;js&lt;/li&gt;
&lt;li&gt;views&lt;/li&gt;
&lt;li&gt;img&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Save this as &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;CanJS Contacts Manager&amp;lt;/title&amp;gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;css/bootstrap.min.css&amp;quot;&amp;gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;css/contacts.css&amp;quot;&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;span12&amp;quot;&amp;gt;
          &amp;lt;h1&amp;gt;Contacts Manager&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;span3&amp;quot;&amp;gt;
          &amp;lt;div class=&amp;quot;well&amp;quot;&amp;gt;
            &amp;lt;nav id=&amp;quot;filter&amp;quot;&amp;gt;&amp;lt;/nav&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;span9&amp;quot;&amp;gt;
          &amp;lt;div id=&amp;quot;create&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
          &amp;lt;div id=&amp;quot;contacts&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;script src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;js/can.jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;js/can.fixture.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;js/contacts.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;p&gt;At the bottom of the page, we load jQuery, CanJS, the fixture plugin and your application code (&lt;code&gt;contacts.js&lt;/code&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The CSS and images for this tutorial are in included in the source files, which can be downloaded above.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Building Your UI With Views&lt;/h2&gt;
&lt;p&gt;Views are client-side templates that are used to render parts of your app. CanJS supports multiple templating languages, but this tutorial will be using EJS (Embedded JavaScript), which is packaged with CanJS and supports live binding.&lt;/p&gt;
&lt;p&gt;EJS templates look like HTML but with magic tags where you want dynamic behavior (using JavaScript). There are three types of magic tags in EJS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;% CODE %&gt;&lt;/code&gt; runs JavaScript code,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;%= CODE %&gt;&lt;/code&gt; runs a JavaScript statement, and writes the &lt;strong&gt;escaped&lt;/strong&gt; result into the resulting HTML,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;%== CODE %&gt;&lt;/code&gt; runs a JavaScript statement and writes the &lt;strong&gt;unescaped&lt;/strong&gt; result into the resulting HTML (used for sub-templates).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Templates can be loaded from a file or script tag. In this tutorial templates will be loaded from EJS files.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Displaying Contacts&lt;/h2&gt;
&lt;p&gt;To render contacts, you&amp;#8217;ll need an EJS template. Save the following code as &lt;code&gt;contactsList.ejs&lt;/code&gt; within your views folder:&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;ul class=&amp;quot;clearfix&amp;quot;&amp;gt;
  &amp;lt;% list(contacts, function(contact){ %&amp;gt;
    &amp;lt;li class=&amp;quot;contact span8&amp;quot; &amp;lt;%= (el)-&amp;gt; el.data('contact', contact) %&amp;gt;&amp;gt;
      &amp;lt;%== can.view.render('views/contactView.ejs', {
        contact: contact, categories: categories
      }) %&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;% }) %&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;contactLists.ejs&lt;/code&gt; will render a list of contacts. Let&amp;#8217;s examine the template code here in more detail:&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;% list(contacts, function(contact){ %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The EJS &lt;code&gt;list()&lt;/code&gt; helper invokes a callback function on each contact in the list. When used with an observable list, the &lt;code&gt;list()&lt;/code&gt; helper will use live binding to re-run anytime the length of the list changes.&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;li class=&amp;quot;contact span8&amp;quot; &amp;lt;%= (el)-&amp;gt; el.data('contact', contact) %&amp;gt;&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The code above uses an element callback to add the contact instance to the data of the &lt;code&gt;&amp;lt;li&gt;&lt;/code&gt;. Everything after the arrow is wrapped in a function that will be executed with &lt;code&gt;el&lt;/code&gt; set to the current element.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
&amp;lt;%== can.view.render('views/contactView.ejs', {
  contact: contact, categories: categories
}) %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This code renders the &lt;code&gt;contactView.ejs&lt;/code&gt; sub-template for each contact. &lt;code&gt;can.view.render()&lt;/code&gt; takes a template and data as its parameters and returns HTML.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Rendering A Single Contact&lt;/h2&gt;
&lt;p&gt;Sub-templates are an excellent way of organizing your views into manageable chunks. They also help simplify your templates and promote DRY (Don&amp;#8217;t Repeat Yourself). Later in this tutorial, you&amp;#8217;ll re-use this template to create contacts. Save this code as &lt;code&gt;contactView.ejs&lt;/code&gt; in your views folder:&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;a href=&amp;quot;javascript://&amp;quot; class=&amp;quot;remove&amp;quot;&amp;gt;&amp;lt;i class=&amp;quot;icon-remove&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;form&amp;gt;
&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;span2&amp;quot;&amp;gt;
    &amp;lt;img src=&amp;quot;img/contact.png&amp;quot; width=&amp;quot;100&amp;quot; height=&amp;quot;100&amp;quot;&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;span3&amp;quot;&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;name&amp;quot; placeholder=&amp;quot;Add Name&amp;quot;
      &amp;lt;%= contact.attr('name') ? &amp;quot;value='&amp;quot; + contact.name + &amp;quot;'&amp;quot; : &amp;quot;class='empty'&amp;quot; %&amp;gt;&amp;gt;
    &amp;lt;select name=&amp;quot;category&amp;quot;&amp;gt;
      &amp;lt;% $.each(categories, function(i, category){ %&amp;gt;
        &amp;lt;option value=&amp;quot;&amp;lt;%= category.data %&amp;gt;&amp;quot; &amp;lt;%= contact.category === category.data ? &amp;quot;selected&amp;quot; : &amp;quot;&amp;quot; %&amp;gt;&amp;gt;
          &amp;lt;%= category.name %&amp;gt;
        &amp;lt;/option&amp;gt;
      &amp;lt;% }) %&amp;gt;
    &amp;lt;/select&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;span3&amp;quot;&amp;gt;
    &amp;lt;label&amp;gt;Address&amp;lt;/label&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;address&amp;quot;
      &amp;lt;%= contact.attr('address') ? &amp;quot;value='&amp;quot; + contact.address + &amp;quot;'&amp;quot; : &amp;quot;class='empty'&amp;quot; %&amp;gt;&amp;gt;
    &amp;lt;label&amp;gt;Phone&amp;lt;/label&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;phone&amp;quot;
      &amp;lt;%= contact.attr('phone') ? &amp;quot;value='&amp;quot; + contact.phone + &amp;quot;'&amp;quot; : &amp;quot;class='empty'&amp;quot; %&amp;gt;&amp;gt;
    &amp;lt;label&amp;gt;Email&amp;lt;/label&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;email&amp;quot;
      &amp;lt;%= contact.attr('email') ? &amp;quot;value='&amp;quot; + contact.email + &amp;quot;'&amp;quot; : &amp;quot;class='empty'&amp;quot; %&amp;gt;&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Each property of a contact is placed in an &lt;code&gt;&amp;lt;input&gt;&lt;/code&gt; tag. These will be used to add and update a contact&amp;#8217;s information.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Making Your Views Live&lt;/h2&gt;
&lt;p&gt;Any time EJS encounters &lt;code&gt;attr()&lt;/code&gt; while processing a template, it knows that the surrounding code should be turned into an event handler bound to that property&amp;#8217;s changes. When the property is changed elsewhere in the app, the event handler is triggered and your UI will be updated. This is referred to as live binding. EJS Live binding is opt-in. It only turns on if you use &lt;code&gt;attr()&lt;/code&gt; to access properties.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s look at one of the &lt;code&gt;&amp;lt;input&gt;&lt;/code&gt; tags from the &lt;code&gt;contactView.ejs&lt;/code&gt; to see how this works:&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;name&amp;quot; placeholder=&amp;quot;Add Name&amp;quot;
  &amp;lt;%= contact.attr('name') ? &amp;quot;value='&amp;quot; + contact.name + &amp;quot;'&amp;quot; : &amp;quot;class='empty'&amp;quot; %&amp;gt;&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The code in the magic tags will become an event handler bound to the contact&amp;#8217;s name property. When we update the name property, the event handler is run and the HTML will be updated.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Organizing Application Logic Using &lt;code&gt;can.Control&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;can.Control&lt;/code&gt; creates an organized, memory-leak free, stateful control that can be used to create widgets or organize application logic. You create an instance of a Control on a DOM element and pass it data your control will need. You can define any number of functions in your Control and bind to events.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When the element your Control is bound to is removed from the DOM, the Control destroys itself, cleaning up any bound event handlers.
  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To create a new Control, extend &lt;code&gt;can.Control()&lt;/code&gt; by passing it an object containing functions you want to define. In part two, event handlers will be passed in as well.&lt;/p&gt;
&lt;p&gt;There are a few important variables and functions present in every Control instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;this&lt;/code&gt; &amp;#8211; A reference to the Control instance&lt;/li&gt;
&lt;li&gt;&lt;code&gt;this.element&lt;/code&gt; &amp;#8211; The DOM element that you created the instance on&lt;/li&gt;
&lt;li&gt;&lt;code&gt;this.options&lt;/code&gt; &amp;#8211; An object containing any data passed to the instance when it was created&lt;/li&gt;
&lt;li&gt;&lt;code&gt;init()&lt;/code&gt; &amp;#8211; Called when an instance is created&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Managing Contacts&lt;/h2&gt;
&lt;p&gt;Add the following snippet to your &lt;code&gt;contacts.js&lt;/code&gt; file to create the Control that will manage contacts:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
Contacts = can.Control({
  init: function(){
    this.element.html(can.view('views/contactsList.ejs', {
      contacts: this.options.contacts,
      categories: this.options.categories
    }));
  }
})
&lt;/pre&gt;
&lt;p&gt;When an instance of &lt;code&gt;Contacts&lt;/code&gt; is created, &lt;code&gt;init()&lt;/code&gt; will do two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Uses &lt;code&gt;can.view()&lt;/code&gt; to render contacts. &lt;code&gt;can.view()&lt;/code&gt; accepts two parameters: the file or id of the script tag containing our template code and data. It returns the rendered result as a documentFragment (a lightweight container that can hold DOM elements).&lt;/li&gt;
&lt;li&gt;Inserts the documentFragment from &lt;code&gt;can.view()&lt;/code&gt; into the Control&amp;#8217;s element using jQuery&amp;#8217;s &lt;code&gt;.html()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;Representing Data Using Models&lt;/h2&gt;
&lt;p&gt;A Model abstracts the data layer of an application. Two models are needed in this application: one for contacts and one for categories. Add this code to &lt;code&gt;contacts.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
Contact = can.Model({
  findAll: 'GET /contacts',
  create  : &amp;quot;POST /contacts&amp;quot;,
  update  : &amp;quot;PUT /contacts/{id}&amp;quot;,
  destroy : &amp;quot;DELETE /contacts/{id}&amp;quot;
},{});

Category = can.Model({
  findAll: 'GET /categories'
},{});
&lt;/pre&gt;
&lt;p&gt;A model has five static methods that you can define to create, retrieve, update and delete data. They are &lt;code&gt;findAll&lt;/code&gt;, &lt;code&gt;findOne&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt;. You can overwrite these functions to work with any back-end, but the easiest way to define a Model is using REST service, as exemplified in the code above. You can safely omit any static methods that won&amp;#8217;t be used in an application.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s important to point out here that the model instances in CanJS are actually what we call &amp;#8216;observables&amp;#8217;. &lt;code&gt;can.Observe&lt;/code&gt; provides the observable pattern for objects and &lt;code&gt;can.Observe.List&lt;/code&gt; provides the observable pattern for arrays. This means you can get and set properties using &lt;code&gt;attr()&lt;/code&gt; and bind to changes in those properties. &lt;/p&gt;
&lt;p&gt;The &lt;code&gt;findAll()&lt;/code&gt; method returns a &lt;code&gt;Model.list&lt;/code&gt;, which is a &lt;code&gt;can.Observe.List&lt;/code&gt; that triggers events when an element is added or removed from the list.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Simulating a Rest Service Using Fixtures&lt;/h2&gt;
&lt;p&gt;Fixtures intercept AJAX requests and simulate their response with a file or function. This is fantastic for testing, prototyping or when a back-end isn&amp;#8217;t ready yet. Fixtures are needed to simulate the REST service the models in this application are using.&lt;/p&gt;
&lt;p&gt;But first, you&amp;#8217;ll need some sample data for the fixtures to use. Add the following code to &lt;code&gt;contacts.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var CONTACTS = [
  {
    id: 1,
    name: 'William',
    address: '1 CanJS Way',
    email: 'william@husker.com',
    phone: '0123456789',
    category: 'co-workers'
  },
  {
    id: 2,
    name: 'Laura',
    address: '1 CanJS Way',
    email: 'laura@starbuck.com',
    phone: '0123456789',
    category: 'friends'
  },
  {
    id: 3,
    name: 'Lee',
    address: '1 CanJS Way',
    email: 'lee@apollo.com',
    phone: '0123456789',
    category: 'family'
  }
];

var CATEGORIES = [
  {
    id: 1,
    name: 'Family',
    data: 'family'
  },
  {
    id: 2,
    name: 'Friends',
    data: 'friends'
  },
  {
    id: 3,
    name: 'Co-workers',
    data: 'co-workers'
  }
];
&lt;/pre&gt;
&lt;p&gt;Now that you have some data, you need to wire it up to fixtures so you can simulate a REST service. &lt;code&gt;can.fixture()&lt;/code&gt; takes two parameters. The first is the URL we want to intercept and the second is a file or function that is used to generate a response. Often URLs you want to intercept are dynamic and follow a pattern. In this case, you should use templated URLs. Simply add curly braces to the URL where you want to match wildcards.&lt;/p&gt;
&lt;p&gt;Add the following to &lt;code&gt;contacts.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
can.fixture('GET /contacts', function(){
  return [CONTACTS];
});

var id= 4;
can.fixture(&amp;quot;POST /contacts&amp;quot;, function(){
  return {id: (id++)}
});

can.fixture(&amp;quot;PUT /contacts/{id}&amp;quot;, function(){
  return {};
});

can.fixture(&amp;quot;DELETE /contacts/{id}&amp;quot;, function(){
  return {};
});

can.fixture('GET /categories', function(){
  return [CATEGORIES];
});
&lt;/pre&gt;
&lt;p&gt;The first four fixtures simulate the &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; responses for the &lt;code&gt;Contact&lt;/code&gt; model, and the fifth fixture simulates the &lt;code&gt;GET&lt;/code&gt; response for the &lt;code&gt;Category&lt;/code&gt; model.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Bootstrapping the Application&lt;/h2&gt;
&lt;p&gt;Your application has Models for your data, Views to render contacts, and a Control to hook everything up. Now you need to kickstart the application!&lt;/p&gt;
&lt;p&gt;Add this to your &lt;code&gt;contacts.js&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
$(document).ready(function(){
  $.when(Category.findAll(), Contact.findAll()).then(
    function(categoryResponse, contactResponse){
      var categories = categoryResponse[0],
        contacts = contactResponse[0];

      new Contacts('#contacts', {
        contacts: contacts,
        categories: categories
      });
  });
});
&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s take a closer look at what is happening in this code:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
$(document).ready(function(){
&lt;/pre&gt;
&lt;p&gt;Wait for the DOM to be ready using jQuery&amp;#8217;s document ready function.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
$.when(Category.findAll(), Contact.findAll()).then(
  function(categoryResponse, contactResponse){
&lt;/pre&gt;
&lt;p&gt;Call &lt;code&gt;findAll()&lt;/code&gt; on both models to retrieve all of the contacts and categories. Since &lt;code&gt;findAll()&lt;/code&gt; returns a Deferred, &lt;code&gt;$.when()&lt;/code&gt; is used to make both requests in parallel and execute a callback when they are finished.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var categories = categoryResponse[0],
  contacts = contactResponse[0];
&lt;/pre&gt;
&lt;p&gt;Get the list of model instances from the response of the two &lt;code&gt;findAll()&lt;/code&gt; calls. The responses are arrays, with the first index being the list of model instances retrieved.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
new Contacts('#contacts', {
  contacts: contacts,
  categories: categories
});
&lt;/pre&gt;
&lt;p&gt;Create an instance of the &lt;code&gt;Contact&lt;/code&gt; Control on the &lt;code&gt;#contacts&lt;/code&gt; element. The list of contacts and categories are passed into the Control.&lt;/p&gt;
&lt;p&gt;When you run your application in a browser, you should see a list of contacts:&lt;/p&gt;
&lt;div class="tutorial_image"&gt;
  &lt;img src='http://d2o0t5hpnwv4c1.cloudfront.net/2043_canJS/part1.png' /&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;That does it for part one of this series! You&amp;#8217;ve been introduced to the core of CanJS: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Models&lt;/strong&gt; abstract the data layer in your application&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Views&lt;/strong&gt; are templates that turn data into HTML&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controls&lt;/strong&gt; wire everything up.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the next lesson (to be published May 28th), you&amp;#8217;ll create a &lt;code&gt;Control&lt;/code&gt; and &lt;code&gt;View&lt;/code&gt; to display categories and use routing to filter contacts. Hope to see you there!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Questions? Ask away below!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SV8DvH7TqwLQtmwekMJOoLa8CCk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SV8DvH7TqwLQtmwekMJOoLa8CCk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SV8DvH7TqwLQtmwekMJOoLa8CCk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SV8DvH7TqwLQtmwekMJOoLa8CCk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=kA1zFDDzUPI:yT9IQVqEc3U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=kA1zFDDzUPI:yT9IQVqEc3U:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=kA1zFDDzUPI:yT9IQVqEc3U:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=kA1zFDDzUPI:yT9IQVqEc3U:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=kA1zFDDzUPI:yT9IQVqEc3U:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=kA1zFDDzUPI:yT9IQVqEc3U:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=kA1zFDDzUPI:yT9IQVqEc3U:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=kA1zFDDzUPI:yT9IQVqEc3U:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/kA1zFDDzUPI" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/tutorials/javascript-ajax/diving-into-canjs/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/javascript-ajax/diving-into-canjs/</feedburner:origLink></item>
		<item>
		<title>Quick Tip: What Exactly is Web Hosting?</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/T1OlUv0Sezw/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/quick-tip-what-exactly-is-web-hosting/#comments</comments>
		<pubDate>Sat, 19 May 2012 10:00:20 +0000</pubDate>
		<dc:creator>Jeffrey Way</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Videos]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25091</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25091&amp;c=2116442191' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25091&amp;c=2116442191' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;Tired of the &amp;#8220;techie&amp;#8221; trying to explain to you what web hosting is all about from his bedroom-recorded Skype video? Ever get confused with all the funny terms they drop, like &amp;#8220;Shared Hosting&amp;#8221; and &amp;#8220;Dedicated Servers&amp;#8221;? We&amp;#8217;ve all been there at one point or another! Well, the guys over at &lt;a href="http://www.inmotionhosting.com/"&gt;InMotion Hosting&lt;/a&gt; created a quick, visual guide that will get you up and running with the jargon in no time! &lt;/p&gt;
&lt;p&gt;&lt;span id="more-25091"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div class=tutorial_image&gt;&lt;iframe width="600" height="305" src="http://www.youtube.com/embed/n7rzi2hGAzA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;div&gt;&lt;em&gt;By &lt;a href="http://www.inmotionhosting.com/"&gt;InMotion Hosting&lt;/a&gt;&lt;/em&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;If you&amp;#8217;re still new to this world, and have questions about the hosting world, leave a comment below, and one of us will do our best to help!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/829pOWOSBqyev7De8H8v8r66JAk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/829pOWOSBqyev7De8H8v8r66JAk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/829pOWOSBqyev7De8H8v8r66JAk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/829pOWOSBqyev7De8H8v8r66JAk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=T1OlUv0Sezw:TfqRCFejQwc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=T1OlUv0Sezw:TfqRCFejQwc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=T1OlUv0Sezw:TfqRCFejQwc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=T1OlUv0Sezw:TfqRCFejQwc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=T1OlUv0Sezw:TfqRCFejQwc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=T1OlUv0Sezw:TfqRCFejQwc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=T1OlUv0Sezw:TfqRCFejQwc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=T1OlUv0Sezw:TfqRCFejQwc:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/T1OlUv0Sezw" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/quick-tip-what-exactly-is-web-hosting/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/tools-and-tips/quick-tip-what-exactly-is-web-hosting/</feedburner:origLink></item>
		<item>
		<title>Ticksy: A Support Story</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/btY1tHMUIUA/</link>
		<comments>http://net.tutsplus.com/articles/general/ticksy-a-support-story/#comments</comments>
		<pubDate>Fri, 18 May 2012 15:05:33 +0000</pubDate>
		<dc:creator>Justin Scheetz</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ticksy]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25073</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25073&amp;c=1409906540' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25073&amp;c=1409906540' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;When I started designing and developing themes and templates for the &lt;a href="http://themeforest.net"&gt;ThemeForest&lt;/a&gt; marketplace five years ago, customer support was easy. I’d get an email or two a day, answer them, and move on.&lt;/p&gt;
&lt;p&gt;But as sales picked up, things became complicated. One or two emails turned into five, which turned into ten, which turned into twenty! I’d respond to a question, and get another question in response. Emails were lost. Customers were frustrated. It was all a big mess.&lt;br /&gt;
&lt;span id="more-25073"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;Email was no longer a tenable support solution.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Two years ago, I decided that enough was enough. Email was no longer a tenable support solution. I needed to find a better way. &lt;/p&gt;
&lt;p&gt;So I did some digging around for a support solution. And believe me, there are plenty out there. Some are free &amp;#8212; mostly poorly designed, buggy DIY scripts to install and run on your own server. Some aren’t &amp;#8212; prettier, feature-rich … and expensive. Fifty bucks a month? For a guy like me, forget it.&lt;/p&gt;
&lt;p&gt;Simply put, there was nothing out there that appealed to someone doing well &amp;#8212; but not getting rich &amp;#8212; selling online. So I decided to build one. Something simple. Something with the features I needed, and nothing else. And something that played nice with the &lt;a href="http://marketplace.envato.com/api/documentation"&gt;Envato API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Two years later, I finished &lt;a href="https://www.ticksy.com/"&gt;Ticksy&lt;/a&gt; &amp;#8212; and I love it. It’s sleek, easy to use and getting some great reviews. &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Most importantly, it’s doing a great job handling my support requests &amp;#8212; the reason I built it in the first place!&lt;/p&gt;&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;Designing Ticksy&lt;/h2&gt;
&lt;p&gt;As any developer knows, simple on the outside invariably means complicated on the inside. And, while &lt;a href="http://ticksy.com"&gt;Ticksy&lt;/a&gt; was a labor of love, building it was anything but easy.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Naming it? That’s a different story. Support ticket system. “Tick.” “Sy.” Ticksy. Get it?&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I spent roughly three months designing the UI &amp;#8211; buttons and form fields on the login screen, tabs and dropdowns in the app and more. Product management had to be spot-on, too. The initial Envato integration made it possible for me to tie every ticket directly into one of my products in the marketplace. Eventually, I worked product verification into the mix &amp;#8212; only actual owners (not pirates) of my themes could submit tickets.&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;They liked it. No more email!&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I developed the first, basic version of Ticksy using PHP and MySQL in about five months &amp;#8212; continuing to support customers via email in the meantime (yuck). Finally, by the end of 2010, I was able to deploy the system for my own business. Customers started using it. They liked it. No more email! I felt great; a huge load was off my shoulders.&lt;/p&gt;
&lt;div class="tutorial_image" style="clear: both;"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2041_ticksy/ticksy_original_design.jpg" alt="Original Ticksy"&gt;&lt;/p&gt;
&lt;div&gt;&lt;em&gt;The original Ticksy dashboard, circa 2010&lt;/em&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then, something unexpected &amp;#8212; and pleasant &amp;#8212; happened. People started asking me about the system. The customers actually enjoyed using it as much as I did and wanted to know how they could use it in their businesses. I had no answer at the time. This was my system. I built it for me. Were there other people like me that would use something so simple?&lt;/p&gt;
&lt;p&gt;Turns out there were. People wanted Ticksy. So I was back to the drawing board.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Ticksy For All&lt;/h2&gt;
&lt;p&gt;Two partners and I redesigned the UI and backend to allow for multiple systems, added social sign-in buttons (Facebook and Twitter), got feedback from friends and family and added a few other features. I essentially redesigned/developed the entire Ticksy system, and launched a beta build in early 2011.&lt;/p&gt;
&lt;p&gt;I had around ten beta users using it full-time, and they loved it. Months went by, bugs were squashed, the UI was refined and I let it get some good use for a long time. If I was going to release this to the public and expect people to pay for it, it had to work well. I let it go for a year before deciding to release it to the public. My product was polished. Ticksy was ready for the limelight.&lt;/p&gt;
&lt;p&gt;After many months of testing, developing a marketing site (powered by &lt;a href="http://wordpress.org/"&gt;WordPress&lt;/a&gt;), creating a marketing video (with the help of &lt;a href="http://videohive.net/"&gt;VideoHive’s&lt;/a&gt; own &lt;a href="http://videohive.net/user/bryandrake"&gt;Bryan Drake&lt;/a&gt;) and planning everything to the last detail, we launched Ticksy to the public in March.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;a href="http://ticksy.com"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2041_ticksy/ticksy-launch.jpg" alt="Ticksy"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2041_ticksy/ticksy_today_design.jpg" alt="The Ticksy Dashboard, 2012"&gt;&lt;/p&gt;
&lt;div&gt;The Ticksy dashboard, 2012&lt;/em&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you’re a designer, you know the feeling of taking a product live. It’s amazing. But it’s also a bit scary. What if people don’t like it? What if it doesn’t sell? &lt;/p&gt;
&lt;p&gt;Thankfully, with Ticksy, my fears were quickly assuaged. The initial group of users loved it, talking up its simplicity, its reliability and even its price point. Like me, they were freed from the headaches of email-based support &amp;#8212; without having to turn to a cheaply built free solution or an expensive, bloated “do-it-all” app. &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;As a designer, it was supremely validating. And it was a reminder to keep working.&lt;/p&gt;&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;More to Come&lt;/h2&gt;
&lt;p&gt;A developer’s work is never done. And despite the project’s success, that’s certainly been true for Ticksy. &lt;/p&gt;
&lt;p&gt;As initially released, Ticksy was an intuitive, bloat-free, web-based customer support solution that could be customized to match any existing brand. After months of work, it’s still that &amp;#8212; and more. Now, end users can label their tickets “public” or “private,” bringing an element of the traditional community forum to support. Search functionality for customers is enabled. And enhanced FAQs, notification systems and better Envato integration are on the way soon. (You can check out our &lt;a href="http://www.ticksy.com/roadmap"&gt;roadmap here&lt;/a&gt;.)&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Summing it Up&lt;/h2&gt;
&lt;blockquote class="pullquote"&gt;&lt;p&gt;Ticksy has been a two-year journey of discovery and hard work.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;For me, Ticksy has been a two-year journey of discovery and hard work. But it’s been worth it.&lt;/p&gt;
&lt;p&gt;What started as a project to simplify my own work has taken on a life of its own. I never expected Ticksy to see the light of day outside my office. But it’s incredibly vindicating to check the growing list of users and read their feedback. Really, it’s every developer’s dream. Ticksy has truly arrived. And, with each user, it’s making web-based customer support just a little bit simpler.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The process of taking an idea from sketch to launch is a significant achievement. If you have any, more specific, questions about the process (such as the tools we used for reporting bugs, version control, etc.), let me know in the comments, and we&amp;#8217;ll talk!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-6W_jk2frS7QbHcbAfSOSmOew7U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-6W_jk2frS7QbHcbAfSOSmOew7U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-6W_jk2frS7QbHcbAfSOSmOew7U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-6W_jk2frS7QbHcbAfSOSmOew7U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=btY1tHMUIUA:rs9hxhYh17g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=btY1tHMUIUA:rs9hxhYh17g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=btY1tHMUIUA:rs9hxhYh17g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=btY1tHMUIUA:rs9hxhYh17g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=btY1tHMUIUA:rs9hxhYh17g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=btY1tHMUIUA:rs9hxhYh17g:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=btY1tHMUIUA:rs9hxhYh17g:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=btY1tHMUIUA:rs9hxhYh17g:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/btY1tHMUIUA" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/articles/general/ticksy-a-support-story/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/articles/general/ticksy-a-support-story/</feedburner:origLink></item>
		<item>
		<title>Diving Into CSS Regions</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/vUHrlXUe5DA/</link>
		<comments>http://net.tutsplus.com/tutorials/html-css-techniques/diving-into-css-regions/#comments</comments>
		<pubDate>Thu, 17 May 2012 17:20:11 +0000</pubDate>
		<dc:creator>Umar Hansa</dc:creator>
				<category><![CDATA[HTML & CSS]]></category>
		<category><![CDATA[regions]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25061</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25061&amp;c=1105051727' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25061&amp;c=1105051727' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;This tutorial will cover the basics of CSS regions, which allow us to flow content within various sections of the page. Confused? You probably are; read on!&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25061"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;div class="download_wrap"&gt;
&lt;div class="big_btn" style="margin-left:120px;"&gt;
    	&lt;a href="http://umaar.github.com/css-region-demo/" rel="external" target="_blank"&gt;&lt;span&gt;Demo&lt;/span&gt; &lt;small&gt;View It Online&lt;/small&gt;&lt;/a&gt;
  	&lt;/div&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;CSS Region Support&lt;/h2&gt;
&lt;p&gt;At the time of this writing, the &lt;a href="http://dev.w3.org/csswg/css3-regions/" rel="external" target="_blank"&gt;CSS Regions specification&lt;/a&gt; is a working draft and &lt;strong&gt;things may change!&lt;/strong&gt; Techniques mentioned in this tutorial might change in implementation. The aim of this tutorial is to give a basic understanding of CSS Regions and what might be coming to a browser near you.&lt;/p&gt;
&lt;p&gt;
	Check out &lt;a href="http://caniuse.com/css-regions" rel="external" target="_blank" title="Can I Use CSS Regions"&gt;caniuse.com&lt;/a&gt; for a list of browsers which have some support for CSS Regions. This tutorial will only use webkit/non-vendor-prefixed examples for simplicities sake.
&lt;/p&gt;
&lt;p&gt;If you find the demo is not working for you it may be because CSS Regions needs enabling, here are instructions for Chrome  (should work for &lt;a href="https://www.google.com/chrome" rel="external" target="_blank" title="Google Chrome"&gt;Chrome&lt;/a&gt;, &lt;a href="https://tools.google.com/dlpage/chromesxs" rel="external" target="_blank" title="Google Chrome Canary"&gt;Chrome Canary&lt;/a&gt; &amp;amp; &lt;a href="http://www.chromium.org/getting-involved/download-chromium" rel="external" target="_blank" title="Chromium"&gt;Chromium&lt;/a&gt; )
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to chrome://flags/ (or about:flags)&lt;/li&gt;
&lt;li&gt;Find &amp;#8220;Enable CSS Regions&amp;#8221; and enable it.&lt;/li&gt;
&lt;li&gt;Restart your browser and verify that the demo is working.&lt;/li&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2040_cssRegions/chrome-flags-screenshot.png" alt="Screenshot of the Chrome Flags page" border="0" /&gt;&lt;/div&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;A Simple Example&lt;/h2&gt;
&lt;p&gt;Demonstrating CSS Regions in a simple manner actually requires very little code!&lt;/p&gt;
&lt;p&gt;To get into the &lt;strong&gt;flow&lt;/strong&gt; of things lets go through a quick example of how to use CSS Regions.&lt;/p&gt;
&lt;p&gt;First, we need some dummy text which is contained within the paragraph tag, below that you&amp;#8217;ll notice two empty divs each with a class of &amp;#8220;regions&amp;#8221;. Using CSS Regions we will allow our &amp;#8220;example-text&amp;#8221; to &lt;strong&gt;flow&lt;/strong&gt; into the region divs.&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;

&amp;lt;p class=&amp;quot;example-text&amp;quot;&amp;gt;&amp;quot;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&amp;quot;&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;regions&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;regions&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; 
&lt;/pre&gt;
&lt;pre class="brush: css; title: ; notranslate"&gt;
.example-text {
	-webkit-flow-into: example-text-flow;
	padding: 0;
	margin: 0;
}

.regions {
	-webkit-flow-from: example-text-flow;
	border: 1px solid black;
	padding: 2px;
	margin: 5px;
	width: 200px;
	height: 50px;
}
&lt;/pre&gt;
&lt;p&gt;If you try &lt;a href="http://jsbin.com/inaheh" rel="external" target="_blank"&gt;viewing the code&lt;/a&gt; above in a Webkit browser that supports CSS Regions, you should see something like: &lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2040_cssRegions/basic-example.png" alt="Basic example of CSS Regions" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;All styling (apart from -webkit-flow-from) which has been applied on the &amp;#8220;regions&amp;#8221; class is only there to make it evident where the regions are, the two lines of CSS that we really care about are:&lt;/p&gt;
&lt;pre class="brush: css; title: ; notranslate"&gt;
-webkit-flow-into: example-text-flow;

-webkit-flow-from: example-text-flow;
&lt;/pre&gt;
&lt;p&gt;These will be discussed in more detail below&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The &lt;code&gt;flow-into&lt;/code&gt; Property and Named Flows&lt;/h2&gt;
&lt;p&gt;The flow-into property accepts an identifier as its value, once we apply the flow-into property onto an element and pass it an identifier, that element then becomes part of a &amp;#8220;named flow&amp;#8221;. As soon as an element becomes part of a named flow it is taken out of its usual flow &amp;#8211; this essentially means the element will not be rendered on the page, for example: &lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;p class=&amp;quot;example-text&amp;quot;&amp;gt;I will not be rendered on the page&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;pre class="brush: css; title: ; notranslate"&gt;
.example-text {
	-webkit-flow-into: example-text-flow;
}
&lt;/pre&gt;
&lt;p&gt;There are some exceptions to this however, if the flow-into property is given the value &amp;#8216;none&amp;#8217; the element will not be part of a named flow and thus be subject to usual rendering on the page. As you might have guessed, another case where an element which is part of named flow will be displayed is when it has a valid region associated with it.&lt;/p&gt;
&lt;p&gt;Multiple elements can be put into the same named flow:&lt;/p&gt;
&lt;pre class="brush: css; title: ; notranslate"&gt;
#example-1 {
	-webkit-flow-into: my-named-flow;
}

#example-2 {
	-webkit-flow-into: my-named-flow;
}
&lt;/pre&gt;
&lt;p&gt;If there is an associated region for &amp;#8220;my-named-flow&amp;#8221;, an attempt will be made to flow the two elements (&lt;code&gt;#example-1&lt;/code&gt; &amp;amp; &lt;code&gt;#example-2&lt;/code&gt;) into their corresponding region chain.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s not just simple bits of text which can be put into a named flow, we &lt;a href="http://jsbin.com/apivan" rel="external" target="_blank"&gt;can put images&lt;/a&gt; too! Having the ability to put all sorts of HTML elements into named flows is a powerful thing. For example, let&amp;#8217;s say we had two individual lists but from a presentation point of view we wanted to show them together. One way to go about this is to use CSS selectors to target only the portions we need and put them into a named flow, example (extract of code): &lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;article id=&amp;quot;css3&amp;quot;&amp;gt;
  &amp;lt;header&amp;gt;&amp;lt;h4&amp;gt;CSS3&amp;lt;/h4&amp;gt;&amp;lt;/header&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;Media Queries&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;Text Shadows&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;3D Transforms&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/article&amp;gt;

&amp;lt;article id=&amp;quot;html5&amp;quot;&amp;gt;
  &amp;lt;header&amp;gt;&amp;lt;h4&amp;gt;HTML5&amp;lt;/h4&amp;gt;&amp;lt;/header&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;Canvas&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;Drag-and-drop&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;Web Storage&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/article&amp;gt;  

&amp;lt;div id=&amp;quot;buzzwords-region&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;pre class="brush: css; title: ; notranslate"&gt;
/* Only put the list within the article into a named flow */
#css3 &amp;gt; ul {
-webkit-flow-into: buzzwords-flow;
}

#html5 &amp;gt; ul {
-webkit-flow-into: buzzwords-flow;
}  

#buzzwords-region {
-webkit-flow-from: buzzwords-flow;
border: 1px solid green;
}
&lt;/pre&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2040_cssRegions/buzzword-list.png" alt="Result of combining two lists using CSS Regions" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;(&lt;a href="http://jsbin.com/ucunes" rel="external" target="_blank"&gt;Demo of the above.&lt;/a&gt;) If you look at the source code you&amp;#8217;ll notice that our HTML5 &amp;amp; CSS3 lists have been merged into a new &lt;del&gt;buzzword&lt;/del&gt; list. Take note of how the headers of those lists were not targeted in the CSS selectors and thus are not part of any named flow, they are therefore still rendered on the page and are not contained within a region.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The &lt;code&gt;flow-from&lt;/code&gt; Property&lt;/h2&gt;
&lt;p&gt;The flow-from property is able to take a container, for example an empty div and turn it into a region. For it to turn into a valid region it must have an associated named flow. As discussed, named flows are created by using the flow-into property and then using an identifier as its value.&lt;/p&gt;
&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;div class=&amp;quot;region&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;pre class="brush: css; title: ; notranslate"&gt;
.region {
	-webkit-flow-from: my-named-flow;
}
&lt;/pre&gt;
&lt;p&gt;Similar to flow-into property, we can assign the value of &amp;#8216;none&amp;#8217; to the flow-from property, this makes the corresponding element nothing more than a container e.g. it will not act as a region.&lt;/p&gt;
&lt;p&gt;When applying the flow-from property on an element, it will not have a height or width which is why you&amp;#8217;ll need to set these in order to view the contents of the region. Regions may only act as region chains for a single named flow, so multiple elements may flow-into a single named flow however a region can only flow-from a single named flow. A region will maintain the styles of its source element; this means if the source element has the colour value of red the text will continue to appear red when rendered as part of a region.&lt;/p&gt;
&lt;p&gt;The CSS Region specification has been considering using @region rules for specific region styling. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
&amp;#8220;An &lt;code&gt;@region&lt;/code&gt; rule contains style declarations specific to particular regions.&amp;#8221;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This could allow for CSS syntax (similar to that of media queries) such as:&lt;/p&gt;
&lt;pre class="brush: css; title: ; notranslate"&gt;
/* A regular style on all paragraph tags */
p {
	font-weight: normal;
}

@region #my-region {
	/* When text from the p element is flowing into #my-region, use the styling below */
	p {
		font-weight: bold;
	}
}
&lt;/pre&gt;
&lt;p&gt;Being able to do this would allow region specific styling to be applied on the source, currently, setting for example &amp;#8220;font-weight: bold&amp;#8221; on a region will not cause content displayed within it to be bold &amp;#8211; the styling must be applied on the source element. &lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;JavaScript API&lt;/h2&gt;
&lt;p&gt;At the time of this writing, there is some support in Webkit-based browsers to access CSS Region information through JavaScript. Using JavaScript, we can pick out a flow according to its identifier and find out what regions are associated with it. We can even find out the status of a particular region, there may be a use case where empty regions need specific handling, using JavaScript we can accomplish this.&lt;/p&gt;
&lt;h3&gt;Accessing a flow by name&lt;/h3&gt;
&lt;p&gt;A named flow can be accessed in JavaScript using document.getFlowByName(&amp;#8216;identifier&amp;#8217;) (You can try these in the developer console in the demo.)&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var flow = document.webkitGetFlowByName('example-1-text');
&lt;/pre&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2040_cssRegions/WebkitNamedFlow.png" alt="The return object of getFlowByName" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;The returned object is something called a WebkitNamedFlow. flow.contentNodes will contain an array of HTML Elements which are being used as the source for the flow being accessed.&lt;/p&gt;
&lt;h3&gt;Discovering which regions belong to which content node&lt;/h3&gt;
&lt;p&gt;The ability to detect which content belongs to which regions can prove useful in various situations.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var flow = document.webkitGetFlowByName('example-4-text');
var main_content = document.querySelector('#example-4 .main_content');
flow.getRegionsByContentNode(main_content);
&lt;/pre&gt;
&lt;p&gt;In the code above, we first find our flow on the page using the flow name, then using the &lt;a href="http://www.w3.org/TR/selectors-api/"&gt;Selectors API&lt;/a&gt; we access a piece of content on the page and pass it as an argument to getRegionsByContentNode(), this returns a list of elements which are being used as regions for that particular piece of content.&lt;/p&gt;
&lt;h3&gt;Finding out whether or not a piece of content fits inside a region&lt;/h3&gt;
&lt;p&gt;We can very quickly determine the status of a region in regards to how content inside it fits.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
//This is not a very efficient selector, see https://developers.google.com/speed/docs/best-practices/rendering#UseEfficientCSSSelectors
var region7 = document.querySelector('#example-4 .regions &amp;gt; div:nth-child(7) ');
region7.webkitRegionOverflow //&amp;quot;fit&amp;quot;
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;element.regionOverflow&lt;/code&gt; will return different values depending on how it&amp;#8217;s handling the source content. There are four possible values: &amp;#8216;overflow&amp;#8217;, &amp;#8216;fit&amp;#8217;, &amp;#8216;empty&amp;#8217; and &amp;#8216;undefined&amp;#8217;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;overflow:&lt;/strong&gt; The content does not fit in the specified region and will overflow to the next region if it&amp;#8217;s available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fit:&lt;/strong&gt; The region has successfully contained the content and no overflow is necessary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;empty:&lt;/strong&gt; There is no content inside of the selected region and therefore it is empty  (as will normally be the case with a region whose previous region returns &amp;#8216;fit&amp;#8217; for regionOverflow)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;undefined:&lt;/strong&gt; The element is not a valid region.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can try this out using developer tools in Chrome, on the demo page, right click on one of the blue boxes (a region) and select &amp;#8216;Inspect Element&amp;#8217;. You may find the source element is selected rather than the region div. Try to find the nearest div with the class of &amp;#8216;regions&amp;#8217; and select one of the child divs (they should appear empty). At this point you can hit the Escape key on your keyboard which should bring up the console; now as a handy shortcut you can type $0 into the console to access the selected element. Now try typing: &lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;
$0.webkitRegionOverflow //'overflow', 'fit', 'empty' or'undefined'
&lt;/pre&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2040_cssRegions/developer-console-region-api.png" alt="Using the dollar zero shortcut in developer console to access the selected element" border="0" /&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;A Few Notes and Opinions&lt;/h2&gt;
&lt;p&gt;Hello! Thanks for reading this tutorial, here are some extra bits of information you may be interested in.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Browser implementation for CSS Regions isn&amp;#8217;t great right now and even when it does improve browser implementation may vary. For example Internet Explorer only allows flow-into to be set on an iframe. &lt;/li&gt;
&lt;li&gt;CSS Regions can let developers and designers offer a more improved experience on the web, especially on mobile/tablet devices.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://modernizr.com/"&gt;Modernizr&lt;/a&gt; can &lt;a href="https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css-regions.js"&gt;detect support&lt;/a&gt; for CSS Regions, it&amp;#8217;s what the &lt;a href="http://umaar.github.com/css-region-demo/"&gt;demo&lt;/a&gt; uses.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://labs.adobe.com/"&gt;Adobe&lt;/a&gt; &lt;a href="http://adobe.github.com/web-platform/samples/css-regions/"&gt;have&lt;/a&gt; &lt;a href="http://labs.adobe.com/technologies/cssregions/"&gt;taken&lt;/a&gt; &lt;a href="http://html.adobe.com/webstandards/cssregions/"&gt;a&lt;/a&gt; &lt;a href="http://www.adobe.com/devnet/html5/articles/css3-regions.html"&gt;great&lt;/a&gt; &lt;a href="https://blogs.adobe.com/webplatform/2012/03/16/css-regions-one-year-in/"&gt;initiative&lt;/a&gt; on CSS Regions. Be sure to check out their &lt;a href="http://labs.adobe.com/downloads/cssregions.html"&gt;demos&lt;/a&gt;!  &lt;/li&gt;
&lt;li&gt;Chris Coyier of &lt;a href="http://css-tricks.com/"&gt;CSS Tricks&lt;/a&gt; has come up with a cool and &lt;a href="http://css-tricks.com/content-folding/"&gt;practical use for CSS Regions&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HtNMhhBCcejj4mkNdKNRNRFwj7U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HtNMhhBCcejj4mkNdKNRNRFwj7U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HtNMhhBCcejj4mkNdKNRNRFwj7U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HtNMhhBCcejj4mkNdKNRNRFwj7U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=vUHrlXUe5DA:kkHUtjqJryo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=vUHrlXUe5DA:kkHUtjqJryo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=vUHrlXUe5DA:kkHUtjqJryo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=vUHrlXUe5DA:kkHUtjqJryo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=vUHrlXUe5DA:kkHUtjqJryo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=vUHrlXUe5DA:kkHUtjqJryo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=vUHrlXUe5DA:kkHUtjqJryo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=vUHrlXUe5DA:kkHUtjqJryo:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/vUHrlXUe5DA" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/tutorials/html-css-techniques/diving-into-css-regions/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/html-css-techniques/diving-into-css-regions/</feedburner:origLink></item>
		<item>
		<title>Meet Crockford’s JSCheck</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/elFnjAFtJ_Q/</link>
		<comments>http://net.tutsplus.com/tutorials/javascript-ajax/meet-crockford%e2%80%99s-jscheck/#comments</comments>
		<pubDate>Wed, 16 May 2012 20:50:33 +0000</pubDate>
		<dc:creator>Andrew Burgess</dc:creator>
				<category><![CDATA[JavaScript & AJAX]]></category>
		<category><![CDATA[crockford]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25044</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25044&amp;c=1434558222' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25044&amp;c=1434558222' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;There are dozens of JavaScript testing frameworks, but most of them function in, more or less, the same way. However, Douglas Crockford&amp;#8217;s &lt;a href='http://www.jscheck.org/'&gt;JSCheck&lt;/a&gt; is considerably different from most. In this tutorial, I&amp;#8217;ll show you how it&amp;#8217;s different and why you should consider using it!&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25044"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;blockquote class=pullquote&gt;&lt;p&gt;
Crockford describes &lt;a href='http://www.jscheck.org/'&gt;JSCheck&lt;/a&gt; as a &amp;#8220;specification-driven testing tool.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Crockford describes &lt;a href='http://www.jscheck.org/'&gt;JSCheck&lt;/a&gt; as a &amp;#8220;specification-driven testing tool.&amp;#8221; When using the frameworks you&amp;#8217;re used to, you would write a test for a given piece of functionality, and, if that test passes, declare that the given functionality is working correctly. However, it&amp;#8217;s possible that you might miss some of edge cases or exceptions that your tests don&amp;#8217;t cover.&lt;/p&gt;
&lt;p&gt;While uncovering edge cases isn&amp;#8217;t the express purpose of JSCheck, it is a nice side benefit. The main idea behind JSCheck is this: the specification you write will actually describe how the code you are testing should work. Then, JSCheck will take that specification (called a &lt;strong&gt;claim&lt;/strong&gt; in JSCheck-lingo), and generate random tests to prove the claim. Finally, it will report the results to you.&lt;/p&gt;
&lt;p&gt;Sounds interesting? Read on! Sounds familiar? You might have used the Haskell testing tool, &lt;a href="http://www.haskell.org/haskellwiki/Introduction_to_QuickCheck"&gt;QuickCheck&lt;/a&gt;, on which JSCheck was based.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Some Code to Test&lt;/h2&gt;
&lt;p&gt;Of course, before actually writing our claim, we&amp;#8217;ll want to have some code to test. Recently, I wrote a mini-password scorer, similar to the functionality on &lt;a href='http://howsecureismypassword.net/'&gt;HowSecureIsMyPassword.net&lt;/a&gt;. It really isn&amp;#8217;t fancy: you just pass the function a password and get a score back. Here&amp;#8217;s the code:&lt;/p&gt;
&lt;h3&gt;passwordScorer.js&lt;/h3&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;(function () {
    var PasswordScorer = {};

    PasswordScorer.score = function (password) {
        var len = password.length,
            lengthScore = 0,
            letterScore = 0,
            chars = {}

        if      (len &amp;gt;= 21) { lengthScore = 7; }
        else if (len &amp;gt;= 16) { lengthScore = 6; }
        else if (len &amp;gt;= 13) { lengthScore = 5; }
        else if (len &amp;gt;= 10) { lengthScore = 4; }
        else if (len &amp;gt;=  8) { lengthScore = 3; }
        else if (len &amp;gt;=  5) { lengthScore = 2; }

        var re = [ null, /[a-z]/g, /[A-Z]/g, /\d/g, /[!@#$%\^&amp;amp;amp;\*\(\)=_+-]/g];

        for (var i = 1; i &amp;lt; re.length; i++) {
            letterScore += (password.match(re[i]) || []).length * i;
        }

        return letterScore + lengthScore;
    };

    (typeof window !== 'undefined' ? window : exports).PasswordScorer = PasswordScorer;
}());&lt;/pre&gt;
&lt;p&gt;It&amp;#8217;s pretty simple code, but here&amp;#8217;s what&amp;#8217;s going on: the score is made up of two sub-scores. There&amp;#8217;s a starting score, that&amp;#8217;s based on the length of the password, and then an additional score for each character, 1 point for each lowercase letter, 2 points for each uppercase letter, 3 points for each number, and 4 points for each symbol (from a limited set).&lt;/p&gt;
&lt;p&gt;So, this is the code we&amp;#8217;re going to test: we&amp;#8217;ll randomly generate some passwords with JSCheck and make sure they get an appropriate score.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Writing our Claim&lt;/h2&gt;
&lt;p&gt;Now we&amp;#8217;re ready to write our claims. First, head over the &lt;a href='https://github.com/douglascrockford/JSCheck'&gt;JSCheck Github page&lt;/a&gt; and download the &lt;code&gt;jscheck.js&lt;/code&gt; file. I like to run my tests in the terminal, via NodeJS, so add this single line to the very bottom of the file:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;(typeof window !== 'undefined' ? window : exports).JSC = JSC;&lt;/pre&gt;
&lt;p&gt;This won&amp;#8217;t affect the way the file behaves in the browser at all, but it will make it work as a module within Node. Notice that the &lt;code&gt;jscheck.js&lt;/code&gt; file exposes &lt;code&gt;JSC&lt;/code&gt; as the single global variable for the whole library. If we weren&amp;#8217;t making this adjustment, that&amp;#8217;s how we&amp;#8217;d access it.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s open &lt;code&gt;passwordScorerSpec.js&lt;/code&gt; and start things:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;JSC = require(&amp;quot;./../vendor/jschec&amp;quot;;).JSC;
PasswordScorer = require(&amp;quot;./../lib/passwordScore&amp;quot;;).PasswordScorer;&lt;/pre&gt;
&lt;p&gt;Since I&amp;#8217;m running these tests in NodeJS, we&amp;#8217;ll have to require the modules we want. Of course, you&amp;#8217;ll want to make sure that paths match your file locations.&lt;/p&gt;
&lt;p&gt;Now, we&amp;#8217;re ready to write our first claim. Of course, we use the &lt;code&gt;JSC.claim&lt;/code&gt; method. This method accepts three parameters, with an optional fourth. The first parameter is just a string, a &lt;strong&gt;name&lt;/strong&gt; for the claim. The second parameter is called the &lt;strong&gt;predicate&lt;/strong&gt;: it&amp;#8217;s the actual testing function. Very simply, this function should return &lt;code&gt;true&lt;/code&gt; if the claim is true, and &lt;code&gt;false&lt;/code&gt; if the claim is false. The random values that JSCheck will generate for the test will be passed as parameters to the predicate.&lt;/p&gt;
&lt;p&gt;But how does JSCheck know what type of random values to hand the predicate? That&amp;#8217;s where the third parameter, the &lt;strong&gt;specifier&lt;/strong&gt; comes into play. This is an array, with an item for each parameter for predicate. The items in the array specify what types to give the predicate, using JSCheck&amp;#8217;s specifier functions. Here are a few of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JSC.boolean()&lt;/code&gt; returns either true or false.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSC.character()&lt;/code&gt; takes a min and max character and returns a single character from that range. It can also take a single character code and return that character.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSC.integer()&lt;/code&gt; will return a prime number. Or, pass it a single parameter to get an integer (whole number) between 1 and the parameter, or two parameters for an integer in that range.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You get the idea. There are other specifiers, and we&amp;#8217;ll use some now as we write our first claim.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;JSC.claim(&amp;quot;All Lowercase Password&amp;quot;;, function (password, maxScore) {
  return PasswordScorer.score(password) &amp;lt;= maxScore;
}, [
  JSC.string(JSC.integer(10, 20), JSC.character('a', 'z')),
  JSC.literal(26)
]);&lt;/pre&gt;
&lt;p&gt;Our first parameter is a name. The second is the testing function: it receives a password and a max score, and returns true if the score for that password is less than or equal to the max score. Then, we have our specifier array. Our first parameter (the password) should be a string, so we use the &lt;code&gt;JSC.string()&lt;/code&gt; method: it can take two parameters, the number of characters in the string, and value for those characters. As you can see, we&amp;#8217;re asking for a password between 10 and 20 characters. For the value, we&amp;#8217;re using the &lt;code&gt;JSC.characters()&lt;/code&gt; method to get random characters between &amp;#8216;a&amp;#8217; and &amp;#8216;z&amp;#8217;.&lt;/p&gt;
&lt;p&gt;The next value is our &lt;code&gt;maxScore&lt;/code&gt; parameter. Sometimes, we don&amp;#8217;t want the randomness that JSCheck offers, and this is one of those times. That&amp;#8217;s why there&amp;#8217;s &lt;code&gt;JSC.literal&lt;/code&gt;: to pass a literal value the predicate. In this case, we&amp;#8217;re using 26, which should be the max score for any all-lowercase password between 10 and 20 characters.&lt;/p&gt;
&lt;p&gt;Now we&amp;#8217;re ready to run the test.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Running our Claim&lt;/h2&gt;
&lt;p&gt;Before we actually run the claim and get the report, we have to setup the function that will receive the report. JSCheck passes the report to a callback function of &lt;code&gt;JSC.on_report&lt;/code&gt;. Hence:&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;JSC.on_report(function (str) {
  console.log(str);
});&lt;/pre&gt;
&lt;p&gt;Nothing fancy. Now, all that&amp;#8217;s left is to call &lt;code&gt;JSC.check()&lt;/code&gt;. Now, we can head to our terminal and run this:&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;node path/to/passwordScorerSpec.js&lt;/pre&gt;
&lt;p&gt;Behind the scenes, JSCheck runs the predicate 100 times, generating different random values each time. You should see your report printed out.&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;All Lowercase Passwords 100 of 100
 pass 100&lt;/pre&gt;
&lt;p&gt;They all passed, but that&amp;#8217;s not much of a report, eh? Well, if any of our tests had failed, they would have been included in the report. However, you can adjust the level of output with the &lt;code&gt;JSC.detail&lt;/code&gt; function: pass it a number between 0 and 4 (inclusive) to get anything for no output to all the test cases. The default value is 3.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Adding a Classifier&lt;/h2&gt;
&lt;p&gt;Remember how I said that &lt;code&gt;JSC.claim&lt;/code&gt; could take a fourth parameter? It&amp;#8217;s called a &lt;strong&gt;classifier&lt;/strong&gt;, and it receives the same parameters that the predicate receives. Then, it can returns a string to classify, or group, our test cases. I&amp;#8217;ll admit I wasn&amp;#8217;t really sure where this would be useful until I was creating the above example claim. See, I made a mistake in the predicate and compared the score to the &lt;code&gt;maxScore&lt;/code&gt; with the &lt;code&gt;&lt;&lt;/code&gt; operator instead of the &lt;code&gt;&lt;=&lt;/code&gt; operator, so any passwords that scored 26 points were failing. I was seeing reports that looked something like this:&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;All Lowercase Passwords 96 of 100
 FAIL [12] (&amp;quot;vqfqkqqbwkdjrvplkrx&amp;quot;;,26)
 FAIL [21] (&amp;quot;nhgkznldvoenhqqlfza&amp;quot;;,26)
 FAIL [62] (&amp;quot;eclloekuqhvnsyyuekj&amp;quot;;,26)
 FAIL [78] (&amp;quot;rvrkfivwtdphrhjrjis&amp;quot;;,26)
 pass 96 fail 4&lt;/pre&gt;
&lt;p&gt;It&amp;#8217;s still not entirely obvious why some tests are failing. So I added a classifier function that grouped the test cases by score: like I said, the function takes the same parameters as the predicate, and it returns a string. Every test case that gets the same string back from the classifier will be grouped together in the report.&lt;/p&gt;
&lt;pre class="brush: jscript; title: ; notranslate"&gt;function (password, maxScore) {
	return PasswordScorer.score(password) + &amp;quot; points&amp;quot;;;
}&lt;/pre&gt;
&lt;p&gt;This function should be the last parameter of our claim. Now, you&amp;#8217;ll get a report that&amp;#8217;s something like this:&lt;/p&gt;
&lt;pre class="brush: bash; title: ; notranslate"&gt;All Lowercase Passwords 96 of 100
 FAIL [4] 26 points:(&amp;quot;illqbtiubsmrhxdwjfo&amp;quot;;,26)
 FAIL [22] 26 points:(&amp;quot;gruvmmqjzqlcyaozgfh&amp;quot;;,26)
 FAIL [34] 26 points:(&amp;quot;chhbevwtjvslprqczjg&amp;quot;;,26)
 FAIL [65] 26 points:(&amp;quot;kskqdjhtonybvfewdjm&amp;quot;;,26)
14 points: pass 8
15 points: pass 5
16 points: pass 12
18 points: pass 10
19 points: pass 12
20 points: pass 11
22 points: pass 12
23 points: pass 8
24 points: pass 10
25 points: pass 8
26 points: pass 0 fail 4
&lt;/pre&gt;
&lt;p&gt;You can see how the tests are grouped by how many points the passwords are worth. Now, it&amp;#8217;s easy to see that the only passwords that fail the tests are the passwords that score 26 points. And while the problem here was with the test, and not the code, it still shows how it can be useful to add a classifier function to your claims.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;So, at the end of the day, it JSCheck worth using? Here&amp;#8217;s what I think: it&amp;#8217;s not something you&amp;#8217;re necessarily going to use with every code base, but sometimes you&amp;#8217;ll find it useful to be able to create random test cases that will rigorously test a given piece of code. When that&amp;#8217;s what you want to do, I haven&amp;#8217;t seen a tool better for that than JSCheck.&lt;/p&gt;
&lt;p&gt;JSCheck has a few other options and a bunch of specifiers that we haven't reviewed in this tutorial; head over to &lt;a href='http://www.jscheck.org/'&gt;JSCheck.og&lt;/a&gt; to read about those. Otherwise, I&amp;#8217;d love to hear your thoughts about JSCheck in the comments!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qNkRomtrJyXDqzCk_xHX46WDe48/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qNkRomtrJyXDqzCk_xHX46WDe48/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qNkRomtrJyXDqzCk_xHX46WDe48/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qNkRomtrJyXDqzCk_xHX46WDe48/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=elFnjAFtJ_Q:SrpB9skSgzk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=elFnjAFtJ_Q:SrpB9skSgzk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=elFnjAFtJ_Q:SrpB9skSgzk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=elFnjAFtJ_Q:SrpB9skSgzk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=elFnjAFtJ_Q:SrpB9skSgzk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=elFnjAFtJ_Q:SrpB9skSgzk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=elFnjAFtJ_Q:SrpB9skSgzk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=elFnjAFtJ_Q:SrpB9skSgzk:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/elFnjAFtJ_Q" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/tutorials/javascript-ajax/meet-crockford%e2%80%99s-jscheck/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/javascript-ajax/meet-crockford%e2%80%99s-jscheck/</feedburner:origLink></item>
		<item>
		<title>How to Super-Scale Magento in the Cloud</title>
		<link>http://feedproxy.google.com/~r/nettuts/~3/gCVIO2Y0hy4/</link>
		<comments>http://net.tutsplus.com/tutorials/php/how-to-super-scale-magento-in-the-cloud/#comments</comments>
		<pubDate>Tue, 15 May 2012 17:31:25 +0000</pubDate>
		<dc:creator>Jed Galbraith</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[pagoda box]]></category>
		<guid isPermaLink="false">http://net.tutsplus.com/?p=25037</guid>
		<description>&lt;a href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25037&amp;c=1348385573' target='_blank'&gt;&lt;img src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=25037&amp;c=1348385573' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;This tutorial will help you prepare a &lt;a href="http://www.magentocommerce.com/"&gt;Magento&lt;/a&gt; install for high traffic, better load times, and simpler ongoing site management. Ready?&lt;/p&gt;
&lt;p&gt;&lt;span id="more-25037"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
&lt;p&gt;You can &lt;a target="_blank" href="https://github.com/pagodabox/magento-install-basic/tarball/tutorial"&gt;download the finished code&lt;/a&gt; for this tutorial, or launch the &amp;#8220;magento-basic&amp;#8221; Quickstart from your Pagoda Box account to test a working site.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Pagoda Box Account (free)&lt;/li&gt;
&lt;li&gt;A functional local &lt;a target="_blank" href="http://www.magentocommerce.com/product/community-edition"&gt;Magento Install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Local Development Software (&lt;a target="_blank" href="http://www.mamp.info"&gt;MAMP&lt;/a&gt; or &lt;a target="_blank" href="http://www.wampserver.com"&gt;WAMP&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a target="_blank" href="http://git-scm.com/download"&gt;Git&lt;/a&gt; Installed (Can use SFTP)&lt;/li&gt;
&lt;li&gt;The Pagoda Terminal Client Installed&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;Fair Warning: This tutorial may change your life. &lt;a href="http://pagodabox.com/"&gt;Pagoda Box&lt;/a&gt; is not traditional hosting. The teachings in this article will not only help scale Magento, but it also lays the groundwork for a progressive development-to-production workflow. &lt;/p&gt;&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 1:&lt;/span&gt; Set Up Git Locally (SFTP will work as an alternate)&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;Note: If you already use Git, you can skip this section. If not, the guide &lt;a target="_blank" href="http://help.pagodabox.com/customer/portal/articles/202225-setting-up-git"&gt; Setting Up Git&lt;/a&gt; provides specific instructions for creating an SSH Key, as well as links for downloading and installing Git (also below).&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;While it is possible to use just &lt;a target="_blank" href="http://help.pagodabox.com/customer/portal/articles/401507"&gt;SFTP&lt;/a&gt; on Pagoda Box, the officially recommended (and most efficient) workflow integrates Git into your daily development. Git enables features like collaboration, uniform code distribution, deploys, deploy history and rolling back code. While most of these features are available to FTP users, using Git makes integration seamless.&lt;/p&gt;
&lt;p&gt;If you want to fully take advantage of Pagoda Box, &lt;a target="_blank" href="http://git-scm.com/download"&gt;download Git&lt;/a&gt;, and &lt;a target="_blank" href="http://git-scm.com/book/ch1-3.html"&gt;Learn the Basics&lt;/a&gt;. Depending on your operating system, set up may vary slightly. Regardless of your OS, the commands are identical once Git is installed.&lt;/p&gt;
&lt;p&gt;Using Git to manage collaboration and version control may involve a brief learning curve. However, there are generally only three commands we&amp;#8217;ll use on an ongoing basis to commit changes locally, then deploy to Pagoda Box:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git add . &lt;/code&gt; &amp;#8211; Adds local files to your repository&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -m "some message about what you've done"&lt;/code&gt; &amp;#8211; Commits your changes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git push pagoda --all&lt;/code&gt; &amp;#8211; Pushes changes to Pagoda Box Repository (auto-deployed by default)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;#8217;ll use these later.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 2:&lt;/span&gt; Install the Pagoda Box Terminal Client&lt;/h2&gt;
&lt;pre name="code" class="php"&gt;

                             *
                           /   \
                         /       \
                     +_/ / / | \ \ \_+
                         ||*|||*||
                         |+||*||+|
                         /       \
                     +_/ / / | \ \ \_+
                         ||*|||*||
                         |+||*||+|
     ____   _    ____  ___  ____    _    ____   _____  __
    |  _ \ / \  / ___|/ _ \|  _ \  / \  | __ ) / _ \ \/ /
    | |_) / _ \| |  _| | | | | | |/ _ \ |  _ \| | | \  /
    |  __/ ___ \ |_| | |_| | |_| / ___ \| |_) | |_| /  \
    |_| /_/   \_\____|\___/|____/_/   \_\____/ \___/_/\_\

       Welcome To Your Pagoda Box Terminal Client.
      -----------------------------------------------
          -----------------------------------------
             ---------------------------------
                          Enjoy.&lt;/pre&gt;
&lt;p&gt;Pagoda Box provides a Terminal Client that lets you clone, create, deploy, destroy, rename and rollback an application from the command line. Later in this tutorial, we&amp;#8217;ll use the client to create a secure tunnel to the live Magento database with Sequel Pro (the process is similar for other database managment tools like HeidiSQL).&lt;/p&gt;
&lt;p&gt;The Pagoda Box Terminal Client is a rubygem, so installation is pretty simple. First off, Ruby needs to be installed. Installation is different for each operating system.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mac &amp;#8211; Ruby and RubyGems come pre-installed on Mac OSX. As long as you are running v10.5 or later, you should be good to go.&lt;/li&gt;
&lt;li&gt;Windows &amp;#8211; There are a couple of different ways to install Ruby in Windows. We recommend this &lt;a target="_blank" href="http://rubyinstaller.org/"&gt;auto-installer&lt;/a&gt;. If it doesn&amp;#8217;t work for your set-up, a Google search will give you a pretty good list of installation walk-throughs.&lt;/li&gt;
&lt;li&gt;Linux &amp;#8211; Use your preferred package manager to download the Ruby package. For Ubuntu users, the gem is available through &lt;a target="_blank" href="http://www.getdeb.net/software/Pagoda%20Terminal%20Client"&gt;getdeb.net.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Install and Verify Terminal Client&lt;/h3&gt;
&lt;p&gt;Once Ruby is installed, simply run the following command to install the Pagoda RubyGem:&lt;/p&gt;
&lt;p&gt; On Mac or Linux:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
$ sudo gem install pagoda
&lt;/pre&gt;
&lt;p&gt; On Windows:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
$ gem install pagoda
&lt;/pre&gt;
&lt;p&gt;Then, to verify you have the Pagoda Gem installed properly, run:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
$ pagoda list
&lt;/pre&gt;
&lt;p&gt;If this is the first time you&amp;#8217;ve used the Gem, it will ask for your Pagoda Box Username and Password. After you&amp;#8217;ve entered those, expect to see a list of your Pagoda Box applications. If you haven&amp;#8217;t created any applications, the list will be blank.&lt;/p&gt;
&lt;p&gt;If you get an error, it&amp;#8217;s most likely invalid credentials. You can verify or change which credentials the gem uses by editing the file located on your local computer at &lt;code&gt;~/.pagodarc&lt;/code&gt;. Make sure to exactly match the credentials you use in your Pagoda Box account. (Note: this is a hidden file, so you&amp;#8217;ll need to enable hidden files or open via the terminal. Also note that the file stores your credentials twice, so edit both if needed.)&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 3:&lt;/span&gt; Install Magento Locally&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;Note: Skip this step if you already have a working local Magento install.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If you don&amp;#8217;t have it already, ensure you are using local webserver and database management software. There are several options available, depending on your operating system. A common option for Mac is &lt;a target="_blank" href="http://www.mamp.info"&gt;MAMP&lt;/a&gt;, or &lt;a target="_blank" href="http://www.wampserver.com"&gt;WAMP&lt;/a&gt; for Windows. Both are free and easily set up.&lt;/p&gt;
&lt;p&gt;Once your local development environment is set up, go ahead and &lt;a target="_blank" href="http://www.magentocommerce.com/download"&gt;download Magento,&lt;/a&gt; then follow the &lt;a target="_blank" href="http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/magento_installation_guide"&gt;official guide&lt;/a&gt; to install Magento locally.&lt;/p&gt;
&lt;p&gt;Feel free to use Magento&amp;#8217;s auto install script to set up the application in your local environment. However, due to Pagoda Box&amp;#8217;s distributed cloud architecture, the script will not install Magento directly in your production environment. The Pagoda Box workflow and architecture requires you to make code modifications locally, commit, then deploy to production. This workflow accommodates collaboration and development &gt; staging &gt; production best practices.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-magento-installation.jpg" border="0" /&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 4:&lt;/span&gt; Configure PHP Using a Boxfile&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;Note: On Pagoda Box, a YAML &lt;a target="_blank" href="http://help.pagodabox.com/customer/portal/articles/175475-understanding-the-boxfile"&gt;Boxfile&lt;/a&gt; can be included in the root of your code repository. While the Boxfile is optional, it does provide advanced features, like manipulating your hosted environment on each deploy. We&amp;#8217;ll use the Boxfile extensively in this Tutorial to simplify tasks, and to make the respository reusable on Pagoda Box.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Create a file named &amp;#8220;Boxfile&amp;#8221; in the root of your local Magento installation, then copy the following into your Boxfile (explanation below):&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
web1:
  name: mag-app
  shared_writable_dirs:
    - media
    - var
  php_version: 5.3.8
  php_extensions:
    - pdo_mysql
    - mysql
    - simplexml
    - mcrypt
    - hash
    - gd
    - dom
    - iconv
    - curl
    - soap
&lt;/pre&gt;
&lt;h3&gt;Create / Name the Web Cluster&lt;/h3&gt;
&lt;p&gt;This Boxfile serves several purposes. First, it creates a &lt;code&gt;web1&lt;/code&gt; component, then names it &lt;code&gt;mag-app&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Shared Writable Directories&lt;/h3&gt;
&lt;p&gt;Second, the Boxfile identifies &lt;code&gt;media&lt;/code&gt; and &lt;code&gt;var&lt;/code&gt; as shared writable directories. This allows users to upload images, video, and other media to a distributed Magento cloud site without instances writing themselves out of sync.&lt;/p&gt;
&lt;p&gt;When a directory is marked as writable, the contents are no longer deployed to Pagoda Box from your local repository. Any time local files need to be deployed to these directories, they must be manually copied via SSH or SFTP. You may also &lt;a target="_blank" href="http://help.pagodabox.com/customer/portal/articles/175418-shared-writable-storage-management"&gt;use SSH/SFTP to transfer files&lt;/a&gt; from Pagoda Box to your local machine as needed.&lt;/p&gt;
&lt;h3&gt;PHP Version and Extensions&lt;/h3&gt;
&lt;p&gt;The Boxfile also declares which PHP version and extensions will be included in your web instances as they deploy. This way, both the environment and the application are versioned together, so rolling back to a previous deploy includes the correct PHP version and extensions. The list of PHP extensions in this Boxfile was taken from Magento&amp;#8217;s official system requirements.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Tip: Once Git is installed in your local environment, use the &lt;code&gt;.gitignore&lt;/code&gt; file to ignore the writable directories specified in your Boxfile. Identifying these directories inside the &lt;code&gt;.gitignore&lt;/code&gt; file helps reduce the size of your repo, and your deploy time. In addition to the writable directories, you can also add the &lt;code&gt;downloader&lt;/code&gt; directory to the &lt;code&gt;.gitignore&lt;/code&gt; file, since it&amp;#8217;s used locally, and not on Pagoda Box.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Once you&amp;#8217;ve installed Git and the Terminal Client, configured the Boxfile and finalized your local source code, you&amp;#8217;re ready to launch on Pagoda Box.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 5:&lt;/span&gt; Create a Free Pagoda Box Account&lt;/h2&gt;
&lt;p&gt;If you don&amp;#8217;t already have one, create a free &lt;a target="_blank" href="http://www.pagodabox.com/account/register"&gt;Pagoda Box account.&lt;/a&gt; You will not need to enter a credit card to install Magento for testing.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-box-register.jpg" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;If you have not already done so, follow this guide to &lt;a target="_blank" href="http://help.pagodabox.com/customer/portal/articles/200927#add-ssh-pagoda"&gt;Add an SSH Key&lt;/a&gt; in your Pagoda Box Admin panel. The guide will provide specific instructions for setting up an SSH Key on either Mac or Windows.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 6:&lt;/span&gt; Upload Magento to Pagoda Box&lt;/h2&gt;
&lt;p&gt;Once you&amp;#8217;ve created a Pagoda Box account and set up an SSH Key, go to the Home Page in your new account and click the &amp;#8220;New Application&amp;#8221; button to create a new application.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Note: This tutorial names our sample application &amp;#8220;magento&amp;#8221;. The app name is also used for the Pagoda Box repository, the subdomain for the freshly deployed application (magento.pagodabox.com), and the username in SFTP mode. Replace &amp;#8220;magento&amp;#8221; with &amp;#8220;your-app-name-here&amp;#8221; where appropriate throughout the remainder of this tutorial.&lt;/p&gt;&lt;/blockquote&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-new-app-button.jpg" border="0" /&gt;&lt;/div&gt;
&lt;h3&gt;Upload to an Empty Repo (recommended for this tutorial)&lt;/h3&gt;
&lt;p&gt;Next, choose from the 3 options to launch your Magento site. Since you already have a customized version of Magento locally, select &amp;#8216;Empty Repo&amp;#8217; to deploy using SFTP or Git, name your application, and click &amp;#8220;Launch Application&amp;#8221;.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-empty-repo.jpg" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;You&amp;#8217;ll be asked to select your preferred deployment method (Git or SFTP). Click on your preference, and follow the instrutions on-screen.&lt;/p&gt;
&lt;h3&gt;Git Option&lt;/h3&gt;
&lt;p&gt;You can copy and paste the on-screen instructions from the Pagoda Box dashboard to your terminal after using Terminal to change directory (cd) to the root of your project.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-choice.png" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;The pasted commands do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git init &lt;/code&gt; &amp;#8211; Initialize your Magento project as a Git Repository&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add . &lt;/code&gt; &amp;#8211; Add all files from the project to the repo&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -m 'your commit message' &lt;/code&gt; &amp;#8211; Commit files with a message that allows you to quickly scan deploy history in the future, in case you need to revert or modify changes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git remote add pagoda git@git.pagodabox.com:magento.git &lt;/code&gt; &amp;#8211; Add Pagoda Box as a remote (the specific git url for your application appears on both this screen, and in your app dashboard&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git push pagoda --all &lt;/code&gt; &amp;#8211; Push your local code to the Pagoda Box remote repository. As long as you&amp;#8217;re on the &amp;#8220;master&amp;#8221; branch (which is the default), Pagoda Box will automatically deploy your code, and carry out the instructions we set in the Boxfile. Auto-deploy can be turned off in the Admin dashboard, or configured to deploy automatically from a Git branch other than Master.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;SFTP Option&lt;/h3&gt;
&lt;p&gt;If you opted for SFTP, Pagoda Box will guide you through establishing credentials and a password. Connect via SFTP to Pagoda Box, and upload your Magento source code in the &lt;code&gt;code&lt;/code&gt; directory.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-sftp.jpg" border="0" /&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 7:&lt;/span&gt; Create a Database&lt;/h2&gt;
&lt;p&gt;There are two ways to create a database on Pagoda Box. Each has benefits, explained below:&lt;/p&gt;
&lt;h3&gt;Create a DB in the Boxfile&lt;/h3&gt;
&lt;p&gt;The Boxfile will automatically create a database component on deploy, as long as that component (&lt;code&gt;db1&lt;/code&gt;, &lt;code&gt;db2&lt;/code&gt;, etc.) doesn&amp;#8217;t already exist. Declaring the database in the Boxfile saves a bit of time now, and makes deploying multiple Magento sites from a standardized code base much simpler in the future. (Note: Only cloud DBs can be deployed from the Boxfile. If you need a larger, dedicated or redundant database, see the Dashboard option later in this Step.) Add the following to your Boxfile: &lt;/p&gt;
&lt;pre name="code" class="php"&gt;
db1:
  name: mag-db
  type: mysql
  &lt;/pre&gt;
&lt;p&gt;Your updated Boxfile should look like this:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
web1:
  name: mag-app
  shared_writable_dirs:
    - media
    - var
  php_version: 5.3.8
  php_extensions:
    - pdo_mysql
    - mysql
    - simplexml
    - mcrypt
    - hash
    - gd
    - dom
    - iconv
    - curl
    - soap
db1:
  name: mag-db
  type: mysql
  &lt;/pre&gt;
&lt;p&gt;Then commit changes to the updated file and push changes to Pagoda Box:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
$ git commit -m "pagoda config"
$ git push pagoda --all
&lt;/pre&gt;
&lt;h3&gt;Alternate: Create a DB in the Dashboard&lt;/h3&gt;
&lt;p&gt;You can also create a database from the Pagoda Box Dashboard. This is where you add a larger, dedicated or redundant database.&lt;/p&gt;
&lt;p&gt;First, click &amp;#8220;Add Database&amp;#8221; in the Dashboard.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-add-db.jpg" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;Pagoda Box will step through a series of screens to configure your database, depending on your choices. If you&amp;#8217;ve chosen the Dedicated option, you will be asked to size your database as follows:&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-dedicated-db.jpg" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;Cloud databases usually deploy within minutes. If you chosen Dedicated, don&amp;#8217;t get impatient. You may wait for up to 90 minutes for a big server to be provisioned to your specifications.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 8:&lt;/span&gt; Configure DB Credentials for Production&lt;/h2&gt;
&lt;p&gt;Your database automatically generates credentials when it&amp;#8217;s created on Pagoda Box. We&amp;#8217;ll use those credentials to configure Magento in production.&lt;/p&gt;
&lt;p&gt;However, since Magento will be used in both local environments and in production, we need to supply different database credentials for each. We&amp;#8217;ll use Deploy Hooks in the Boxfile to simplify this process by executing scripts or commands during deploy.&lt;/p&gt;
&lt;p&gt;In the case of Magento, we&amp;#8217;ll swap the &lt;code&gt;local.xml&lt;/code&gt; file upon deploy. That way, without manually switching credentials, the &lt;code&gt;app/etc/local.xml&lt;/code&gt; file will automatically have local database credentials in development, but production database credentials on Pagoda Box.&lt;/p&gt;
&lt;h3&gt;Create a local.xml for Production&lt;/h3&gt;
&lt;p&gt;First, create a directory named &lt;code&gt;pagoda&lt;/code&gt; in root, then copy Magento&amp;#8217;s &lt;code&gt;app/etc/local.xml&lt;/code&gt; to the new directory.&lt;/p&gt;
&lt;p&gt;Next, edit &lt;code&gt;local.xml&lt;/code&gt; to include Pagoda Box database credentials from your account dashboard. Note that Pagoda Box uses 3 levels of authentication, so that even if your credentials are compromised, other users cannot access your database.&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-db-credentials.jpg" border="0" /&gt;&lt;/div&gt;
&lt;h3&gt;Swap local.xml Configs on Deploy&lt;/h3&gt;
&lt;p&gt;Add the following into your Boxfile, under the &lt;code&gt;web1&lt;/code&gt; section to create the Deploy Hook.&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
after_build:
  "mv pagoda/local.xml app/etc/local.xml"
&lt;/pre&gt;
&lt;p&gt;Your updated Boxfile should look like this:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
web1:
  name: mag-app
  shared_writable_dirs:
    - media
    - var
  php_version: 5.3.8
  php_extensions:
    - pdo_mysql
    - mysql
    - simplexml
    - mcrypt
    - hash
    - gd
    - dom
    - iconv
    - curl
    - soap
  after_build:
  - "mv pagoda/local.xml app/etc/local.xml"
db1:
  name: mag-db
  type: mysql
  &lt;/pre&gt;
&lt;p&gt;Then commit changes and push to Pagoda Box:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
$ git add .
$ git commit -m "pagoda config"
$ git push pagoda --all
&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 9:&lt;/span&gt; Migrate the Database&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;With the same tools you use to manage a local database, you can securely manage a live database on Pagoda Box. We&amp;#8217;ll use Sequel Pro for this example, but the process is similar for tools like HeidiSQL.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3&gt;Export Your Local DB&lt;/h3&gt;
&lt;p&gt;When the Magento install script ran locally, it created several tables in the local database. Those tables need to be migrated to production.&lt;/p&gt;
&lt;p&gt;First, export your local database using your database manager: File &gt; Export.&lt;/p&gt;
&lt;p&gt;Now choose a location, and Save the export.&lt;/p&gt;
&lt;h3&gt;Establish a Secure DB Connection&lt;/h3&gt;
&lt;p&gt;Now establish a database tunnel. Using the Pagoda Box Terminal Client, specify the app whose database you are trying to access, and the ID of the database component (e.g. db1), as in this example:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
$ pagoda -a magento tunnel -c db1
--OR--
$ pagoda --app=magento tunnel --component=db1
&lt;/pre&gt;
&lt;p&gt;Once the tunnel is established, use Sequel Pro (or similar) to connect to the database using the Host and Port provided by the Pagoda Terminal Client&amp;#8230;&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-host-port.png" border="0" /&gt;&lt;/div&gt;
&lt;p&gt;And the username and password in your Pagoda database credentials. These were automatically created with your database, and may be found in the Pagoda Box Dashboard under the database component (see example in Step 8).&lt;/p&gt;
&lt;h3&gt;Import and Update the Production DB&lt;/h3&gt;
&lt;p&gt;Next, import your database into production using Sequel Pro (or similar): File &gt; Import. Now select the database export file, and Open.&lt;/p&gt;
&lt;p&gt;Finally, since we ran the install script locally, it&amp;#8217;s necessary to adjust the base url directly in the database before browsing the site. While you are still connected to the Pagoda Box database in Sequel Pro, navigate/filter to the &lt;code&gt;core_config_data&lt;/code&gt; table and edit the value for the following paths:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
web/unsecure/base_url
web/secure/base_url
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;The values for each should look something like this:&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-sequel-pro.jpg" border="0" /&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 10:&lt;/span&gt; Configure Mail&lt;/h2&gt;
&lt;p&gt;To protect your IPs from being flagged as spam, Pagoda Box uses the SMTP mail protocol to send email via third party mail provider SMTP credentials. In English, that means you need a company (like Gmail) that provides mail services.&lt;/p&gt;
&lt;p&gt;Regardless of which mail provider you choose, enter account credentials from that provider in your Pagoda Box dashboard. It should look something like this:&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-mail-dash.jpg" border="0" /&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Step 11:&lt;/span&gt; Cron Jobs (Optional)&lt;/h2&gt;
&lt;p&gt;A few recurring tasks in Magento (e.g. sending newsletters, log cleaning, customer notifications, etc.) need to happen periodically. The &lt;code&gt;cron.php&lt;/code&gt; file located in Magento&amp;#8217;s root will trigger these tasks. We&amp;#8217;ll set up a Cron Job in the Pagoda Box admin panel to run &lt;code&gt;cron.php&lt;/code&gt; every 15 minutes. (Note: To configure Magento specific tasks, see their &lt;a target="_blank" href="http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/how_to_setup_a_cron_job#unixbsdlinux"&gt;Official Guide.&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;Cron Jobs in the Boxfile&lt;/h3&gt;
&lt;p&gt;Cron Jobs can be added or updated via the Boxfile, then deployed to Pagoda Box. To schedule a task at 15 minute intervals, add the following to your Boxfile under the &lt;code&gt;web1:&lt;/code&gt; component (change the &amp;#8220;magento&amp;#8221; to point to your own app name / subdomain):&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
  cron:
    - "*/15 * * * *": "curl -s -o /dev/null http://magento.pagodabox.com/cron.php"
    &lt;/pre&gt;
&lt;p&gt;Your updated Boxfile should look like this:&lt;/p&gt;
&lt;pre name="code" class="php"&gt;
web1:
  name: mag-app
  shared_writable_dirs:
    - media
    - var
  php_version: 5.3.8
  php_extensions:
    - pdo_mysql
    - mysql
    - simplexml
    - mcrypt
    - hash
    - gd
    - dom
    - iconv
    - curl
    - soap
  after_build:
  - "mv pagoda/local.xml app/etc/local.xml"
cron:
    - "*/15 * * * *": "curl -s -o /dev/null http://magento.pagodabox.com/cron.php"
db1:
  name: mag-db
  type: mysql
  &lt;/pre&gt;
&lt;h3&gt;Alternate: Cron Jobs in the Dashboard&lt;/h3&gt;
&lt;p&gt;In the Pagoda Box admin panel under the Cron tab, add the following (change the &amp;#8220;magento&amp;#8221; to point to your own app name):&lt;/p&gt;
&lt;p&gt;Command: &lt;code&gt;curl -s -o /dev/null http://magento.pagodabox.com/cron.php&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Schedule:  &lt;code&gt;*/15 * * * *&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It should look like this:&lt;/p&gt;
&lt;div class="tutorial_image"&gt;&lt;img src="http://d2o0t5hpnwv4c1.cloudfront.net/2038_magentoScale/pagoda-cron-dash.jpg" border="0" /&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt; &lt;span&gt;Part 2 &amp;#8211; Optimization:&lt;/span&gt; Redis, Scaling &amp;#038; Benchmarking&lt;/h2&gt;
&lt;p&gt;You&amp;#8217;ve already gotten the heavy lifting out of the way. Your Magento application is scalable, and changes are easily deployed across all instances with &lt;code&gt;$ git push pagoda --all&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the follow-up article, we&amp;#8217;ll optimize Magento, add a Redis cache, SSL and Domain aliases, then scale the application for benchmarking and production. See you soon!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AfTPf0WMHHY9sZYknY-Dstp6rYA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AfTPf0WMHHY9sZYknY-Dstp6rYA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AfTPf0WMHHY9sZYknY-Dstp6rYA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AfTPf0WMHHY9sZYknY-Dstp6rYA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=gCVIO2Y0hy4:iklNFAMdN6o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=gCVIO2Y0hy4:iklNFAMdN6o:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=gCVIO2Y0hy4:iklNFAMdN6o:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=gCVIO2Y0hy4:iklNFAMdN6o:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=gCVIO2Y0hy4:iklNFAMdN6o:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=gCVIO2Y0hy4:iklNFAMdN6o:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=gCVIO2Y0hy4:iklNFAMdN6o:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=gCVIO2Y0hy4:iklNFAMdN6o:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/gCVIO2Y0hy4" height="1" width="1"/&gt;</description>
		<wfw:commentRss>http://net.tutsplus.com/tutorials/php/how-to-super-scale-magento-in-the-cloud/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		<feedburner:origLink>http://net.tutsplus.com/tutorials/php/how-to-super-scale-magento-in-the-cloud/</feedburner:origLink></item>
	<media:rating>nonadult</media:rating></channel>
</rss><!-- Dynamic Page Served (once) in 0.709 seconds -->

