<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>The Stickies Project</title>
	<atom:link href="http://thestickiesproject.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://thestickiesproject.wordpress.com</link>
	<description>All stickies, all the time</description>
	<lastBuildDate>Wed, 12 May 2010 15:25:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='thestickiesproject.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>The Stickies Project</title>
		<link>http://thestickiesproject.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://thestickiesproject.wordpress.com/osd.xml" title="The Stickies Project" />
	<atom:link rel='hub' href='http://thestickiesproject.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Where&#8217;s the Sticky? Behaviors over Classes in JS</title>
		<link>http://thestickiesproject.wordpress.com/2010/05/12/wheres-the-sticky/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/05/12/wheres-the-sticky/#comments</comments>
		<pubDate>Wed, 12 May 2010 13:46:33 +0000</pubDate>
		<dc:creator>sarahggray</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=205</guid>
		<description><![CDATA[Imagine the sticky as a thing with a varied set of behaviors. Physically, it is a div &#8212; a DOM element made up of other DOM elements that have unique IDs and classes.  It is styled to look like the little thing you get from your office supply closet. And as for what it does? Well, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=205&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Imagine the sticky as a thing with a varied set of behaviors. Physically, it is a div &#8212; a DOM element made up of other DOM elements that have unique IDs and classes.  It is styled to look like the little thing you get from your office supply closet. And as for what it does? Well, it has a bunch of different ways that it can behave:</p>
<p>It has <em>dragging-related behaviors</em>: it drags, groups, sticks and un-sticks.  It has <em>editing-related behaviors</em>: it records and remembers stuff you type into it. It will have <em>physical behaviors</em> such as the ability to minimize and enlarge.  And it will be able to export its data when asked, either independently or from the group it belongs to.</p>
<p>One way of looking at this is as a <em>collection of state and behavior</em>: an object. State includes visual properties (such as  color, width, height) and behavioral properties (such as flags that indicate whether it is in &#8220;sticky&#8221; mode or not).  Behavior includes methods for dragging, grouping, sticking and unsticking, sharing content, resizing, etc.</p>
<p>It would therefore be easy to extrapolate this to a class <em>Sticky</em> that might look something like this (JavaScript-y pseudocode):</p>
<p><span id="more-205"></span></p>
<pre>var Sticky = (function(){
  return{
    color: yellow,
    width: 100px,
    height: 100px,
    isSticky: true,
    findOrCreate: function(domId){
      var sticky = $(domId);
      sticky.attr("color", color);
      // etc.
      return sticky;
    },
    onDrag: function(dragEvent){
       // do something to handle dragging
    },
   onSave:function(){
      // do something to handle saving via AJAX
   }
   // etc.
  };
}());</pre>
<p>Where  you find or create the relevant DOM object, encapsulate it in a <em>Sticky</em> namespace, and bind static properties and behaviors triggered by events.</p>
<p>This is reasonable, but this can quickly get unwieldy because the DOM element is mixed up in the logic and because there are methods that handle different types of behavior all mixed into one class. While it is only 15 or so lines above, it would grow with new functionality such as exporting, docking, etc.</p>
<p>Given this, we moved away from the idea of a <em>class</em> Sticky that can stamp out sticky objects, and towards building collections of behaviors that can be applied on as as-needed basis to DOM elements &#8212; e.g., behaviors that  &#8220;make&#8221; an existing DOM element &#8220;sticky&#8221;.</p>
<p>I think of it as creating an <em>enhanced element</em>. The canonical representation of a sticky is the DOM element and behaviors are applied on a just-in-time basis. For instance, a &#8220;dragging sticky&#8221; is what is able to drag around and do all drag-related activities. Think of it like wrapping a sticky in adjectives to make it &#8216;enhanced&#8217; in a particular way.</p>
<p>Here&#8217;s an example, a proof-of-concept created in a JavaScript spike session:</p>
<pre>
var createDraggingSticky = function(sticky_dom_element, newNeighborMover, neighborLookup){
    var sticky_id = sticky_dom_element.attr("id");
    var draggingSticky = {
      dom_element: sticky_dom_element,
      id: sticky_id,
      updatePositionBy: function(dx, dy){
          var element, oldLeft, oldTop;
          element = $(this.dom_element);
          oldLeft = element.position().left;
          oldTop =  element.position().top;
          element.css("left", oldLeft+dx);
          element.css("top", oldTop+dy);
      },
      youAreBeingDragged : function(dx, dy, neighborMover) {
          if(!neighborMover) {
             neighborMover = newNeighborMover(this);
          }
          neighborMover.moveMyNeighbors(dx,dy, this);
          this.updatePositionBy(dx, dy);
      },
      getNeighbors:function() {
          return neighborLookup(this);
      }
};</pre>
<p>And this gets attached on the drag handler, which gets triggered by jQuery drag, like so:</p>
<pre>draggingSticky = createDraggingSticky($(ui.helper), Factories.neighborMover, Relationships.getNeighbors);</pre>
<p>So until the div is dragged &#8212; and again, after it is dragged &#8212; it is just a regular DOM element wired up with a few jQuery plugins such as draggable and editable. When the dragging starts and the sticky needs to be able to call upon its dragging behaviors, a reference to the DOM element is passed to the dragging behaviors (so they know who to act on), and the behaviors are attached and can interact with the sticky: at this point the sticky is now dragging_sticky.</p>
<p>Then, when the sticky <em>stops</em> dragging, its neighborlookup and other caches are cleared, and the behaviors are no longer applied.  The pattern reminds me of mixing in a module of behavior in Ruby, except here it is mixed in just in time for use and only the relevant module is added at any given point.</p>
<p>From the standpoint of a user interacting with the application, however, it appears that the sticky <em>always</em> has those behaviors: after all, every time you drag it, it acts like a dragging_sticky, and you never see it behaving as a non-dragging-sticky. Sure, when it&#8217;s sitting still and you&#8217;re just writing in it, you could say it&#8217;s non-dragging, but that&#8217;s not really fair, since it&#8217;s not supposed to be dragging then. So in this respect &#8212; from the experience of it &#8212; it is seamless and always endowed with what it needs.</p>
<p>But from an application standpoint the &#8216;enhanced stickies&#8217; are ephemeral: they only exist during the time they are needed, rather than hanging around in memory or cluttering up a large object, such as my JS pseudo-code example from before.  Instead of 50 JavaScript objects held in memory, waiting to be used, we have 50 DOM elements, each able to be enhanced on a hair trigger and reverted as needed.  It&#8217;s a smaller footprint.</p>
<p>Similar patterns can be applied for other types of behaviors, such as physical behaviors and editing behaviors I mentioned at the beginning. We&#8217;re still working this out, but it seems very promising and clean, and it keeps a clear separation between the DOM side of things and the application logic side of things.</p>
<p>As a final thought, working in this way reminds me of getting my head around the concept of Existentialism in college: the philosophy that a person is a total of their actions, not a predetermined &#8220;self&#8221;. While a person may appear to be a seamless construct of self (indisputably Sarah or indisputably Zak), we really just seem that way because for the most part, our behavior sets are consistent with themselves &#8212; i.e., I usually do things that I usually do. However, if I change my actions, I am changing myself.</p>
<p>It is really that idea we are building into the application as we move away from the immutable concept of the Class into a shifting collection of actions that are applied at runtime.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/205/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=205&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/05/12/wheres-the-sticky/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a76239db5edcb9923d04687bda88cf27?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sarahggray</media:title>
		</media:content>
	</item>
		<item>
		<title>Simple Design starts from the outside in</title>
		<link>http://thestickiesproject.wordpress.com/2010/04/08/simple-design-starts-from-the-outside-in/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/04/08/simple-design-starts-from-the-outside-in/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 17:12:43 +0000</pubDate>
		<dc:creator>coreyhaines</dc:creator>
				<category><![CDATA[Design]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=186</guid>
		<description><![CDATA[I ran into 2 interesting situations while working on claimed/unclaimed surfaces that appeared different, but they both ended up being very similar when deciding on the solutions. First: what should the URL for unclaimed surfaces be? My first thought was /surfaces; That seemed reasonable. Then I wondered about using /surfaces/unclaimed. Is the extra part of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=186&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I ran into 2 interesting situations while working on claimed/unclaimed surfaces that appeared different, but they both ended up being very similar when deciding on the solutions.</p>
<p><i>First:</i> what should the URL for unclaimed surfaces be? My first thought was /surfaces; That seemed reasonable. Then I wondered about using /surfaces/unclaimed. Is the extra part of the URL unnecessary, is it a violation of <a href="http://c2.com/cgi/wiki?YouArentGonnaNeedIt">YAGNI</a>?</p>
<p><i>Second:</i> what should the URL for viewing your claimed surfaces be? Should it be /surfaces/claimed, showing the surfaces belonging to the logged-in user? Or, should I be explicit and use /users/:user_id/surfaces? Should I also add /users/:user_id/surfaces/claimed?</p>
<p>I had an intuition about what the solutions should be, but, when I am uncertain, I like to fall back on base principles, such as the <a href="http://c2.com/xp/XpSimplicityRules.html">4 rules of simple design</a> and the <a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod">SOLID</a> principles. I thought I would write a blog post outlining how I went about analyzing these 2 problems.</p>
<h3>Simple Design</h3>
<p>The 4 rules of simple design are as follows:</p>
<ul>
<li>Passes all tests</li>
<li>Reveals Intent</li>
<li>Contains no duplication</li>
<li>Is Small</li>
</ul>
<p><a href="http://www.twitter.com/jbrains">J.B. Rainsberger</a> makes a convincing argument that there are really only 2 rules: no duplication and reveals intent, since &#8216;passing all tests&#8217; is like breathing and &#8216;is small&#8217; comes naturally from the other principles.</p>
<p><span id="more-186"></span></p>
<h3>Unclaimed Surfaces </h3>
<p>A driving force in the user experience for the stickies project is the ability to very quickly try the system, even before registering. The surfaces created by unregistered users are considered &#8216;unclaimed&#8217; and public to everyone else. I wrote a <a href="http://thestickiesproject.wordpress.com/2010/03/09/claimed-and-unclaimed-surfaces/">blog post</a> outlining this approach a little while ago. A major and important decision is what the URL should be for these surfaces (Sarah wrote <a href="http://thestickiesproject.wordpress.com/2010/03/04/domain-modeling-for-dummies/">a post on our choice of domain</a>). The natural first thought would be /surfaces, since it seems like a natural root name.</p>
<p>Thinking about this, though, I realized that the decision to use /surfaces as the url broke the rule about revealing intent. This rule can also be thought of as &#8216;named clearly.&#8217; What is the usual expectation of a URL like /surfaces? In general, it is used as the index, or the list of all surfaces. Giving it an implicit filter (unclaimed) is a violation of this. Another interpretation of &#8216;reveals intent&#8217; is the Principle of Least Surprise &#8211; you shouldn&#8217;t be surprised when you access something. An explicit URL for the unclaimed surfaces would be /surfaces/unclaimed.</p>
<p>Being explicit also opens you up to extensibility and future enhancements without having to worry about it. No, I&#8217;m not saying that you should be designing for unknown future requirements, but, given a choice, I like to choose the path which will give me the most flexibility in the future. Having explicit filters on the /surfaces URL, such as /unclaimed, provides both a precedent and a mechanism for this. I am a firm follower of the SOLID principles, and one of my favorites is the Open-Closed principle: systems should be open for extensibility, closed for modification. There are a lot of resources online with detailed explanations, but it boils down to this: build systems that can accept behavorial changes through extension without requiring modification of the core system. We can take this idea to our resource locators, as well. So, if we hide some implementation behind /surfaces, then we create the potential need to change what it means in the future. By relying on a form of extension, /surfaces/unclaimed, then we create a situation where we can more easily and predictable add future behaviors simply by adding a new filter: /surfaces/private or /surfaces/about_to_be_deleted, for example.</p>
<h3>Claimed Surfaces</h3>
<p>Viewing a user&#8217;s claimed surfaces seems natural to use /users/:user_id/surfaces. Most people wouldn&#8217;t argue with this. When using an authentication system in Rails, though, generally you are given a #current_user method on your controller. This provides access to the currently logged-in user. I often see people taking a shortcut when scoping resources. In our case, it would be using #current_user to scope the surfaces given when accessing /surfaces. So, when you access /surfaces, you are actually getting the equivalent of current_user.surfaces, or, all the surfaces belonging to the logged-in user. This seems reasonable, since it feels like overkill to provide the user id on the URL: /users/:user_id/surfaces. We already have the user id, don&#8217;t we? Don&#8217;t the 4 rules say we shouldn&#8217;t have duplication? Yes, they do, but this isn&#8217;t really duplication. In addition, this scheme creates a severe inconsistency in the addressing scheme due to a subtle implication of the DRY principle.</p>
<p>The idea of duplication isn&#8217;t just about code, but more importantly about concepts. The DRY principle (don&#8217;t repeat yourself) is a form of &#8216;every concept should have a single representation in your system.&#8217; There is a nice corollary that every representation should be of one concept.</p>
<p>Suppose you use /users/:user_id/surfaces to view some claimed surfaces (other people&#8217;s), yet /surfaces or /surfaces/claimed to see your own. The concept of &#8216;surfaces claimed by a user&#8217; now has two different representations in the system. The second rule of simple design (eliminate duplication) comes into play, so we should eliminate one of them; since we already have a concrete use for /users/:user_id/surfaces, it makes sense to stick with that.</p>
<p>What about duplication between the location of the user id: if my id is 3, then I have /users/3/surfaces, and I also have a 3 in my session somewhere, stored as &#8216;current user id.&#8217; Is this duplication? No, it isn&#8217;t; it is just happenstance that they coincide. When eliminating duplication, it is important to remember that you sometimes have constants which represent different concepts. In this case, the concepts are &#8216;user owning the viewed surfaces&#8217; and &#8216;user currently logged in.&#8217;</p>
<p><b>Aside:</b> This idea of a number representing two different concepts comes up a lot at coderetreat. According to the rules of Conway&#8217;s Game of Life, a live cell stays alive if it has 3 neighbors, and a dead cell comes to life if it has 3 neighbors. It is common to see people refactor both of those 3&#8242;s into a single representation. This generally leads to less understandable code, as the meaning gets lost, muddled in a haze between two different thoughts. It also makes the system less flexible, as the extraction of the &#8216;magic number&#8217;-ness of it becomes difficult, due to an unnecessary coupling between the two different rules.</p>
<p>Should it be /users/:user_id/surfaces/claimed?</p>
<p>This is an interesting question. On one hand, we do have /surfaces/unclaimed, so it seems as though the symmetry of having /users/:user_id/surfaces/claimed is desirable. But, taking this URL apart, we can notice something important: there is duplication in concept. The URL /users/:user_id/surfaces reads as &#8216;the surfaces belonging to the user represented by :id.&#8217; The /surfaces/claimed reads &#8216;the surfaces claimed by &#8230;&#8217; Since &#8216;belonging to&#8217; and &#8216;claimed by&#8217; are synonyms in our system, we can see that the single URL /users/:user_id/surfaces/claimed has duplication in it. Since we have already seen that the prefix /users/:user_id is needed, the /claimed suffix should be dropped.</p>
<p>So, all of this discussion has lead us to the following identifiers for our collections:</p>
<p>/surfaces &#8211; all surfaces, both claimed and unclaimed. What does this mean, how best to represent it? I&#8217;m not sure, and I don&#8217;t think we&#8217;ll implement this quite yet;<br />
/surfaces/unclaimed &#8211; all unclaimed surfaces;<br />
/users/:user_id/surfaces &#8211; all claimed surfaces for user represented by :id;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/186/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=186&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/04/08/simple-design-starts-from-the-outside-in/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d7807bb66e1a0c68c73ab2daaa77d8f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">coreyhaines</media:title>
		</media:content>
	</item>
		<item>
		<title>Moving Patterns</title>
		<link>http://thestickiesproject.wordpress.com/2010/04/06/moving-patterns/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/04/06/moving-patterns/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 19:22:40 +0000</pubDate>
		<dc:creator>sarahggray</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=163</guid>
		<description><![CDATA[We&#8217;ve gotten to the point in our coding where we&#8217;re building the groups of stickies; what the user will experience is being able to drag stickies in attached groups across a surface. When a sticky drops on another, it joins that group. When a sticky drops on disconnected stickies, thereby connecting them, it forms a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=163&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve gotten to the point in our coding where we&#8217;re building the groups of stickies; what the user will experience is being able to drag stickies in attached groups across a surface. When a sticky drops on another, it joins that group. When a sticky drops on disconnected stickies, thereby connecting them, it forms a new group out of all that are touching. Dragging any sticky in a group will move the entire group at once.</p>
<p>It has been really interesting to see how I did this before, and see how this has evolved into a new approach.</p>
<p>I wrote the original prototype of the stickies project about three years ago. When I began coding, I had the concept of &#8220;a group&#8221; in my mind. This was directly related to how I thought about stickies, which was possibly more like a user than a developer: I was describing the outcome of the behavior &#8212; &#8220;stickies are in groups&#8221; &#8212; and modeling that. After all, that&#8217;s what inspired me to write the application. My approach was very straightforward: each sticky knew everyone in its group, and told them to move when it moved. It recalculated the members of a group at critical moments: on dragDrop, onDelete, onResize, as each of those events could directly affect which stickies were touching.</p>
<p>It did this by finding its <em>intersects</em> (those stickies it was immediately touching) and then it&#8217;s &#8220;<em>recursiveIntersects</em>,&#8221; as I called them: the stickies that each of its intersects were touching. In short, its extended family. I wrote a function called <em>groupOnIntersect</em> that was called whenever a sticky was dropped (or deleted or resized). This method added and removed stickies to their new group by figuring out the current configuration of the stickies on the stage (which we are now referring to as a &#8216;surface&#8217;, see <a href="http://thestickiesproject.wordpress.com/2010/03/04/domain-modeling-for-dummies/">my previous post on naming</a>). When this method completed, the groups were configured. This way when a sticky was dragged it would simply access its group by a group ID number, loop through the group, and set the x and y position of everyone in its group, like so:</p>
<p><span id="more-163"></span></p>
<pre>if( this.isSticky  ){
  for( var i in group ){
    var sticky = group[i];
    if( sticky.isSticky &amp;&amp; sticky != this ){
      sticky.xpos += deltaX;
      sticky.ypos += deltaY;
      $Dom.setXY(sticky.id, [sticky.xpos,sticky.ypos]);
    }
  }
}</pre>
<p>This worked and was a valid approach to the problem of moving stickies around, but it generated a lot of long function definitions. I ended up with code to go through all the states that I could envision the stickies being in, in order, and writing code for each one. This approach led to a lot of conditional checks, for example:</p>
<pre>var len = this.intersects.length;
if( len == 0 ){
   /* intersects w/nobody, needs to have own new group */
   ... do stuff
} else if( len == 1 ){
   /* intersected w/only one other element so add to its group */
} else if( len &gt; 1 ){
   /* intersected w/more than one element */
}</pre>
<p>While code in this style can work just fine, it is not very flexible and it doesn&#8217;t have clear abstractions. It is also fragile: because it relies on a number of diverse condition-checks, there is always the possibility for leaving one out, having duplication, inadvertently creating a bug, or having trouble scaling into new conditions. Another side-effect of code like this is that it can get physically long, which makes it hard to read on the page. So there is a lot of visual scanning, looking for where this &#8220;if&#8221; started, and what &#8220;else&#8221; we are inside. When scanning the code this way, it is harder to see the abstractions and pull them out.</p>
<p>Anyway, I&#8217;ve come a long way since then, so it was exciting to revisit this problem and look at different types of solutions for grouping and moving the stickies. Corey has more experience applying patterns and abstractions, and he is also removed from the problem, so we were able to look at it together with fresh eyes. We talked through three different ways: two based on some standard design patterns and one a combination of the two. We decided to start with an implementation of the <a href="http://en.wikipedia.org/wiki/Visitor_pattern">Visitor Pattern</a>. As a note, it was great to talk through them all on the whiteboard: rather than approaching them as dry examples in a book, we literally acted them out in the living room, understanding how they could work in the context of the stickies. I recommend story-telling and whiteboarding for these types of design discussions.</p>
<p>So, the current implementation is as follows: when a sticky begins to move, as triggered by the jQuery drag event, it will access or create an object that we are calling a MovingVisitor (MV). This object is responsible for getting the collection of neighbors (what I called <em>intersects</em> in the first iteration) from the sticky, and then telling each of those (that it hasn&#8217;t visited before) to move (and by what deltaX and deltaY). It continues making visits until all of the stickies have been visited. As you can see, this approach obliterates the need for the concept of <em>recursiveInterects</em> entirely! The MV takes care of traversing the set of stickies, thereby simplifying our calculations.</p>
<p>Here is an extraction of the code as it is being developed, test-first, in the JavaScript specs:</p>
<pre>// Sticky
sticky = {}
sticky.youAreBeingDragged = function(dx, dy, movingVisitor) {
     if(!movingVisitor) {
         movingVisitor = createMovingVisitor();
     }
     movingVisitor.moveMyNeighbors(dx,dy, sticky);
};
sticky.getNeighbors = function() {
     return neighborLookup(sticky);
};

// MovingVisitor
 var movingVisitor = {};
 movingVisitor.moveMyNeighbors = function(dx,dy,sticky){
    $(sticky.getNeighbors()).each(function() {
         this.youAreBeingDragged(dx,dy, movingVisitor);
    }
  );
};
</pre>
<p>The code does not yet do a few critical things:</p>
<ol>
<li>Track the stickies who have already been visited</li>
<li>Be explicit about how the neighbors are calculated (neighborLookup)</li>
</ol>
<p>These things will come next, and then this will be wired up and moved from the spec files into the JavaScript objects themselves. But it is a great example of leveraging an existing pattern and having clean abstractions. One of the benefits that I see from applying the pattern is that the sticky itself does not have to worry about doing a large overhead calculation to determine its whole extended family; it just does its thing (move), and passes on this information to someone else (the visitor). It is then the job of the visitor to tell the others. They each have their own jobs, so we have shorter code with more clearly defined roles, and tasks specific to each actor in the story.</p>
<p>The most exciting thing I am getting from this, beyond the code-benefits from this approach, is an interesting insight into the procedural mind-set and a more object-oriented or abstract mindset. Looking at my original approach, I can see how logical it was. This is how we as humans complete tasks: I am going to wash the dishes, then I am going to dry them, followed by putting them on the shelves, and if there are too many, I will put them on another shelf, at which point I will get one out to eat dinner, etc. Yet at the same time, adapting that step-by-step mindset to writing code is not the cleanest translation, though it may seem the most direct and familiar when you are starting out. It is also interesting that some applications, like Flash, offer both a timeline and an editor w/a scripting language, to accommodate different styles of thinking (though of course you can go step-by-step in an editor, it is just more clearly represented that that is what you are doing in a timeline).</p>
<p>What is required is a kind of mental transliteration: from the procedural way of understanding tasks to a more abstracted way of sending messages between objects.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/163/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=163&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/04/06/moving-patterns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a76239db5edcb9923d04687bda88cf27?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sarahggray</media:title>
		</media:content>
	</item>
		<item>
		<title>Some thoughts on JavaScript</title>
		<link>http://thestickiesproject.wordpress.com/2010/03/31/some-thoughts-on-javascript/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/03/31/some-thoughts-on-javascript/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 15:08:24 +0000</pubDate>
		<dc:creator>coreyhaines</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=145</guid>
		<description><![CDATA[As I&#8217;ve been learning how to test JavaScript, moving from a test-first to a test-driven approach, I&#8217;ve started to extract some guidelines for my designs. The majority of them come from listening to my tests: when I feel pain in testing something, I look to see what that is telling me about my design. I&#8217;ve [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=145&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve been learning how to test JavaScript, moving from a test-first to a test-driven approach, I&#8217;ve started to extract some guidelines for my designs. The majority of them come from listening to my tests: when I feel pain in testing something, I look to see what that is telling me about my design. I&#8217;ve a few definite ideas forming about some differences in the techniques I use when I&#8217;m testing JavaScript, versus when I&#8217;m testing Ruby or C#/Java. They aren&#8217;t fully formed, yet, but this blog post outlines a few of them.</p>
<h2>Get away from the DOM as soon as possible</h2>
<p>Even with great tools like jQuery, interacting with the browser blows big time. So, build a very thin layer at the entry points to your system, detach yourself from the actual DOM by creating JavaScript object wrappers and manipulate those. This has a lot of benefits, including the usual ones gained from isolation. A lot of times, I hear people talk about JavaScript being all UI/view code. In the stickies project, we are putting the majority of our system in JavaScript, using the browser as an application platform. This means that we have view code and domain logic all running in there. So, as with any architecture, you should be isolating the UI and just testing the innards.</p>
<p>So, I have a general rule, only a small set of functions are allowed to pass a string into the root jQuery selector, a la $(&lt;string&gt;), the rest of the functions, if they access the DOM at all, must use a context-based find, such as $(element).find(&lt;string&gt;). This keeps the code ignorant of any unnecessary structural details. Most of the these functions that work on the DOM would be highly encapsulated inside JavaScript objects.</p>
<p>Side story: When I was first learning about test-first programming, I had to build a user interface for the automation tool I was writing. I was pairing with Bob Koss at the time, and I had come to work in the morning after struggling all night with the idea of writing tests for the user interface. I asked him about it, and he reinforced the rule that most people believe, but few people truly do: there should be no logic at all in your user interface. That is, the layer directly behind the UI should be receiving events, grabbing the data and sending it to the underlying logic components. I&#8217;ve been doing it religiously ever since. When you start moving heavily from test-first to test-driven, you really start to see that you can&#8217;t do anything but isolate the user interface. After all, when your executable examples are treated as a client of your system, your UI will just be the second client, heavily relying on a well-defined api.<br />
<span id="more-145"></span></p>
<h2>Object creation is cheap</h2>
<p>In the stickies project, a sticky is represented on the screen by a div. Plugins, such as jQuery UI, interact with our system via the DOM, not via our JavaScript objects. So, why not have the div be the canonical &#8216;sticky&#8217; object, spinning up JavaScript-based &#8216;stickies&#8217; whenever we need them. Create a builder function that takes a div and returns a JavaScript object. However, we don&#8217;t persist these JavaScript objects, they are built on an as needed basis, generally due to a stimulus from a user event, then thrown away when we are done reacting to the event. This also allows us to easily test our functionality by passing in dummy objects that we create in our tests. Yeah, we could use jQuery to spin up some dummy DOM elements, but then you have a lot of unnecessary cruft around.</p>
<h2>Test doubles are free</h2>
<p>One beauty of JavaScript&#8217;s prototype-based nature, as opposed to being class-based, is that the concept of &#8216;type&#8217; really frees itself from the usual tight-coupling with &#8216;class&#8217; that most people think of. A JavaScript object is this: {}. That&#8217;s it. Nothing more than that. What type is it? Well, no real type, yet. Want to change the type of it? Add some behaviors, either by mixing in a new prototype or just add the individual behaviors, yourself. Using jQuery makes this very easy, as it has an extend function, which you can use to easily mix in behaviors. This allows you to very easily evolve the type of an object as it moves through it&#8217;s lifetime.</p>
<p>What does this mean for test doubles? Well, you don&#8217;t need anything other than {} to create yourself a test double. Need to stub out a behavior?</p>
<pre>function functionUnderTest(collaborator) {</pre>
<pre>  return 2 + collaborator.foo('hello');</pre>
<pre>}</pre>
<p>Do something like</p>
<pre>var double = {};</pre>
<pre>double.foo = function() { return 5; }</pre>
<pre>functionUnderTest(double);</pre>
<p>Because functions in JavaScript are closures, you can even do something like:</p>
<pre>var double, returnValue;</pre>
<pre>returnValue = 5;</pre>
<pre>double = {};</pre>
<pre>double.foo = function() { return returnValue; }</pre>
<pre>functionUnderTest(double);</pre>
<p>Want to capture the arguments? That&#8217;s easy, too:</p>
<pre>var double, __args_stubbedFunction;</pre>
<pre>__args_stubbedFunction = 5;</pre>
<pre>double = {};</pre>
<pre>double.foo = function() { __args_stubbedFunction = arguments; }</pre>
<pre>functionUnderTest(double);</pre>
<p>I&#8217;ll leave it as an exercise to the reader how to both capture the arguments and return a value. :)</p>
<p>As I&#8217;ve been spinning my own doubles, I&#8217;m starting to notice a few patterns begging to be extracted. Stubbing a function with a given return value and collecting the arguments given is a common task. It is the most common activity that I do. I occasionally do it on existing objects, but most of the time it is on doubles that I&#8217;ve spun up to pass in. I&#8217;ve allowed the duplication to persist for a while, trying different techniques, but I&#8217;ve pretty much settled on the one. This means that it is time to extract it. I don&#8217;t know whether they will come out into a cohesive set that could be called a doubling framework, or just stay a set of functions that I reuse. I&#8217;ll definitely put it out on github, though.</p>
<p>There are other things I&#8217;ve learned, but I want to end this and get it posted. We are doing our best to post regularly, so you can expect more thoughts on JavaScript while we continue to build the stickies project. We are close to initial feature complete, so a beta release is on the horizon. No specific date, yet, but it will be soon.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/145/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=145&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/03/31/some-thoughts-on-javascript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d7807bb66e1a0c68c73ab2daaa77d8f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">coreyhaines</media:title>
		</media:content>
	</item>
		<item>
		<title>Oldies But Goodies: Vendor Everything</title>
		<link>http://thestickiesproject.wordpress.com/2010/03/12/oldies-but-goodies-vendor-everything/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/03/12/oldies-but-goodies-vendor-everything/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 11:17:40 +0000</pubDate>
		<dc:creator>sarahggray</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Setup]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=127</guid>
		<description><![CDATA[I thought I&#8217;d take a moment to reprise err the blog&#8216;s classic, Vendor Everything. Why? Because I sat down to work tonight and ran into some missing gem errors: specifically jslint_on_rails. Corey and I have been pairing on his computer recently, so apparently we&#8217;d had jslint_on_rails installed locally but not vendored into our project. On [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=127&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I thought I&#8217;d take a moment to reprise <a href="http://errtheblog.com/">err the blog</a>&#8216;s classic,  <a href="http://errtheblog.com/posts/50-vendor-everything">Vendor Everything</a>.  Why? Because I sat down to work tonight and ran into some missing gem errors: specifically <a href="http://github.com/psionides/jslint_on_rails">jslint_on_rails</a>. Corey and I have been pairing on his computer recently, so apparently we&#8217;d had jslint_on_rails installed locally  but not vendored into our project. On my laptop, boom. Missing file errors. These are easy things to overlook, and we&#8217;re still using config.gem &#8212; having not yet made the move to <a href="http://github.com/wycats/bundler">Bundler</a> and its strict <em>disable_system_gems</em> setting.   Bundler wouldn&#8217;t have let that slip. It also turned out that the version of Cucumber we had in vendor/gems was missing some directories: probably an aborted install. Until it was asked to run against that version, we didn&#8217;t see the errors.  Right now we&#8217;re all vendored up. </p>
<p>At some point soon we&#8217;ll be moving to Bundler, and at that point there will be a treat of a blog post about it :) Right now, <a href="http://skitch.com/leinweber/n218g/gem-bundler">this is how I feel about Bundler</a>: optimistic, excited and cautious, all from personal experience.</p>
<p>While I&#8217;m on this house-cleaning topic, for those of you who <em>do</em> vendor jslint_on_rails, be sure to specify it&#8217;s :lib setting, otherwise it looks for a non-existent file called <code>jslint_on_rails.rb</code>, when it really wants <code>jslint.rb</code>: </p>
<p><code>config.gem 'jslint_on_rails', :lib =&gt; "jslint"  </code></p>
<p>For those of you who *are* using Bundler that would translate to: </p>
<p><code>gem 'jslint_on_rails', :require_as =&gt; "jslint"  </code></p>
<p>And for those of you who are wondering what&#8217;s up with JSLint, it is a &#8220;a JavaScript program that looks for problems in JavaScript programs&#8221;. JSLint comes with a warning, though: as it states flat out, <a href="http://jslint.com/">JSLint will hurt your feelings</a>!</p>
<p><span id="more-127"></span><br />
Why? Because the easy, loosy-goosy JavaScript that you&#8217;ve most likely learned to write over the years is actually a hotbed of errors waiting to happen. It&#8217;s like one of those microscopic views of an everyday surface, such as, oh, your keyboard: everything looks OK from normal distance, but then there&#8217;s all these little creepy things crawling around. </p>
<p>JSLint is a script written by <a href="http://www.crockford.com/">Douglas Crockford</a>, who is awesome and is the best source to both boggle and clear your mind about JavaScript. JSLint allows you to check your JavaScripts against a number of sloppy coding practices that are allowed by JavaScript but that can cause problems in your application or when your code is minified. Some of the things we are allowed to do in JavaScript but encouraged against are: leaving semicolons off (can cause trouble when your scripts are minified as line breaks won&#8217;t be read correctly); creating non-standard markup (such as UPPERCASE tags); using eval, which can leave your code open to being exploited by user input; failing to declare your variables before using them (as failure to initialize a JS var creates it in the global namespace, where it can easily and mysteriously cause namespace collisions); and more. </p>
<p>To use jslint_on_rails, you set up a config file, config/jslint.yml, where you declare your tolerance for a set of conditions. You can also set paths where JSLint should look, so it checks your own JavaScripts and not, for instance, JQuery or the entire YUI library.  </p>
<p>Going through the jslint.yml config can spark great discussion, so be warned that it&#8217;s more fun to do it with someone else. It&#8217;s like one of those quick-dating sites where you can learn more about a person than you really wanted to&#8230; (&#8220;You voted for George Bush?? In 2004?&#8221; ..or, the web developer equivalent.. &#8220;You use UPPERCASE attrs in your html??&#8221;) Of course, other things may horrify you than horrify me, but that&#8217;s the fun of it.  Here&#8217;s a glimpse of our config file, to see some of the options.</p>
<p><code>adsafe:   false     # true if ADsafe rules should be enforced. See http://www.ADsafe.org/<br />
bitwise:  true      # true if bitwise operators should not be allowed<br />
newcap:   true      # true if Initial Caps must be used with constructor functions<br />
eqeqeq:   true      # true if === should be required (for ALL equality comparisons)<br />
immed:    true      # true if immediate function invocations must be wrapped in parens<br />
nomen:    true      # true if initial or trailing underscore in identifiers should be forbidden<br />
onevar:   false     # true if only one var statement per function should be allowed<br />
plusplus: true      # true if ++ and -- should not be allowed<br />
regexp:   false     # true if . and [^...] should not be allowed in RegExp literals<br />
safe:     false     # true if the safe subset rules are enforced (used by ADsafe)<br />
strict:   false     # true if the ES5 "use strict"; pragma is required<br />
undef:    true      # true if variables must be declared before used<br />
white:    false     # true if strict whitespace rules apply (see also 'indent' option)<br />
 </code></p>
<p>Anyway, it&#8217;s simple to set up and then you just run: </p>
<p><code>rake jslint</code></p>
<p>(We made that part of the default rake task, so we don&#8217;t have to think about it). And the JavaScripts you included in your paths are checked. </p>
<p>JSLint is something I would recommend working with when you&#8217;re starting a project as opposed to when you already have a ton of JavaScripts. It&#8217;s like a strict teacher who can keep you on the straight and narrow, and depending on how far you&#8217;ve strayed it may be too hard to start using it when you&#8217;re already knee deep in undeclared variables.  Otoh, that may be when you need it most.  More than anything though, <a href="http://www.jslint.com/lint.html">wander over to their site and read about it</a>: it&#8217;s a great read and gives a lot of insight into JavaScript and coding practices. </p>
<p>So tonight&#8217;s post turns out to be about strictness: vendoring gems, checking javascripts.  Luckily, tomorrow is Friday so all bets are off and we can forget our semicolons at the bar :)</p>
<p>Happy coding.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/127/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=127&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/03/12/oldies-but-goodies-vendor-everything/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a76239db5edcb9923d04687bda88cf27?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sarahggray</media:title>
		</media:content>
	</item>
		<item>
		<title>Claimed and Unclaimed Surfaces</title>
		<link>http://thestickiesproject.wordpress.com/2010/03/09/claimed-and-unclaimed-surfaces/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/03/09/claimed-and-unclaimed-surfaces/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 15:40:36 +0000</pubDate>
		<dc:creator>coreyhaines</dc:creator>
				<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=100</guid>
		<description><![CDATA[One of the stories that we had for the stickies project was to allow people to create surfaces without logging in: Feature: Unclaimed Surfaces In order to easily see whether the stickies project has functionality I want to use As a visitor to the site I want to create a surface and stickies without registering [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=100&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>One of the stories that we had for the stickies project was to allow people to create surfaces without logging in:</p>
<pre>
Feature: Unclaimed Surfaces
  In order to easily see whether the stickies project has functionality I want to use
  As a visitor to the site
  I want to create a surface and stickies without registering
</pre>
<p>We began calling this type of surface &#8216;unclaimed.&#8217; You can try out the functionality immediately, see what it is all about, then decide whether you want to register for the site. Naturally, what you see is going to make you want to register. What happens to this surface, though, when you register? It would be nice if you could associate it with your user. This led to the idea of &#8220;Claimed Surfaces:&#8221;</p>
<pre>
Feature: Claimed Surfaces
  In order to keep track of surfaces that I have created
  As a registered user
  I want to claim a surface and associate it to my account
</pre>
<p>The idea of &#8216;claimed&#8217; and &#8216;unclaimed&#8217; are different from public and private, though. From a resource perspective, the URIs would be different:</p>
<p>Unclaimed: /surfaces/:unclaimed-surface-name<br />
Claimed: users/:user_id/surfaces/:claimed-surface-name</p>
<p><strong>Note:</strong> We have talked about public and private surfaces, but those are later stories that change the nature of claimed surfaces. For now, there is no authorization functionality implemented. This also means that you can edit other users&#8217; claimed surfaces (until we implement authorization stories).</p>
<p><span id="more-100"></span></p>
<p>Previous cards related to editing surfaces had created the functionality related to &#8216;unclaimed&#8217; surfaces. The question was how best to add the functionality for users to have surfaces associated with them. We wanted to do it as simply as possible. When we started the project, we decided that the idea of a user had no intrinsic value on its own. Instead, we wanted to wait to see what value-creating feature would cause us to need the concept. And, here we are, &#8216;claimed surfaces.&#8217; We discussed other options, including a simple naming system, where you could create a group of surfaces that would stand in for user. In the end, looking at the next stories coming (spoiler: public and private surfaces), we decided that adding users made sense here. So, how best to add this functionality? Could we add claimed surfaces without making many changes to our system? As it turns out, it took very little effort at all to add this functionality while keeping the unclaimed surfaces working.</p>
<p>As it stood, we had cucumber features for unclaimed surfaces.<br />
Note: in the interest of brevity, I&#8217;m only going to show the basic cucumber scenarios.</p>
<pre>
Feature: Creating an unclaimed surface

  Scenario: Create surface from new surface page
    Given I am on the new surface page
    When I submit the surface name "foo"
    Then I should be on the surface page for "foo"
</pre>
<p>And it was passing. I wanted to add something like:</p>
<pre>
Feature: Creating a claimed surface

  Scenario: Create surface from new surface page
    Given I am logged in as user "coreyhaines@example.com"
    And I am on the new surface page
    When I submit the surface name "foo"
    Then I should be on the surface page for "foo" belonging to "coreyhaines@example.com"
</pre>
<p>The first step we did was to implement user registration/login/etc. Well, to say we &#8216;implemented&#8217; it would be a bit of overkill. After all, we are in the rails ecosystem. We downloaded <a href="http://github.com/thoughtbot/clearance">Clearance</a>, by the prolific guys at <a href="http://thoughtbot.com/">thoughtbot</a> and went through the quick and easy instructions to implement a ready-made user-authentication system. In the end, I think we spent about 4 pomodoros this. Why so long? Well, we initially had used an older version, found they had a dependency on Factory-Girl (go figure), so we had to install that. The Clearance-generated cucumber features for user and session functionality were still failing. We stumbled a bit creating our own factories, as they hadn&#8217;t been brought over when we generated. After a pomodoro, or two, we decided to look again at the documentation and realized that there was a newer version. We scrapped what we had, installed the newer version, generated it, and voila, everything worked great. So, we now had a working user authentication system, which also included registration (with confirmation emails) and forgotten password. Yeah, Clearance is pretty awesome.</p>
<p>But, this was just a precursor to getting our own cucumber feature passing. Let&#8217;s start going through the &#8216;change the message or make it pass&#8217; loop to get it implemented. First pass, we get that the &#8220;I am logged in as user&#8230;&#8221; step isn&#8217;t defined. Well, looking at the Clearance-generated scenarios, we see that we can use the following steps:</p>
<pre>
Given I am signed up and confirmed as "coreyhaines@example.com/password"
And I sign in as "coreyhaines@example.com"
</pre>
<p>to create a user and login. The feature changes to incorporate this.</p>
<pre>
Feature: Creating a claimed surface

  Scenario: Create surface from new surface page
    Given I am signed up and confirmed as "coreyhaines@example.com/password"
    And I sign in as "coreyhaines@example.com"
    And I am on the new surface page
    When I submit the surface name "foo"
    Then I should be on the surface page for "foo" belonging to "coreyhaines@example.com"
</pre>
<p>Now, the creation of the surface uses the same steps as the unclaimed surface scenario, so we don&#8217;t have any worries there. In fact, I&#8217;m happy that we can reuse those, as we want the user experience to be the same whether you are logged in or not. The rub is that last step:</p>
<pre>
Then I should be on the surface page for "foo" belonging to "coreyhaines@example.com"
</pre>
<p>When we run cucumber, we find that there is no path defined for this step. We have a path for an unclaimed surface, but nothing for specifying it is claimed. At this point, we notice that there is a bit of a language mismatch. From a rails perspective, we are talking about surfaces belonging to a user, but we keep bouncing between the terms &#8216;belonging to&#8217; and &#8216;claimed.&#8217; Sarah talked about <a href="http://thestickiesproject.wordpress.com/2010/03/04/domain-modeling-for-dummies/">the importance of keeping the metaphor</a> going through our language (ubiquitous language as James Martin points out in the comments to her post), so let&#8217;s change this step:</p>
<pre>
Then I should be on the surface page for "foo" claimed by "coreyhaines@example.com"
</pre>
<p>Changing the term didn&#8217;t get us any closer to having a path for it, though. Let&#8217;s go look at implementing it.</p>
<pre>
when /the surface page for "([^"]*)" claimed by "([^"]*)"$/
  surface = Surface.find_by_name($1)
  user = User.find_by_email($2)
  user_surface_path(user,surface)
</pre>
<p>When I run this, I find that I don&#8217;t have a user_surface_path. Of course I don&#8217;t, because the routes only have</p>
<pre>map.resources :surfaces, :has_many =&gt; :stickies</pre>
<p>This provides me with all the basic xxx_surface routes, but I want to also support having routes that include a user. Reading through the rails documentation a bit (routing is always one of those places that I stumble upon new capabilities), I find that I can add some options:</p>
<pre>
map.resources :surfaces, :has_many =&gt; :stickies,
              :path_prefix =&gt; '/users/:user_id', :name_prefix =&gt; 'user_'
</pre>
<p>I want to support both, so what happens if I just put add the above line, keeping the basic map.resources :surfaces above it? Will I get two sets of routes? Spoiler Alert: Yes, it works. So, if I do a rake routes, I&#8217;ll see both the basic surface routes, as well as ones related to xxx_user_surface routes. Very sweet! Let&#8217;s run cucumber and see where we stand. Ah, the functionality seems to work, but the path we are on is wrong:</p>
<pre>
expected: "/users/1/surfaces/foo",
got: "/surfaces/foo" (using ==)
</pre>
<p>This makes sense, we don&#8217;t have anything that would cause the controller to route us to different URL. Now, we are using resource_controller, so I actually think this should be given to us for &#8220;free.&#8221; Let&#8217;s see if what it would take. Well, first off, we need the new surface form to send to the correct url:</p>
<p>unclaimed: POST /surfaces<br />
claimed: POST /users/:user_id/surfaces</p>
<p>This is a matter of using the Clearance helpers. Let&#8217;s change from</p>
<pre>
-semantic_form_for surface do |form|
  -form.inputs do
    = form.input :name
    = form.buttons
</pre>
<p>to</p>
<pre>
-action = signed_in? ? user_surfaces_path(current_user) : surfaces_path
-semantic_form_for surface, :url =&gt; action do |form|
  -form.inputs do
    = form.input :name
    = form.buttons
</pre>
<p>This should cause the form to post to the desired url depending on whether we are signed in.</p>
<p>When we run this, we still don&#8217;t get routed to the correct url (still going to /surfaces/foo). This is because the surfaces controller doesn&#8217;t realize that we are trying to scope our surface to a user. Luckily, we are using <a href="http://twitter.com/jamesgolick">James Golick</a>&#8216;s most excellent <a href="http://github.com/jamesgolick/resource_controller">resource_controller gem</a> (yes, it really is most excellent). How does this help us? Well, it supports nested controllers. All we have to do is tell the controller that surfaces can belong to users by adding the following line to the surfaces controller:</p>
<pre>belongs_to :user</pre>
<p>Yup, that&#8217;s all it takes for the controller to become aware of a relationship between the user and the surface. When we run our cucumber feature, though, we get an exception at an unexpected point in the scenario:</p>
<pre>
Given I am signed up and confirmed as "person@example.com/password"
And I sign in as "person@example.com/password"
  undefined method `surfaces' for # (NoMethodError)
  (eval):2:in `click_button'
  ./features/step_definitions/webrat_steps.rb:20:in `/^(?:|I )press "([^\"]*)"$/'
  features/create_surfaces_logged_in.feature:4:in `And I sign in as "person@example.com/password"'
</pre>
<p>This makes sense. When we log in, we are going to the index page for surfaces. Resource Controller is trying to set the @surfaces variable to the surfaces scoped to the user we just logged in as (after login, we route to /users/:user_id/surfaces). This is an easy enough fix, let&#8217;s add the relationship to the User model:</p>
<pre>
Given I am signed up and confirmed as "person@example.com/password"
And I sign in as "person@example.com/password"
  undefined method `surfaces' for # (NoMethodError)
  (eval):2:in `click_button'
  ./features/step_definitions/webrat_steps.rb:20:in `/^(?:|I )press "([^\"]*)"$/'
  features/create_surfaces_logged_in.feature:4:in `And I sign in as "person@example.com/password"'
</pre>
<p>Let&#8217;s run our cucumber feature. Wow! It passes. Let&#8217;s run the cucumber feature creating an unclaimed surface. Beautiful! That passes, as well. So, looking back, we added the ability to create a claimed surface by adding effectively 3 lines of code: get the form posting to the correct URL, let Resource Controller know that surfaces can belong to users and let the user model know that it has surfaces. Pretty sweet!</p>
<p>At this point, a question comes up: where are the rspec-level examples? Why didn&#8217;t I write any isolation tests? This is a great question, and an interesting discussion point around the level of examples that are needed to drive out declarative statements for the underlying framework. I don&#8217;t generally write an example for model relationships, relying on some behavior to cause me to write them. In this case, the model relationship was driven by the cucumber scenario. The belongs_to declaration in the surfaces controller sits in the same space for me: I&#8217;m declaring a relationship to the underlying framework, Resource Controller. The last question is the logic in the view, deciding which url to use. I tend not to write view specs, relying on cucumber to tell me if there is something missing. This is logic, though. Shouldn&#8217;t it be tested? There are definite arguments for it. Actually, as we began rippling the concept of claimed surface through the rest of the CRUD operations on surfaces, we found this pattern to appear multiple times, resulting in a very definite need to refactor away the duplication. When refactoring, the tests are there to give us confidence that we haven&#8217;t broken anything. In this case, the cucumber scenarios provide us with that confidence. They do this, because the scenarios were failing until the logic was added. This gives me a sense of security that they will catch any mistakes I make.</p>
<p>As we filled out the rest of the CRUD operations on claimed surfaces, we found that we also needed to add the declaration to the surface model that it belonged to a user. This was</p>
<pre>
class Surface &lt; ActiveRecord::Base
  belongs_to :user
end
</pre>
<p>Adding this line completed the relationship between a surface and a user, and the stickies project now had the concept of &#8216;claimed surfaces.&#8217; Once Clearance was installed, the driving out of the complete claimed surface CRUD took 4 pomodoros: 2 hours. Pretty quick work of what could have been a complicated architectural change.</p>
<p>Just as a base point, the app currently supports user/session functionality, CRUD operations on claimed and unclaimed surfaces, and CRUD operations on stickies assigned to a surface. Here are the code stats (not including javascript or plugins):</p>
<pre>
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |    45 |    36 |       4 |       2 |   0 |    16 |
| Helpers              |     3 |     2 |       0 |       0 |   0 |     0 |
| Models               |    19 |    16 |       3 |       0 |   0 |     0 |
| Libraries            |     0 |     0 |       0 |       0 |   0 |     0 |
| Model specs          |    58 |    51 |       0 |       0 |   0 |     0 |
| View specs           |     0 |     0 |       0 |       0 |   0 |     0 |
| Controller specs     |    95 |    81 |       0 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |   220 |   186 |       7 |       2 |   0 |    91 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 54     Test LOC: 132     Code to Test Ratio: 1:2.4
</pre>
<p><strong>Random Fact:</strong> this blog post was written at around 38000 feet above the atlantic ocean</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/100/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=100&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/03/09/claimed-and-unclaimed-surfaces/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d7807bb66e1a0c68c73ab2daaa77d8f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">coreyhaines</media:title>
		</media:content>
	</item>
		<item>
		<title>Domain Modeling For Dummies</title>
		<link>http://thestickiesproject.wordpress.com/2010/03/04/domain-modeling-for-dummies/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/03/04/domain-modeling-for-dummies/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 15:01:48 +0000</pubDate>
		<dc:creator>sarahggray</dc:creator>
				<category><![CDATA[Process]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=69</guid>
		<description><![CDATA[Domain Modeling, at least to me, sounds complicated. It sounds like something you should have an advanced degree to do, and something that, if you do understand the term at face value, marks you as an Expert. At something. And while there are a lot of valuable domain modeling tools that help developers make useful [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=69&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Domain Modeling, at least to me, sounds complicated.  It sounds like something you should have an advanced degree to do, and something that, if you do understand the term at face value, marks you as an Expert. At something.  And while there are a lot of valuable domain modeling tools that help developers make useful applications, it can be an off-putting term. It took me a while to understand that &#8216;Domain Modeling&#8217; can be boiled down to:</p>
<p><em>&#8220;Explain this little world of yours&#8221; </em></p>
<p>or<br />
<em><br />
&#8220;This thing you&#8217;re describing: What&#8217;s it like? How does it work? What makes it special?&#8221; </em></p>
<p>The first time I wrote the stickies project, I created the following resources: Users, Stickies, Projects.  It was remarkably simple. There was also the concept of Groups (a cluster of related stickies); and a Dock (a place to move those groups out of the way). Beyond that, though &#8212; go get a hamburger, we&#8217;re done. We&#8217;ve got users, the people using the application; stickies, those little sticky notes; and projects, well&#8230;</p>
<p>Wait.</p>
<p><span id="more-69"></span></p>
<p>I&#8217;d chosen &#8220;Project&#8221; without thinking about it too much. Having projects and thinking about new ways to keep track of projects is one of our favorite occupations as web developers (and people) these days. Plus, it&#8217;s a status symbol. Have a lot of projects! Yum, projects. Yum, to-dos.  Yum, airport-bookstore-manage-your-life books.</p>
<p>Yum.</p>
<p>However, had I been on the Domain Modeling ball, I would have seen that when I sat down and stuck stickies to the floor, table, or wall, it had more to do with cataloging a tumbleweed of thoughts and feelings, creating clustered relationships and visualizing a brain dump than doing project related tasks such as creating milestones, to-dos and deliverables.  Well, I actually did know that, but I would have also said&#8230;</p>
<p><em>Hey, wait! </em>While there&#8217;s nothing stopping a user from using stickies to flesh out a particular, extant project or to start a new one &#8212; hell, the stickies project even hooks into the Basecamp API because somewhere on your living room rug you might find the seed of a project and want to manage it &#8212; project management is not where the impulse to stick originates.</p>
<p>What I had been calling a Project was really&#8230; a big, open, preferably flat, preferably indoor, often private, always dry&#8230; surface.</p>
<p>And so we changed &#8220;Projects&#8221; to &#8220;Surfaces&#8221;.</p>
<p>Big deal, right? While it may seem like a minor name change that affects a few files, getting the domain name right can have a small, then bigger, then biggest-of-all effect on the design and world of your application. It&#8217;s similar to character development as a writer or a director: observe and listen to your subject until you find their unique twitch, their particular motivation. Finding this can drive their purpose, save them from cliche, and make them real to the audience.</p>
<p>While steering clear of cliche is an ongoing task, clarifying the &#8220;surfaces&#8221; domain has led us to some organic ideas for the design. Ideas that we hope will enrich the application. Getting closer to the &#8220;real world&#8221; of sticking will allow us to create a more specific &#8220;web world&#8221; of stickies.</p>
<p>This experience has helped me to recast &#8220;Domain Modeling&#8221; in my mind to simpler things, such as listening to your environment, paying attention to what you or your clients are actually doing, and steering clear of the default classification buckets in our minds.  Use all the tools you have handy and feel comfortable with, but remember that getting the domain right starts before the tools come out: it&#8217;s more of a paying attention kind of thing.</p>
<p>In the theater, actors are encouraged not act out an emotion, but to try to achieve a specific objective. Who wants to watch someone &#8220;act sad&#8221;? A similar directive for us as application developers would be to look out for general types of things we think we understand (such as &#8220;projects&#8221;) and instead focus on the little, simple, tasks we are actually trying to represent.  You might find that everything changes shape.</p>
<p>Find the twitch: that unique and domain-centric something that needs to be expressed, and then delve deep.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/69/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=69&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/03/04/domain-modeling-for-dummies/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a76239db5edcb9923d04687bda88cf27?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sarahggray</media:title>
		</media:content>
	</item>
		<item>
		<title>Planning the Surfaces!</title>
		<link>http://thestickiesproject.wordpress.com/2010/01/07/planning-a-new-feature/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/01/07/planning-a-new-feature/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 21:48:38 +0000</pubDate>
		<dc:creator>coreyhaines</dc:creator>
				<category><![CDATA[Process]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=55</guid>
		<description><![CDATA[Note: While I finish the second post in the series for &#8216;listening to the tests,&#8217; here is a post about how Sarah and I planned the next feature: surfaces. So, Sarah and I have sticky notes being added, moved, editing, persisted, etc., and the application is coming along nicely. In fact, we are getting close [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=55&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><em>Note:</em> While I finish the second post in the series for &#8216;listening to the tests,&#8217; here is a post about how Sarah and I planned the next feature: surfaces.</p>
<p>So, Sarah and I have sticky notes being added, moved, editing, persisted, etc., and the application is coming along nicely. In fact, we are getting close to opening up the first public beta. Just having stickies is only good for a single decision, so the two remaining features are surfaces and users. The process we are modeling, as Sarah outlines in the original screencast, is a large surface with stickies moving around. So, using that metaphor, we are adding the concept of &#8216;surfaces,&#8217; separate areas that you can add and manipulate stickies on. We already have a single-surface implementation done, so it is just a matter of having them associated with a specific surface.</p>
<p>We started discussing implementation details, and I brought up a technique that I learned from <a href="http://www.joefiorini.com/">Joe Fiorini</a> a while ago about resource modeling via URI. The basic idea (it can get more complex) is to focus on the URIs and the behaviors related to specific HTTP verbs. I mentioned this to Sarah, so we got out the whiteboard markers and her well-used eraser, and we began mapping both how users would interact with the system and how the application would interact with the backend resources. I didn&#8217;t do it exactly as I learned from Joe, but the slightly looser form I used achieved our goals.</p>
<p><span id="more-55"></span></p>
<p>Here&#8217;s a view of our final board, and I&#8217;ll make some comments on it:</p>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/lh/photo/yyMawfwtRZfBnR__0kCw-g?feat=embedwebsite"><img src="http://lh4.ggpht.com/_dYi-rTxxT2o/S0TxoNSDQZI/AAAAAAAAC-M/UCnauedNNRg/s288/2010-01-05%2008.12.22.jpg" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif;font-size:11px;text-align:right;">From <a href="http://picasaweb.google.com/coreyhaines/TheStickiesProjectBlog?feat=embedwebsite">TheStickiesProjectBlog</a></td>
</tr>
</table>
<p>Side Note: Yes, that is a big-ass, framed whiteboard on Sarah&#8217;s living room wall. Tell me that does not equal AWESOME!</p>
<p>One of the first things we talked about was</p>
<p><code>GET /surfaces/:name(.format)</code></p>
<p>as the canonical accessor for a surface and its stickies. When accessed via html, it would display the surface layout + the necessary javascript calls to place the stickies on the surface. One interesting feature that I really pushed for, inspired by http://tomatoi.st (the pomodor timer that we use while coding), is the idea that doing</p>
<p><code>GET on /surfaces/:non-existing-surface-name</code></p>
<p>would create that surface for you. I like the idea of just being able to create a new one as simply as possible. Sarah was worried about having too many of them just floating around, so we decided on having a cleanup job that would remove any surface that had not seen activity for an hour. I do worry about the possibility of a DOS attack, but, if we get to that point, then we can look at throttling techniques, maybe IP-based, as a simple workaround. I&#8217;d hate to think someone would do that to us, though. :) This also means that sharing a surface would be as simple as sending the URL.</p>
<p>I&#8217;ll write more later about some of the other design decisions we made from this, but I wanted to get this up, especially to talk about the first interesting feature we are planning.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/55/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=55&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/01/07/planning-a-new-feature/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d7807bb66e1a0c68c73ab2daaa77d8f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">coreyhaines</media:title>
		</media:content>

		<media:content url="http://lh4.ggpht.com/_dYi-rTxxT2o/S0TxoNSDQZI/AAAAAAAAC-M/UCnauedNNRg/s288/2010-01-05%2008.12.22.jpg" medium="image" />
	</item>
		<item>
		<title>Listening to Tests &#8211; Part 1</title>
		<link>http://thestickiesproject.wordpress.com/2010/01/04/listening-to-tests-part-1/</link>
		<comments>http://thestickiesproject.wordpress.com/2010/01/04/listening-to-tests-part-1/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 15:07:43 +0000</pubDate>
		<dc:creator>coreyhaines</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=41</guid>
		<description><![CDATA[Editing a Sticky&#8217;s Contents One of the first things that we&#8217;ll need to do is be able to edit the content of a sticky. We decided on using the jEditable component, as it seemed the easiest to integrate, and it was really high up on the google page. In this series of blog posts, I&#8217;m [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=41&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h3>Editing a Sticky&#8217;s Contents</h3>
<p>One of the first things that we&#8217;ll need to do is be able to edit the content of a sticky. We decided on using the <a href="http://plugins.jquery.com/project/jeditable">jEditable component</a>, as it seemed the easiest to integrate, and it was really high up on the google page. In this series of blog posts, I&#8217;m going to take a look at how we went about not only integrating the component, but also how we went about improving our design through shifting to a TDD approach and listening to what the tests were saying as they guided and influenced our design. Along the way, I learned some valuable lessons about bringing old habits from other language styles over without thinking about them. That comes later, though.</p>
<p><span id="more-41"></span></p>
<p><a href="http://gist.github.com/268132">Link to the gist for all the code samples</a></p>
<h3>Do I even know the javascripts?</h3>
<p>It has been a long time since I wrote serious JavaScript; I think the last time I did what I would call an actual &#8216;JavaScript application&#8217; was in 2002, or so. Sure, I&#8217;ve written a few things here and there. In fact, at the startup I worked at, I wrote a couple in-browser things that I was proud of at the time (looking back, naturally, I can see the parts that I&#8217;m not so proud of). But, all-in-all, most of what I do has been pretty non-dynamic. Back in 2002, I&#8217;m pretty sure I was only seeing the beginnings of JavaScript frameworks. There were some libraries coming out, but I seem to remember them being very focused on hiding the differences between DOM implementations. I wrote a couple things back then, but nothing incredibly crazy; I remember writing a client-side form validation library that was pretty damn sweet for the time. :)</p>
<p>So, both my JavaScript and JavaScript testing skills were a bit rusty. I&#8217;ve used this as an example before when talking about using the term &#8216;pragmatic&#8217; to really be a cover over lack of skill: I never tested my JavaScript, not because I was pragmatic about testing, but because I flat-out didn&#8217;t have the skills needed to do it effectively. This was one of the reasons I was so excited to work on The Stickies Project: as I outlined initially, this application is going to be almost entirely JavaScript, so I will have a great opportunity to patch what I consider a significant hole in my skillset. After setting up BlueRidge, I began writing some examples for my code, but I found that, while I was writing tests, I wasn&#8217;t really doing TDD; I was writing some functions, trying to figure out how to get the desired behavior, while writing tests alongside them.</p>
<h3>Figuring out the component</h3>
<p>At first, I was just trying to get things working, figuring out how the component worked, so I wrote the following spike code:</p>
<p><pre class="brush: jscript; auto-links: false; gutter: false; wrap-lines: false;">
function update_sticky_text(value, settings) {
  var stickie = $(this);
  console.log(&quot;value &quot; + value + &quot; settings &quot; + settings + &quot; this &quot; ));
  var url = sticky_update_url_for(stickie);
  console.log(&quot;url &quot; + url );
  // jQuery.post(url, {content : value, method : 'put'});
  return value;
}

function sticky_update_url_for(sticky_div){
  return sticky_div.attr('data-update-url');
}
</pre></p>
<p><pre class="brush: jscript; auto-links: false; gutter: false; wrap-lines: false;">
Screw.Unit(function(){
  describe(&quot;getting information from sticky div&quot;, function(){
    it(&quot;can get the update url&quot;, function(){
      sticky_div = $(&quot;#sticky_23&quot;);
      sticky_div.attr('data-update-url', &quot;/stickies/25&quot;);
      expect(sticky_update_url_for(sticky_div)).to(equal, &quot;/stickies/25&quot;);
    });
  });
});
</pre></p>
<h3>Hmmm&#8230; Reflection</h3>
<p>Yeah, looks pretty bad. But, it was enough to learn the jEditable component, so I was pretty happy. However, I definitely had a few major problems with the code:</p>
<ol>
<li>global functions</li>
<li>no sense of cohesion other than being in the same file for these two functions, even though the dependency was there</li>
<li>#sticky_update_url_for was not used anywhere else, only by #update_sticky_text</li>
<li>no test coverage for the #update_sticky_text function.</li>
</ol>
<h3>Learning from the spike</h3>
<p>Now that I had finished the spike, it was time to actually write some code. I had identified some design problems with the resulting code, and I was curious to see how those problems would be resolved. Before moving on, though, we took a bit of time to learn some more about ScrewUnit. I had learned the expect(&#8230;).to(&#8230;) syntax, but wasn&#8217;t sure what the setup was for checking if methods are called. I&#8217;m tend to do collaboration-style tests, so it is important for me to be able to set expectations on method calls. I wasn&#8217;t ready to jump into using a mocking framework, so I decided to stick with the simplest way I knew how: replace the method with your own that sets a flag if it was called. Something like this should suffice:</p>
<p><pre class="brush: jscript; auto-links: false; gutter: false; wrap-lines: false;">
Screw.Matchers['expect_called'] = function(obj, func_name, block){
  var got_called = false;
  obj[func_name] = function(x) { got_called = true; }
  block();
  this.expect_true(got_called);
};


// used like this
it(&quot;calls #parent_sticky&quot;, function(){
    expect_called(this, 'parent_sticky', function(){
    old_update_sticky_text(&quot;foo&quot;, null);
  });
});
</pre></p>
<p>This is the easiest way to check if something was called, but, of course, it doesn&#8217;t reset the function at the end (I wrote that later), so it isn&#8217;t perfect. But, this allowed me to write isolation-based examples for my functions. With this in hand, I was equiped to write a full set of examples for what was going to be known as #old_update_sticky_text:</p>
<p><pre class="brush: jscript; auto-links: false; gutter: false; wrap-lines: false;">
describe(&quot;#old_update_sticky_text&quot;, function(){
    
    before(function(){
      this.sticky_update_url_for = function(x) { return null; }
      this.parent_sticky = function(x) { return null; }
      this.update_sticky = function(x) { return null; }
    });

    it(&quot;returns the value passed in&quot;, function(){
      var value = old_update_sticky_text(&quot;foo&quot;, null);
      expect(value).to(equal, &quot;foo&quot;);
    });

    it(&quot;calls #parent_sticky&quot;, function(){
      expect_called(this, 'parent_sticky', function(){
        old_update_sticky_text(&quot;foo&quot;, null);
      });
    });

    it(&quot;calls #sticky_update_url_for&quot;, function(){
      expect_called(this, 'sticky_update_url_for', function(){
        old_update_sticky_text(&quot;foo&quot;, null);
      });
    });

    it(&quot;calls #update_sticky&quot;, function(){
      expect_called(this, 'update_sticky', function(){
        old_update_sticky_text(&quot;foo&quot;, null);
      });
    });
});
</pre></p>
<p>So, I was pretty happy that I was able to write isolation tests, but I was still annoyed by the other problems, primarily what I considered to be the big problems of global functions and lack of a sense of cohesion. My experiences have led me to trust in TDD to guide me when I&#8217;m not 100% sure where to go. Let&#8217;s get going. I&#8217;ve comfortable enough with ScrewUnit now, so I thought I would just jump in head-first.</p>
<h3>Let&#8217;s try some TDD</h3>
<p>First example? How about this:</p>
<p><pre class="brush: jscript; auto-links: false; gutter: false; wrap-lines: false;">
require(&quot;spec_helper.js&quot;);
rails_require('tsp');

Screw.Unit(function(){
  describe(&quot;TSP&quot;, function(){
    describe(&quot;#update_sticky_text_handler&quot;, function(){
      it(&quot;returns the value passed in&quot;, function(){
        var value = TSP.update_sticky_text_handler(&quot;new text&quot;, null);
        expect(value).to(equal, &quot;new text&quot;);
      });
    });
  });
});
</pre></p>
<p>It felt somewhat reasonable. This is a handler across all the sticky object editable components, so hanging off a TSP (the stickies project) object feels like it will at least afford me a bit of cohesion while I figure out a better method.</p>
<p>Now to get it passing:</p>
<p><pre class="brush: jscript; auto-links: false; gutter: false; wrap-lines: false;">
var TSP = {
  update_sticky_text_handler : function(value, settings){
                                 return value;
                               }
};
</pre></p>
<p>There, that made it passed, plus satisfied the first behavior that the jEditable component required: the handler returns the new value. In our case, we didn&#8217;t need anything fancy, so this was good enough. Of course, this didn&#8217;t do much, so we need to add the code that would interact with the back-end. The jEditable component executes the handler in the context of the inline editor div, so &#8216;this&#8217; would be that div. The schema for a sticky was starting to look like:</p>
<p><pre class="brush: xml; auto-links: false; gutter: false; wrap-lines: false;">
&lt;div class='sticky'&gt;
  &lt;div class='editable' id='sticky_23'&gt;&lt;/div&gt;
&lt;/div&gt;
</pre></p>
<p>Looking at this, and knowing that we were executing in the context of div.editable, it seemed naturally to have a 2-step process for updating the sticky:</p>
<ol>
<li>construct some sort a sticky object from the div.editable</li>
<li>call #update_content on the sticky object</li>
</ol>
<h3>Reflecting on the work so far</h3>
<ul>
<li>I felt really good with the way that things were progressing, especially how the spike led me to some conclusions about my code and drove me to learn ScrewUnit a bit more. The side-by-side testing on the spike gave me confidence with the toolset, so I was able to build some examples with the code there to base it on.</li>
<li>By holding myself to a bit of isolation, I see that an abstraction has snuck in: &#8216;sticky object.&#8217; What is going to be? I don&#8217;t totally know at this point, but I do know that it is constructed from div.editable somehow and it has an #update_content method which, apparently, updates the content in the backend.</li>
<li>Having a global TSP object feels a bit weird. It is going to be shared between everything, and that makes me uncomfortable. Of course, it is much better than just having free-floating functions out in the world. Not the spoil the surprise, but having a global object like this causes me a bit of pain and annoyance soon, so I end up getting rid of it. :) But, that is a story for the near future.</li>
</ul>
<h3>What is coming up in the next installment</h3>
<p>I&#8217;ve got an idea of what needs to be done, so it is time to write the examples for the updating process and implement the code. Also, we&#8217;ll start writing more examples, learn the smoke framework, get annoyed with the smoke framework, realize that our annoyance is telling us something about our preconceptions, accept that our frustration has a lesson hidden in it, then listen to what the difficulties tell us about our design.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/41/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=41&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2010/01/04/listening-to-tests-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d7807bb66e1a0c68c73ab2daaa77d8f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">coreyhaines</media:title>
		</media:content>
	</item>
		<item>
		<title>Testing the javascripts</title>
		<link>http://thestickiesproject.wordpress.com/2009/12/31/testing-the-javascripts/</link>
		<comments>http://thestickiesproject.wordpress.com/2009/12/31/testing-the-javascripts/#comments</comments>
		<pubDate>Thu, 31 Dec 2009 21:19:06 +0000</pubDate>
		<dc:creator>coreyhaines</dc:creator>
				<category><![CDATA[Setup]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://thestickiesproject.wordpress.com/?p=18</guid>
		<description><![CDATA[The Stickies Project is a fairly straight-forward, resource-oriented application that sits in the sweet spot for Ruby on Rails. The three main resources (users, projects and stickies) don&#8217;t require anything fancier than the standard CRUD operations with validations. Making use of James Golick&#8217;s excellent ResourceController gem makes the backend portions almost custom-code-free, and by sticking [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=18&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The Stickies Project is a fairly straight-forward, resource-oriented application that sits in the sweet spot for Ruby on Rails. The three main resources (users, projects and stickies) don&#8217;t require anything fancier than the standard CRUD operations with validations. Making use of James Golick&#8217;s excellent <a title="Resource Controller" href="http://github.com/jamesgolick/resource_controller">ResourceController</a> gem makes the backend portions almost custom-code-free, and by sticking with a strict resource-oriented design, we can treat the server-side code as a datastore. In this case, our application code moves up a layer to the browser making JavaScript our primary development language for the stickies project. Since the heart of our application is in JavaScript, it would be irresponsible of us not to focus our design and testing efforts on it. But&#8230;but, I don&#8217;t know how to do that in the javascripts! It is going to slow me down. Well, should I make a plea to the all-holy god of &#8216;<a title="You aren't pragmatic, you just suck" href="http://programmingtour.blogspot.com/2009/10/on-term-pragmatic.html">being pragmatic</a>&#8216; and cover up my lack of skill? Hellz to the no! Let&#8217;s get started learning and, shock of shocks, maybe even practicing a bit, so it doesn&#8217;t slow me down in the future!</p>
<p>This post will discuss my experiences setting up and trying out the Blue Ridge JavaScript testing environment.</p>
<p><span id="more-18"></span></p>
<p>My previous experience with testing JavaScript was almost non-existent (I did a tiny bit with <a title="Get it done, but do it right" href="http://programmingtour.blogspot.com/2009/03/story-about-getting-it-done.html">my own assertEquals function</a>), so it was time to settle down and do some learning. There are a lot of JavaScript testing solutions out there, but, based on my knowledge of the maintainers, I chose to use <a title="Blue Ridge" href="http://github.com/relevance/blue-ridge">Blue Ridge</a> by <a title="Drink Relevance" href="http://thinkrelevance.com/">Relevance Software</a>. I know those guys, having spent a couple months working with them, and I have a lot of respect for their code. There are other blog posts (<a title="Testing javascript is fun and easy" href="http://blog.thinkrelevance.com/2009/5/12/blue-ridge-1-0-javascript-unit-testing-for-rails-scandalous">Jason Rudolph&#8217;s</a> and <a title="Dr Nic is a real doctor....of javascript testing" href="http://drnicwilliams.com/2009/11/12/dead-simple-javascript-unit-testing-in-rails/">Dr Nic&#8217;s</a>) that outline the inner details and usage of Blue Ridge (it packages other tools, such as ScrewUnit, to form the whole solution), so I&#8217;ll just write here the steps I took to set it up. I was a bit nervous about what effort it may take to get it up and running in my app, but, as you&#8217;ll see, it was trivial to get my first tests running. By no means am I a ScrewUnit expert, having only written a few tests now all in the form expects(x).to(equal,y), but after only a couple minutes of investigation, I had a test up and running in my own system.</p>
<p><strong>Note:</strong> I know that Blue Ridge wraps a lot of other frameworks in a nice package, so some things that I attribute to Blue Ridge might actually be part of ScrewUnit or env.js or Rhino or Smoke, but I haven&#8217;t done the deep-dive to figure out which parts are which. So, for the sake of my sanity and time, I&#8217;m going to just say everything is part of Blue Ridge. If I mention some feature that is part of one of the packaged frameworks, feel free to put a comment here that sets the record straight.</p>
<p>I want to stress that, while I&#8217;m learning the framework, I am doing a combination of test-first and test-while programming, not TDD. In other languages, where I am comfortable with the tools, I live in a fairly strict BDD workflow, but I&#8217;m still getting used to the tools here. So, as <a title="JB Rainsberger knows his shit!" href="http://programmingtour.blogspot.com/2009/07/test-first-and-test-driven-conversation.html">JB Rainsberger talks about</a>, I&#8217;m still at the point of worrying about testing and not ready to listen to what they are telling me about my design. Also, while I&#8217;ll be looking at <a title="jsSlim" href="http://github.com/ggramlich/JsSlim">jsSlim</a> in the future to fill the heart-shaped hole in my chest that keeps me from doing a nice BDD workflow in the javascripts (I worked on the original RubySlim implementation, so I have a sweet spot in my heart for slim. Plus, I saw Uncle Bob talk about the latest and greatest things in FitNesse last week at the Columbus Ruby Brigade, and I must say that I am pretty damn impressed), I don&#8217;t have the tools, yet. So, I&#8217;m starting at the beginning and building up to TDD.</p>
<h3>Setting up Blue Ridge</h3>
<p>Holy Shit! Talk about easy to setup. I followed the instructions in the readme in the project, and, what do you know, they were right. Here&#8217;s a summarized version of them:</p>
<ol>
<li>install the plugin (command)</li>
<li>generate a spec file for your js file</li>
<li>run rake spec:javascripts</li>
<li>add spec:javascripts to my default rake task</li>
</ol>
<p><strong>Note:</strong> application_spec.js<br />
It is worth mentioning that I deleted the application_spec.js file. I usually delete my application.js file when I init a new rails app, as having it there sets a bad precedent as a dumping ground for the javascripts. I like to keep mine organized, just like I do in other languages, so, since we were dealing with stickies, I generated a stickies_spec.js to go along with the stickies.js file.</p>
<h3>HTML Fixtures</h3>
<p>A nifty part of Blue Ridge is the html fixtures. They provide a dom that I can configure in my own way to test out my codes. It was nice to use it as a proving ground for the structure of my html, which I could then use as a concrete example when building my views. A happy side-effect was that it showed a few places where I felt the need to write a view spec. This was surprising to me, as I generally don&#8217;t write them.</p>
<p>For example, the main user-interface element is the sticky. The visual representation of the sticky is a div.sticky, and, especially since we were still building towards the appropriate javascript abstraction, it was important to have a good schema for the it. When posting new content (using the inline editing component <a title="jEditable (say it 10 times)" href="http://www.appelsiini.net/projects/jeditable">jEditable</a>), we needed to have the uri for updating the sticky. Being a good little boy, I decided that it should be generated on the server and passed with the sticky, so I needed a place to put it that was accessible. The sticky content was a child div (.editable), and I first put the uri as @data-update-url at this level, but, as I was writing the javascripts for posting any new content to the update uri, it became clear that the update url was not associated with the content, but was related to the sticky, itself. So, up it moved to the .sticky div. This seemed pretty important to me, so I quickly generated a view spec and wrote an example for showing that the @data-update-url was being correctly populated on the div. As expected, it failed, so I jumped over the view and moved it to the correct place. Growl growled at me that all was green, and, appropriately enough, the birds started singing happy songs about the green bars of lore.</p>
<p>HAHA! I just told Sarah &#8220;a couple paragraphs above, I mentioned that I wasn&#8217;t doing TDD with javascript, then I realized that I wrote a paragraph about how my tests recommended some design improvements.&#8221;</p>
<p>Well, that&#8217;s it for now. I&#8217;ll be writing more blog posts with details about testing the javascripts later!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/thestickiesproject.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/thestickiesproject.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/thestickiesproject.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/thestickiesproject.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/thestickiesproject.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/thestickiesproject.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/thestickiesproject.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/thestickiesproject.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/thestickiesproject.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/thestickiesproject.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/thestickiesproject.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/thestickiesproject.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/thestickiesproject.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/thestickiesproject.wordpress.com/18/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=thestickiesproject.wordpress.com&amp;blog=11158180&amp;post=18&amp;subd=thestickiesproject&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://thestickiesproject.wordpress.com/2009/12/31/testing-the-javascripts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d7807bb66e1a0c68c73ab2daaa77d8f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">coreyhaines</media:title>
		</media:content>
	</item>
	</channel>
</rss>
