<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="/css/rss.css"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Jeff Olson's bleg</title>
  <link href="http://olsonjeffery.github.com/atom.xml" rel="self"/>
  <link href="http://olsonjeffery.github.com/"/>
  <updated>2011-06-13T16:17:47-07:00</updated>
  <id>http://olsonjeffery.github.com/</id>
  <author>
    <name>Jeff Olson</name>
    <email>olson.jeffery@gmail.com</email>
  </author>
       
  
    <entry>
      <title>Deployment with OpenWrap</title>
      <link href="http://olsonjeffery.github.com/infrastructure/tooling/.NET/2011/02/01/Deployment-with-OpenWrap.html"/>
      <updated>2011-02-01T00:00:00-08:00</updated>
      <id>http://olsonjeffery.github.com/infrastructure/tooling/.NET/2011/02/01/Deployment-with-OpenWrap</id>
      <content type="html">&lt;p&gt;This post is a brief, hand-wavey outline of my efforts to integrate and abuse OpenWrap for the purposes of deployment automation in my shop. I began working on this post before starting the actual process of integrating OpenWrap and have updated as I&amp;#8217;ve progressed. The goal should be that, when complete, it will provide an introductory outline of what a newcomer to OpenWrap (as I consider myself, prior to this post) will want to know/learn in order to competantly grapple with the topics contained herein.&lt;/p&gt;

&lt;p&gt;I will begin by discussing some assumptions about the environment for this exercise (as they pertain to my particular situation), then talk about where my shop was before integrating with OpenWrap and what our current deployment process consists of. Next, I will outline where I &lt;em&gt;want&lt;/em&gt; to be once fully integrated with OpenWrap. Finally (the important stuff), I will provide purposefully vague play-by-play of the conversion process (as, neccesarily, each shop&amp;#8217;s needs and constraints will differ.. so excessive preciseness in the blog post will only serve to, ultimately, mislead you, the gentle reader) starting from a &amp;#8220;vanilla non-OpenWrap&amp;#8217;d&amp;#8221; ASP.NET MVC 2.0 webapp.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s key to point out that, as far as I can surmise, using OpenWrap for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deployment automation&lt;/li&gt;

&lt;li&gt;Packaging ASP.NET MVC projects&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;.. is a massive abuse of it&amp;#8217;s intended purpose. I make no warranties as to the fitness of the process outlined herein and fully expect to inspire the Wrath of Seb as a result (have you ever seen how he browbeats the NuGet people?).&lt;/p&gt;

&lt;h3 id='some_assumptions'&gt;Some Assumptions&lt;/h3&gt;

&lt;p&gt;This post assumes that you&amp;#8217;re working in a MS.NET environment deployed to some variant (most likely Server) of the Windows OS ecosystem. We&amp;#8217;re still on Server 2003 (with a migration to 2008R2 in the next 12 months). It&amp;#8217;s not-at-all clear to me what the Mono/Linux story is for OpenWrap, so I make no warranty that this process can be adapted for such an environment. My shop is still .NET 2.0/3.5SP1-based, so that is the point from which I&amp;#8217;m starting in this post (.NET 4.0 is also on the 12 months plan, heh). Also, my actual production servers exist on a DMZ that is not domain joined and requires copious amounts of red-tape to be waded-through in order to open ports back into some of office backoffice machines in non-DMZ&amp;#8217;d parts of our corporate intranet.&lt;/p&gt;

&lt;h3 id='our_preopenwrap_deployment_process'&gt;Our Pre-OpenWrap Deployment Process&lt;/h3&gt;

&lt;p&gt;Our current setup, roughly, looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Devs work and check-in to our mercurial repo, as needed&lt;/li&gt;

&lt;li&gt;For every checkin, a jenkins build runs. The complete webapp project directory (bins, src, views, etc), post-build, is published as an artifact&lt;/li&gt;

&lt;li&gt;Once we&amp;#8217;re ready to deploy to prod, we have a special, manually triggered, jenkins build that will take the artifacts of the most recent, successful, build and do some config replacement for the prod environment (it&amp;#8217;s configured for dev/test by default) and package the result into a zip. The resulting zip file can be decompressed on the root of the drive on our application servers (so it unpacks into Inetpub/wwwroot by default). This zip file is published as the artifact of the build&lt;/li&gt;

&lt;li&gt;Whoever is doing the deployment (we&amp;#8217;ll call them &amp;#8220;Ops&amp;#8221;) will go to the jenkins page and download the zip artifact from the last step to their local machine&lt;/li&gt;

&lt;li&gt;Ops will then log into the application servers via RDP and copy the zip file onto the machine via the &amp;#8220;Local Resources&amp;#8221; exposure of their local hard drive&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We&amp;#8217;ve found that step 4 is the killer, as it appears to take ~15 minutes of manual time to copy the resource across the intranet. As noted above in the &amp;#8220;Some Assumptions&amp;#8221; section, the app servers are on a DMZ and all ports back into the intranet are closed by default (including network file shares) and the servers are &lt;em&gt;not&lt;/em&gt; domain-joined. My suspicion is that this method of copying large files (the prod deployment zip is ~35MB, currently) across the Local Resources pipe (or, perhaps more aptly, straw) is sub-optimal. I&amp;#8217;d like to test how long it&amp;#8217;ll take when done via HTTP or other methods. I get a feeling that SMB fileshares will be a non-starter, here, as it appears to require the opening of 4-or-more ports and not to mention the whole Active Directory component that isn&amp;#8217;t present on servers in the DMZ. I&amp;#8217;d love to check out rsync, but I get the impression that it&amp;#8217;s support is kind of flakey on Windows. So I&amp;#8217;m interested in seeing what an HTTP transfer of an equivelant size, from the intranet, will look like time-wise.&lt;/p&gt;

&lt;p&gt;But another component of what&amp;#8217;s so horrible about Step 4 is not just the time, but the &amp;#8220;disconnect&amp;#8221; that it creates in what is otherwise a mostly fluid process. That is 15 minutes that an Ops person has to sit there and twiddle their thumbs waiting for the process to complete. It&amp;#8217;s easy to get distracted and not check back until well after the copy has completed. I would like to get to an end-to-end automated process so that, regardless of how long it takes, we can click a button and know that the deployment will be finished, eventually, without dependence upon human intervention. An email notification of completion would be nice as well, but not neccesary.&lt;/p&gt;

&lt;h3 id='where_we_want_to_be'&gt;Where we want to be&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Still have the jenkins build(s) as detailed above&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Chances are the manually-triggered &amp;#8220;prod config/zip&amp;#8221; jenkins build (detailed above in step 3) will be modified to also include publishing the resultant artifact to an intranet-based OpenWrap repository server. OpenWrap seems to support network fileshare-based repositories out-of-the-box, but I think this&amp;#8217;ll be a non-starter for my shop based on the constraints of the DMZ outlined above. So I want a web-server based repository. The solution is quite simple (basically, we do both), and is detailed below (duh)&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Open ip/ports from my production servers to the internal OpenWrap repository&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;From here, two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setup scheduled tasks on the production servers that periodically checks our internal repo for a new package and updates, accordingly. A polling based approach.&lt;/li&gt;

&lt;li&gt;Add support in the app, itself, to allow it to spin off a new process to check for updates via &lt;code&gt;o.exe&lt;/code&gt; and update itself, as needed. We have a place in our app where this could live, already.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Finally, some kind of completion notification once the new site wrap has been installed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Really the goal is to drastically reduce the amount of needed human intervention, in order to successfully deploy, to a couple of mouse clicks. Reducing the speed of the deployment would be nice, but is not essential (especially if we do discover that we are severely hamstrung by a bottleneck in throughput across the intranet between the DMZ and backoffice machines where the OpenWrap will live).&lt;/p&gt;

&lt;h3 id='step_1_make_the_web_application_a_wrap'&gt;Step 1: Make The Web Application A Wrap&lt;/h3&gt;

&lt;p&gt;So, first things first, we have to set up an OpenWrap &amp;#8220;skeleton&amp;#8221; package into which we&amp;#8217;ll place the source of the application that we&amp;#8217;re trying to make into a deployable artifact (in OpenWrap parlance, this is called a &amp;#8220;wrap&amp;#8221;, although we&amp;#8217;re misappropriate the framework a bit in order to have it do our evil bidding). In all places below, I use &lt;code&gt;projectname&lt;/code&gt; as a standin for whatever you wanted to name your wrap, so please substitute appropriately.&lt;/p&gt;

&lt;p&gt;I created a new &amp;#8220;wraps&amp;#8221; directory, inside of which I intend to place any packages I create. I think initialized my new project in there.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir wraps
o init-wrap projectname&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since my environment is Windows Server 2003 based (and I&amp;#8217;ve had problems dealing with the symbolic links/junctions that OpenWrap uses by default), I make sure to disable symbolic links as detailed &lt;a href='https://github.com/openrasta/openwrap/wiki/Package-descriptor'&gt;here&lt;/a&gt;. Open up the &lt;code&gt;projectname.wrapdesc&lt;/code&gt; in your newly created package directory and add:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use-symlinks: false&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to the config.&lt;/p&gt;

&lt;p&gt;After this, go ahead and copy in (or create) the project that you want to encapsulate in the wrap to the &lt;code&gt;src/&lt;/code&gt; directory in your package skeleton. After that, enter:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;o init-wrap -all&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;from the CLI to have OpenWrap hook into your project file (it does this by changing the default compiler target in your .csproj). All of the intracacies of this process are beyond the scope of this blog post, so a good place to start, if you want to learn more, is &lt;a href='https://github.com/openrasta/openwrap/wiki'&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After this, you should now have your project set up as a wrap (in the default configuration). You should be able to do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;o build-wrap -quiet&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;from the CLI and get a .wrap file as output. This is actually just a zip, which you can rename/decompress to check out the contents of in order to get some understanding of how it packages your build artifacts by default.&lt;/p&gt;

&lt;p&gt;For me, though, this wasn&amp;#8217;t the end of the story&amp;#8230;&lt;/p&gt;

&lt;h3 id='step_15_shoehorning_an_aspnet_mvc_webapp_structure_into_openwrap'&gt;Step 1.5: Shoehorning an ASP.NET MVC Webapp Structure Into OpenWrap&lt;/h3&gt;

&lt;p&gt;By default, it appears that OpenWrap is setup to work with projects that aren&amp;#8217;t particularly finnicky about where the bins and resources are placed (or, perhaps more appropriately, are structured to lump everything together in a single build directory). Things like Class Library projects and CLI apps come to mind, here. This works pretty well for Class Libraries (and perhaps even typical CLI projects), but it doesn&amp;#8217;t work (for me), out of the box, for ASP.NET apps (sadly). Of course, it should be noted that I&amp;#8217;m not saying that OpenWrap is fundamentally incapable of dealing with these projects, but it seems that it doesn&amp;#8217;t package them correctly out of the box (whether the remedy is education on how to properly configure OpenWrap or a feature implementation is beyond me at this time).&lt;/p&gt;

&lt;p&gt;My solution, in this case, is to just hand-roll my own &lt;code&gt;.wrap&lt;/code&gt; that abides the constraints required to have a running ASP.NET MVC site (all binaries in &lt;code&gt;/bin&lt;/code&gt; under the root, expose &lt;code&gt;Views&lt;/code&gt;, &lt;code&gt;Content&lt;/code&gt;, &lt;code&gt;Scripts&lt;/code&gt;, have a &lt;code&gt;Default.aspx&lt;/code&gt; and &lt;code&gt;Global.asax&lt;/code&gt; in the root, etc). For now, this is easier than bruising my brain trying to figure out how to make OpenWrap do this via configuration.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not sure how much of the issue is solvable by configuration in the .csproj and how much is a current limitation of OpenWrap, but suffice to say that this is something I wanted to talk about so that it can either 1) be brought up as a possible feature/fix and use case for OpenWrap or 2) be solved by way of education. I&amp;#8217;m also painfully aware of the fact that I&amp;#8217;m taking OpenWrap way outside of it&amp;#8217;s intended comfort zone as part of what I&amp;#8217;m doing in this blog post.&lt;/p&gt;

&lt;p&gt;Obviously, this situation is a &lt;em&gt;big&lt;/em&gt; your-mileage-may-vary kind of thing, but to give you an idea of what I did to make an ASP.NET MVC package nicely into a wrap:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='c1'&gt;# this was derived from:&lt;/span&gt;
    &lt;span class='c1'&gt;# http://snippets.dzone.com/posts/show/6409&lt;/span&gt;
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;get_newest_wrap&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;matching&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='sr'&gt;/.*wrap$/&lt;/span&gt;
        &lt;span class='n'&gt;files&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;entries&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;collect&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;file&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sort&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;file1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;file2&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;mtime&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;file1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;mtime&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;file2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
        &lt;span class='n'&gt;files&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;reject!&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;file?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='n'&gt;file&lt;/span&gt; &lt;span class='o'&gt;=~&lt;/span&gt; &lt;span class='n'&gt;matching&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;?&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt; &lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
        &lt;span class='n'&gt;files&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;last&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;get_version_from&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;open&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt;
      &lt;span class='n'&gt;lines&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;readlines&lt;/span&gt;
      &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;close&lt;/span&gt;
      &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;last&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sub&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='sr'&gt;/\.\*/&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
    &lt;span class='vi'&gt;@siteDir&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;bin-net35&amp;#39;&lt;/span&gt;
    &lt;span class='vi'&gt;@toolsDir&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class='c1'&gt;# where I have some bin tools I use during builds&lt;/span&gt;
    &lt;span class='vi'&gt;@targetProjectName&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;My.Asp.Net.Project&amp;#39;&lt;/span&gt;
    &lt;span class='n'&gt;desc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;hand-roll a wrap for an ASP.NET MVC site&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:drybuildwrap&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='n'&gt;mkpath&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;working&amp;#39;&lt;/span&gt;  
      &lt;span class='n'&gt;version&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;get_version_from&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;.&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;version&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;ts&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;to_i&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;to_s&lt;/span&gt; &lt;span class='c1'&gt;# being lazy and using a unix timestamp&lt;/span&gt;
                              &lt;span class='c1'&gt;# as the build number. it works, i guess.&lt;/span&gt;
      &lt;span class='n'&gt;pkg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;myaspnetproject&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;wrapFile&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;pkg&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;-&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;version&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;.&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;ts&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;.wrap&amp;quot;&lt;/span&gt;
      &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chdir&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;working&amp;#39;&lt;/span&gt;
      &lt;span class='n'&gt;mkpath&lt;/span&gt; &lt;span class='vi'&gt;@siteDir&lt;/span&gt;
    
      &lt;span class='c1'&gt;# files needed in the root of the app, besides bin&lt;/span&gt;
      &lt;span class='n'&gt;rootFiles&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;Default.aspx&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Global.asax&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;robots.txt&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Web.config&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Content&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Scripts&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Views&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
      &lt;span class='n'&gt;rootFiles&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
        &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;src&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='vi'&gt;@targetProjectName&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='vi'&gt;@siteDir&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='c1'&gt;# /bin&lt;/span&gt;
      &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;src&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='vi'&gt;@targetProjectName&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;bin&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='vi'&gt;@siteDir&lt;/span&gt;
    
      &lt;span class='c1'&gt;# needed OpenWrap files&lt;/span&gt;
      &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;version&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;.&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;pkg&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;.wrapdesc&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;.&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;mv&lt;/span&gt; &lt;span class='vi'&gt;@siteDir&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;bin-net35&amp;#39;&lt;/span&gt;
      
      &lt;span class='c1'&gt;# tools dir -- some stuff needed to bootstrap the self-updating&lt;/span&gt;
      &lt;span class='c1'&gt;# functionality .. covered in Step 4.5 below&lt;/span&gt;
      &lt;span class='n'&gt;mkdir&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;tools&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;Tools&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z.dll&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;tools&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;Tools&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z.exe&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;tools&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;rakefile.rb&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;tools&amp;quot;&lt;/span&gt;
    
      &lt;span class='c1'&gt;# Finally, let&amp;#39;s create our wrap&lt;/span&gt;
      &lt;span class='n'&gt;sh&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;Tools&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z.exe a -tzip -r ..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;wrapFile&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; *&amp;quot;&lt;/span&gt;
      &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chdir&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;..&amp;#39;&lt;/span&gt;
      &lt;span class='n'&gt;rmtree&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;working&amp;#39;&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Pretty wild, I know.&lt;/p&gt;

&lt;h3 id='step_2_setup_an_openwrap_repository_to_publish_to'&gt;Step 2: Setup An OpenWrap Repository To Publish To&lt;/h3&gt;

&lt;p&gt;This was a real head-scratcher for me, at first, so I asked about it on the OpenWrap mailing list. I was looking for a full HTTP implementation of an OpenWrap server and, seeing only a stub on github, I went to harass Seb for the full source. The thread is &lt;a href='http://groups.google.com/group/openwrap-devel/browse_thread/thread/ad4f5329f9411e81'&gt;here&lt;/a&gt;. His solution was pretty elegant. From the thread (where he&amp;#8217;s speaking about what he does for the main OpenWraps repo):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As for wraps.openwrap.org, I use something much simpler. I use a file share repository to write packages from teamcity, and on the read side i simply share the same folder as an http folder, that works out of the box as is, so if you&amp;#8217;re just looking at exposing the read side, you can do that now already.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, it&amp;#8217;s pretty simple. With this in mind, I set up two servers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;file://buildserver/openwraps/myaspnetsite&lt;/code&gt; &amp;#8211; A fileshare based repository server that the build server can publish to after a successful build&lt;/li&gt;

&lt;li&gt;&lt;code&gt;http://buildserver&lt;/code&gt; &amp;#8211; A read-only repository that is exposed via IIS 6 directory listing magic (And do remember to add the &lt;code&gt;.wraplist&lt;/code&gt; and &lt;code&gt;.wrap&lt;/code&gt; to your MIME-types if using IIS 6, as I am :/ )&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can find some documentation on setting up OpenWrap repositories &lt;a href='https://github.com/openrasta/openwrap/wiki/Package-repositories'&gt;here&lt;/a&gt;. The actual, esoteric details of your hosting needs are something that I can&amp;#8217;t give specific guidance on.&lt;/p&gt;

&lt;p&gt;For me, above setup gives the flexibility I need for my deployment environment (where I can open a single port on a machine in my backoffice intranet to the DMZ servers), while allowing me to easily publish packages in the backoffice environment (where our build machine lives and the rules are somewhat more lax).&lt;/p&gt;

&lt;h3 id='step_3_integrate_openwrap_publishing_into_build_process'&gt;Step 3: Integrate OpenWrap Publishing Into Build Process&lt;/h3&gt;

&lt;p&gt;This one I will leave as an exercise for the reader. Personally, I&amp;#8217;m using Jenkins (née Hudson) for our builds (with most of the action in rake scripts). I&amp;#8217;ve written some tasks to hand-roll the .wrap (as detailed in Step 1.5 above) and publish that to my fileshare repository.&lt;/p&gt;

&lt;p&gt;Bottom line: You need to start producing and publishing wraps as part of your regular build process. Depending on how pervasive your deployment automation will be (just for prod? why not your continuously updated UAT/Staging server, too?) you could continuously push to one repository, while only &amp;#8220;selectively&amp;#8221; pushing to another, &amp;#8220;production-only&amp;#8221; repository when you&amp;#8217;re ready to deploy via some manually triggered automation. Which approach is appropriate to your situation will depend, largely, on Step 5 below.&lt;/p&gt;

&lt;h3 id='step_4_setup_on_the_application_servers'&gt;Step 4: Setup On The Application Servers&lt;/h3&gt;

&lt;p&gt;After doing the neccesary legwork on my DMZ servers (like opening the port to my read-only HTTP server in the backend and setting up the OpenWrap shell), I have to a few things.&lt;/p&gt;

&lt;p&gt;First, I need to make OpenWrap aware of the repository from which it can fetch the wrap it needs. This was as simple as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;o add-remote myaspnetsite http://buildserver&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As outlined in Step 2 above, this corresponds to the read-only server that I exposed for my DMZ servers to pull from.&lt;/p&gt;

&lt;p&gt;Next, I will initialize a stub project that I&amp;#8217;m going to use to &amp;#8220;host&amp;#8221; the application that I want to deploy via OpenWrap. Finding the place where I want it to be (like &lt;code&gt;D:\Inetpub\wwwroot&lt;/code&gt; or what-have-you), I did:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;o init-all myaspnetsite_prod&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OpenWrap will give me some static about setting up the project structure. I can now go into there and set things up.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd myaspnetsite_prod&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As above in Step 1, my particular situation warrants that I use &lt;code&gt;use-symlinks: false&lt;/code&gt; in my &lt;code&gt;myaspnetsite_prod.wrapdesc&lt;/code&gt; file. With that out of the way, I can do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;o add-wrap myaspnetsite -Anchored&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And, if everything&amp;#8217;s wired up properly, OpenWrap will download and unpack your package within the &lt;code&gt;myaspnetsite_prod/wraps/myaspnetsite&lt;/code&gt; directory. If any of the stuff from previous steps is messed up (like your publishing or hosting for the HTTP repository), you&amp;#8217;ll have some problems here.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-Anchored&lt;/code&gt; flag tells OpenWrap that the dependency you&amp;#8217;re adding you should be unpacked in a &amp;#8220;visible&amp;#8221; location (ouside of the &lt;code&gt;_cache&lt;/code&gt; dir). Normally this is so that you can check that dependency in, but it serves us here by exposing it in a fixed location (independant of the version). More info on package anchoring is available &lt;a href='https://github.com/openrasta/openwrap/wiki/Package-anchoring'&gt;here&lt;/a&gt;. From here, you should be able to point IIS at the &lt;code&gt;myaspnetsite_prod/wraps/myaspnetsite&lt;/code&gt; folder and it will work (provided your .csproj has its references, etc, working right and nothing squirrely happens with how you&amp;#8217;re reworking the wrap.. this is some brittleness that I&amp;#8217;ve brought on myself, here.. I hope in the course of discussing this process, a more elegant solution can be sussed out).&lt;/p&gt;

&lt;h3 id='step_45_a_brief_digression_on_the_topic_of_updating_aspnet_sites'&gt;Step 4.5: A Brief Digression On The Topic Of Updating ASP.NET Sites&lt;/h3&gt;

&lt;p&gt;The whole point of this exercise is to get to a point where, once we have the OpenWrap infrastructure in place, updating to newer versions will be a snap. This is complicated by a major, blocking issue: OpenWrap won&amp;#8217;t &amp;#8220;re-anchor&amp;#8221; updated packages if any of the files in the old package directory are locked. This is the case because OpenWrap updates anchored packages by removing the old directory and replacing with a new one (which is pretty sensible in most cases). This isn&amp;#8217;t neccesarily what we want in ASP.NET land, though, we where can just unzip a new install over the old one and, provided there isn&amp;#8217;t any weirdness with renamed assemblies, etc, ASP.NET will pick up the file changes on the next request and recycle the app automagically. And, while we can unzip over a running application without complaint from IIS, we cannot &lt;em&gt;nuke&lt;/em&gt; the directory of a running without, at the least, taking downt he web site (which may cause false alarms with your application monitoring infrastructure).&lt;/p&gt;

&lt;p&gt;I get the impression that there&amp;#8217;s a lot of people who are used to stopping the web site in order to do updates. I&amp;#8217;ve never been one of those people (unless there&amp;#8217;s file locking issues that prevent a clean unzip, in which case you have no choice but to stop the site). With this in mind, I prefer a deployment process that involves unpacking a zip and letting it override an existing, live app. If this is a grossly irresponsible perspective to take, I&amp;#8217;d like to hear about that (I mean, as much as anyone likes to hear &amp;#8220;you&amp;#8217;re an idiot!&amp;#8221;).&lt;/p&gt;

&lt;p&gt;Anyways, back to the issue at hand: How to work around OpenWrap&amp;#8217;s design limitation in terms of updating a &amp;#8220;live&amp;#8221; site? More rake scripting, of course!&lt;/p&gt;

&lt;p&gt;For me, the strategy is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I decided to modify the rake task outlined above in Step 1.5 to include an additional rakefile (containing the snippet below) and a CLI unzipping utility (7zip, if you must know) in the deployable artifacts for my wrap.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The rakefile that is now embedded in the &lt;code&gt;.wrap&lt;/code&gt; contains logic to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find out what the version # is of the &amp;#8220;newest&amp;#8221;, locally held wrap for our package that we want to continuously update&lt;/li&gt;

&lt;li&gt;Check the remote repository and, using &lt;code&gt;o list-write&lt;/code&gt; and some output parsing magic, find out what its newest version of our target wrap is&lt;/li&gt;

&lt;li&gt;If the remote&amp;#8217;s newest is not equal to ours (unlikely that we&amp;#8217;ll slidebackwards in revisions and maybe even desirable, at times, if so (like a rollback scenario)), then:&lt;/li&gt;

&lt;li&gt;Run &lt;code&gt;o update-wrap&lt;/code&gt; which will, of course, fail to anchor our package (but still download the &lt;code&gt;.wrap&lt;/code&gt; for us)&lt;/li&gt;

&lt;li&gt;Having downloaded a new version, we now find the filename of the newest version of our package (which should be the new one)&lt;/li&gt;

&lt;li&gt;We copy out our CLI unzip&amp;#8217;ing util and then use it to unzip our new package (you have to copy it out, otherwise it&amp;#8217;ll explode when trying to overwrite itself)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I ended up with a script something like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='c1'&gt;# This is pretty lame and depends on the impl of o.exe&amp;#39;s CLI output.. have to&lt;/span&gt;
    &lt;span class='c1'&gt;# keep an eye peeled for changes, here&lt;/span&gt;
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;newest_version_of_package_on_remote&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pkg&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;repo&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='n'&gt;output&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='sb'&gt;`o list-wrap -Query &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;pkg&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='sb'&gt; -Remote &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;repo&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='sb'&gt;`&lt;/span&gt;
      &lt;span class='n'&gt;line&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;output&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;last&lt;/span&gt;
      &lt;span class='n'&gt;line&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;line&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sub&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='sr'&gt;/^.*available: /&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sub&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='sr'&gt;/\)$/&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='n'&gt;line&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;last&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:hotupdate&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='c1'&gt;# this is the task we&amp;#39;ll run from a scheduled task on the app server&lt;/span&gt;
      &lt;span class='n'&gt;pkg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;myaspnetproject&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;repo&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;myaspnetprojectrepo&amp;quot;&lt;/span&gt;
      &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chdir&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;..&amp;quot;&lt;/span&gt; &lt;span class='c1'&gt;# we&amp;#39;re executing from somerepo\wraps\myaspnetproject\tools .. &lt;/span&gt;
                         &lt;span class='c1'&gt;# need to move up the somerepo\wraps\ dir&lt;/span&gt;
      &lt;span class='n'&gt;localWrap&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;get_newest_wrap&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pwd&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sub&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='sr'&gt;/&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;pkg&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='sr'&gt;-/&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sub&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='sr'&gt;/\.wrap/&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='n'&gt;newestWrap&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;newest_version_of_package_on_remote&lt;/span&gt; &lt;span class='n'&gt;pkg&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;repo&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;localWrap&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;newestWrap&lt;/span&gt;
        &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;at latest&amp;quot;&lt;/span&gt;
      &lt;span class='k'&gt;else&lt;/span&gt;
        &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;updating...&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;sh&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;o update-wrap&amp;#39;&lt;/span&gt;
        &lt;span class='n'&gt;wrapFile&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;get_newest_wrap&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pwd&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chdir&lt;/span&gt; &lt;span class='n'&gt;pkg&lt;/span&gt;
        &lt;span class='n'&gt;toolsDir&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;toolsTmp&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;mkdir&lt;/span&gt; &lt;span class='n'&gt;toolsDir&lt;/span&gt;
        &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;tools&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z.exe&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;toolsDir&lt;/span&gt; &lt;span class='c1'&gt;# have to copy out 7zip from the tools dir, so it doesn&amp;#39;t&lt;/span&gt;
        &lt;span class='n'&gt;cp_r&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;tools&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z.dll&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;toolsDir&lt;/span&gt; &lt;span class='c1'&gt;# barf when trying to overwrite itself&lt;/span&gt;
        &lt;span class='n'&gt;sh&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;toolsDir&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='s2'&gt;7z.exe x -y -tzip ..&lt;/span&gt;&lt;span class='se'&gt;\\&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;wrapFile&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;rmtree&lt;/span&gt; &lt;span class='n'&gt;toolsDir&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='step_5_flip_the_switch'&gt;Step 5: Flip The Switch&lt;/h3&gt;

&lt;p&gt;If you made it here successfully, that means that you&amp;#8217;re worked out the details for how to facilitate OpenWrap&amp;#8217;s use as a deployment framework for your project. Now you&amp;#8217;ll have to figure out how to put it on auto-pilot. The key will be to get to the point where you won&amp;#8217;t have to log into your application servers &lt;em&gt;at all&lt;/em&gt; to do a deployment.&lt;/p&gt;

&lt;p&gt;My personal preference is set up a scheduled task on the deployment server that polls for updates on a regular, frequent basis. This way, my deployment choke point is now the act of pushing packages to that repository that is regularly polled (something that I can automate pretty easily as part of my existing build infrastructure). You can easily invert this approach by automating the pushing of packages to your repo and making the update poll be the manually triggered step (via added functionality in your app or some existing tool/server to kick off processes/scripts on your production server).&lt;/p&gt;

&lt;p&gt;I use the &lt;code&gt;:hotupdate&lt;/code&gt; rake task outlined above, executed every five minutes, to check for new versions of our application and handle the downloading and unzipping on an as-needed basis.&lt;/p&gt;

&lt;h3 id='conclusion'&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This post is a skeletal depiction of a process that I&amp;#8217;ve worked through in order use OpenWrap for automating my deployment process (which is currently only automated up-through the point of package generation. Actual deployment on the application server is manual and a hassle). I kept things vague on purpose, as I feel like an overly detailed post would be less valuable (due to be the tendency to get bogged down in semantics and the fact that every environment is different).&lt;/p&gt;

&lt;p&gt;There are a lot of details to work out, but I think the steps outlined above serve as a good place to start for getting things up and running. There&amp;#8217;s a pretty good chance that I&amp;#8217;m doing something Really Wrong, so I&amp;#8217;m interested in having a discussion about what could be done to improve this process.&lt;/p&gt;

&lt;p&gt;With the caveats aside, there are two key points in the OpenWrap workflow where I, pretty much, opt-out in favor doing things a bit differently to suit my own laziness and preferences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When building a new wrap, I roll one by hand (Step 1.5) using a rake script, so that I don&amp;#8217;t have to bother with wrapping my brain around the configuration (see what I did there?).&lt;/li&gt;

&lt;li&gt;When trying to update the wrap (Step 4.5), I go through the motions (in order to have OpenWrap download the newest &lt;code&gt;.wrap&lt;/code&gt; for me), but anticipate the re-anchoring of the new version failing (because IIS has locked the directory) and will go ahead and do a manual upgrade-in-place (by unzipping the &lt;code&gt;.wrap&lt;/code&gt; over the existing anchor, which &lt;em&gt;will&lt;/em&gt; work, most of the time, unlike a delete-and-replace). This may or may not be a bad thing and exposes you to certain Troubles as your application evolves naturally over time (assembly conflicts due to renames, to name just one of many.. not to mention the possibility for &lt;code&gt;.dll&lt;/code&gt; or other files not being updated due to IIS&amp;#8217; rather eccentric and unpredictable file-locking practices). This whole thing stems from the desire to avoid taking down the site/IIS when I can help it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would love to have a discussion around these issues and see if there&amp;#8217;s a possibility to evolve the OpenWrap framework to handle these scenarios/approaches more gracefully, if they&amp;#8217;re deemed safe enough, valuable, etc.&lt;/p&gt;

&lt;p&gt;I hope this post has been valuable for you in your quest to be a Lazier Developer, because that&amp;#8217;s &lt;em&gt;really&lt;/em&gt; what automation about, isn&amp;#8217;t it?&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>An Introduction To machine.javascript Part 2</title>
      <link href="http://olsonjeffery.github.com/javascript/mvc/2010/02/18/An-Introduction-To-Machine-Controller-Part-2.html"/>
      <updated>2010-02-18T00:00:00-08:00</updated>
      <id>http://olsonjeffery.github.com/javascript/mvc/2010/02/18/An-Introduction-To-Machine-Controller-Part-2</id>
      <content type="html">&lt;p&gt;This post is a continuation from &lt;a href='/javascript/mvc/2010/02/17/An-Introduction-To-Machine-Controller.html'&gt;Part 1&lt;/a&gt;, which introduced the ideas of &lt;code&gt;machine-javascript&lt;/code&gt;, namely the script loader and a simple example, showing how a &lt;code&gt;HelloWorldController&lt;/code&gt; was instantiated and attached to the page. What was not explored, however, was what the &lt;code&gt;HelloWorldController&lt;/code&gt; actually looks like and how it works. That is the topic of this post.&lt;/p&gt;

&lt;h3 id='lets_dive_right_in'&gt;Let&amp;#8217;s Dive Right In!&lt;/h3&gt;

&lt;p&gt;Here is the content of &lt;code&gt;HelloWorldController.js&lt;/code&gt;, loaded into our page in the example shown in &lt;a href='/javascript/mvc/2010/02/17/An-Introduction-To-Machine-Controller.html'&gt;Part 1&lt;/a&gt; of the series:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;    &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;jquery.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;machine-controller.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;global&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;viewLeft&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;lt;div&amp;gt;&amp;lt;a id=&amp;quot;clicker&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Hello world!&amp;lt;/a&amp;gt; I have been clicked &amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;viewRight&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39; times.&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      
      &lt;span class='nx'&gt;global&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;HelloWorldController&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;init&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// kicks off Machine.Controller&amp;#39;s internal setup&lt;/span&gt;
                     &lt;span class='c1'&gt;// .. always call this first.&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;setView&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;viewLeft&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;viewRight&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addAction&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;#clicker&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onClickerDivClick&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;

      &lt;span class='nx'&gt;global&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;HelloWorldController&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;Machine&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Controller&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;hw&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;global&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;HelloWorldController&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

      &lt;span class='nx'&gt;hw&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onClickerDivClick&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='c1'&gt;// &amp;#39;this&amp;#39; is always bound to the controller object&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;setView&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;viewLeft&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;viewRight&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;render&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// refresh the domRoot property&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Okay! A lot to take in there. Let&amp;#8217;s start with the &lt;code&gt;include()&lt;/code&gt;s at the top of the file.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;    &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;machine-controller.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='p'&gt;...&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As noted in &lt;a href='/javascript/mvc/2010/02/17/An-Introduction-To-Machine-Controller.html'&gt;Part 1&lt;/a&gt;, calls to &lt;code&gt;include()&lt;/code&gt; are never nested within the scope of a single file, but always occur serially. The first call is to load up &lt;code&gt;machine-controller.js&lt;/code&gt;, upon which this file is dependant. If &lt;code&gt;HelloWorldController&lt;/code&gt; were dependant upon a &amp;#8220;ViewRenderer&amp;#8221; (which is discussed further down), it would also be included at this point. Finally, the actual body of the script is contained within an &lt;code&gt;include()&lt;/code&gt;. This is a convention that must be adherred to in order to leverage the utility of &lt;code&gt;machine-includer.js&lt;/code&gt;. Strictly speaking, &lt;code&gt;machine-controller.js&lt;/code&gt; takes no dependency upon &lt;code&gt;machine-includer.js&lt;/code&gt; and you could easily use it with another script loader or no loader at all, but for the purposes of this example we are going to use it.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;global&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;viewLeft&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;lt;div&amp;gt;&amp;lt;a id=&amp;quot;clicker&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Hello world!&amp;lt;/a&amp;gt; I have been clicked &amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;viewRight&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39; times.&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At this point, we&amp;#8217;re just setting up some variables that will be used in the course of defining &lt;code&gt;HelloWorldController&lt;/code&gt;. I, by habit, typically assign the top-level &lt;code&gt;this&lt;/code&gt; in a given script to &lt;code&gt;global&lt;/code&gt;. The next two variables, &lt;code&gt;viewLeft&lt;/code&gt; and &lt;code&gt;viewRight&lt;/code&gt; are two chunks of text that will make up the &amp;#8220;view&amp;#8221; rendered by &lt;code&gt;HelloWorldController&lt;/code&gt; (that is, the markup that it attaches to the DOM). This approach is not-at-all optimal for general use, but is merely meant to demonstrate the basic functionality of &lt;code&gt;setView()&lt;/code&gt;, which will be covered in-depth below.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='nx'&gt;global&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;HelloWorldController&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;init&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// kicks off Machine.Controller&amp;#39;s internal setup&lt;/span&gt;
                     &lt;span class='c1'&gt;// .. always call this first.&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;setView&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;viewLeft&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;viewRight&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addAction&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;#clicker&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onClickerDivClick&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This chunk of JavaScript is the declaration of &lt;code&gt;HelloWorldController&lt;/code&gt;&amp;#8217;s constructor/intializer and is where the majority of &lt;code&gt;Machine.Controller&lt;/code&gt;-derived controller objects are configured. There&amp;#8217;s a lot of important stuff here, so let&amp;#8217;s go line by line.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;init&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// kicks off Machine.Controller&amp;#39;s internal setup&lt;/span&gt;
                     &lt;span class='c1'&gt;// .. always call this first.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;init()&lt;/code&gt; function in a &lt;code&gt;Machine.Controller&lt;/code&gt;-derived object is where internal initialization is housed. It should be the first thing you call in any controller you define. Obviously, overloading/replacing this would be a Bad Thing unless you really know what you&amp;#8217;re doing. Thankfully, at least, much like Controller development on the server, you&amp;#8217;re not terribly likely to have deeply nested inheritance hierarchies of Controller classes. But if you do need to do so, you can always take measures to Make It Work.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;this.clickCount&lt;/code&gt; is a stateful counter that we&amp;#8217;re going to use to track clicks to the DOM that this controller &amp;#8220;owns&amp;#8221;. This is an example of how client-side controllers are stateful (one thing that can be thought of differently from server-side controllers in many instances).&lt;/p&gt;

&lt;p&gt;Another thing to note: it can generally be assumed that any call to &lt;code&gt;this&lt;/code&gt; in the top-level scope of a function attached to the prototype for a &lt;code&gt;Machine.Controller&lt;/code&gt;-derived object will reference the object itself. This is normal behavior typically but, interestingly, this also applies to functions bound to events using the &lt;code&gt;addAction()&lt;/code&gt; function, which is shown below. Typically, at least with jQuery event binding, &lt;code&gt;this&lt;/code&gt; is bound to some kind of context information for the event in question. Of course, callbacks passed into jQuery functions like &lt;code&gt;$.each()&lt;/code&gt; and &lt;code&gt;$.get()&lt;/code&gt; will still have their &lt;code&gt;this&lt;/code&gt; variable re-bound, as is expected.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;setView&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;viewLeft&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;viewRight&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is the &lt;code&gt;setView()&lt;/code&gt; function, mentioned above. It is used to tell a controller what mechanism it will use to get some markup that will represent its presence in the DOM. There are two valid signatures for this function:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;setView&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;aString&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;setView&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;aString&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;anotherString&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The first signature just takes a single string and is the format used in &lt;code&gt;HelloWorldController&lt;/code&gt;. This treats the passed-in string as static markup text and will move to immediately convert it to a DOM and then attach it to the page&amp;#8217;s DOM when needed. This is the simplest possible use case for &lt;code&gt;setView()&lt;/code&gt; and isn&amp;#8217;t often practical, but can be useful.&lt;/p&gt;

&lt;p&gt;The second signature takes two strings: The first is an argument to pass in to a ViewRenderer. The second argument is the &amp;#8220;key&amp;#8221; for that ViewRenderer. In this case, the &amp;#8220;key&amp;#8221; refers to a string that the renderer uses to globally identify itself when it is registered with &lt;code&gt;Machine.Controllers&lt;/code&gt; mechanism for tracking ViewRenderers. The details of how this works won&amp;#8217;t be covered in this post, but just know that it is there.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;d like to see an example of this use of &lt;code&gt;setView()&lt;/code&gt; and ViewRenderers right now, then look at the &lt;code&gt;/example/example.html&lt;/code&gt; file in the &lt;a href='http://github.com/machine/machine.javascript'&gt;machine-javascript&lt;/a&gt; github repo and check out the &amp;#8216;ViewRenderers and Views&amp;#8217; example.&lt;/p&gt;

&lt;p&gt;Back to the larger issue of the signifigance of &lt;code&gt;setView()&lt;/code&gt;, after calling &lt;code&gt;setView()&lt;/code&gt; you should know that any calls to the controller&amp;#8217;s &lt;code&gt;render()&lt;/code&gt; function will cause whatever &amp;#8220;instructions&amp;#8221; were passed in to &lt;code&gt;setView()&lt;/code&gt; to be reevaluated and the results placed in the &lt;code&gt;domRoot&lt;/code&gt; property of the object. You can also arbitrarily call &lt;code&gt;setView()&lt;/code&gt; at your pleasure to change the &amp;#8220;rendering strategy&amp;#8221; for a given controller (but will of course want to call &lt;code&gt;render()&lt;/code&gt; after that so the changes can be reflected in the &lt;code&gt;domRoot&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The last line in our controller&amp;#8217;s initializer function is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addAction&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;#clicker&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onClickerDivClick&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is the previously mentioned &lt;code&gt;addAction()&lt;/code&gt; function. It is a wrapper around jQuery&amp;#8217;s event binding mechanism that provides a few advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Events bound in this fashion don&amp;#8217;t need to be manually rebound when the controller&amp;#8217;s DOM changes (this uses a combination of jQuery Live Events and manual re-binding on DOM change).&lt;/li&gt;

&lt;li&gt;As mentioned above, callbacks passed in to &lt;code&gt;addAction()&lt;/code&gt; keep their &lt;code&gt;this&lt;/code&gt; property bound to the controller object, instead of the context for the event that called it.&lt;/li&gt;

&lt;li&gt;It provides a straightforward interface to pool your event bindings in a single location.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The syntax is straightforward: The first argument is the name of the event that should be listened for. This uses the jQuery convention for event names (&lt;code&gt;onClick&lt;/code&gt; becomes &lt;code&gt;click&lt;/code&gt;, &lt;code&gt;onBlur&lt;/code&gt; becomes &lt;code&gt;blur&lt;/code&gt;, etc). The second argument is the CSS selector for the element(s) you want a callback bound to. And the third argument is the function callback you want to pass in. For the sake of keeping things clean, I specify my event handlers on the prototype of the controller itself and pass those in. There&amp;#8217;s nothing that says you can&amp;#8217;t specify the function inline, if you so desire. Do note, though, that &lt;code&gt;this&lt;/code&gt; will be bound to the enclosing controller regardless.&lt;/p&gt;

&lt;p&gt;One last interesting (and important) detail: event callbacks bound using &lt;code&gt;addAction()&lt;/code&gt; will only be triggered when the event occurs on elements &lt;em&gt;in the subset of the DOM owned by the controller&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So if, for example, you have several controllers in a given page that each expose &amp;#60;a&amp;#62; elements that all have the &lt;code&gt;foo&lt;/code&gt; class, then a call to &lt;code&gt;addAction(&amp;#39;click&amp;#39;, &amp;#39;a.foo&amp;#39;, this.someCallback);&lt;/code&gt; will only trigger the &lt;code&gt;this.someCallback&lt;/code&gt; function for clicks on those links in the view generated by the controller. Nifty, eh?&lt;/p&gt;

&lt;p&gt;Looking at the next chunk of JavaScript in our &lt;code&gt;HelloWorldController&lt;/code&gt; example, we have:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='nx'&gt;global&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;HelloWorldController&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;Machine&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Controller&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;hw&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;global&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;HelloWorldController&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here, we see that &lt;code&gt;Machine.Controller&lt;/code&gt; uses the usual prototypical inheritance found in JavaScript. It was originally based on John Resig&amp;#8217;s &amp;#8220;Simple JavaScript Inheritance&amp;#8221; model but was subsequently converted to use the more common prototype model. After that, you can see that we assign &lt;code&gt;HelloWorldController&lt;/code&gt;&amp;#8217;s prototype to a simple, local variable called &lt;code&gt;hw&lt;/code&gt; for convenience. This is to merely save keystrokes. It isn&amp;#8217;t such a big time-saver for simple controllers like this one but, if your controller had more functions attached to its prototype, this sort of thing becomes more valuable.&lt;/p&gt;

&lt;p&gt;Secondarily, it&amp;#8217;s also useful to declare the &amp;#8220;public&amp;#8221; functions and properties for a Controller, while allowing you to create functions that aren&amp;#8217;t attached to it and keep those as &amp;#8220;private&amp;#8221;, if that&amp;#8217;s your thing.&lt;/p&gt;

&lt;p&gt;And finally, we have:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='nx'&gt;hw&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onClickerDivClick&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='c1'&gt;// &amp;#39;this&amp;#39; is always bound to the controller object&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;setView&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;viewLeft&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;clickCount&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;viewRight&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;render&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// refresh the domRoot property&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is the callback that was passed-in to &lt;code&gt;addAction()&lt;/code&gt; in our constructor function. It is a typical event-handler callback, with the event information as the sole argument to the function. This may or may not be useful to you and you can omit it if you want to. As is indicated in the comment, &lt;code&gt;this&lt;/code&gt; is bound to the enclosing controller. This means that we have access to any stateful information contained therein (&lt;code&gt;clickCount&lt;/code&gt;, in this case).&lt;/p&gt;

&lt;p&gt;The callback increments the &lt;code&gt;clickCount&lt;/code&gt; property by one and then calls &lt;code&gt;setView()&lt;/code&gt; with the same &lt;code&gt;viewLeft&lt;/code&gt; and &lt;code&gt;viewRight&lt;/code&gt; variables used in the constructor, but with the newly incremented &lt;code&gt;clickCount&lt;/code&gt;. If we were using a more sophisticated rendering scheme, we would merely modify the controller&amp;#8217;s &lt;code&gt;model&lt;/code&gt; property and let that &amp;#8220;trickle down&amp;#8221; to the ViewRenderer. In this case, the call to &lt;code&gt;setView()&lt;/code&gt; would go away and the subsequent call to &lt;code&gt;render()&lt;/code&gt; will be all that would be needed to update the DOM. But, since we&amp;#8217;re using the simplest possible approach to specifying a view in this example, we have to update the view&amp;#8217;s markup ourselves via &lt;code&gt;setView()&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id='the_finished_product'&gt;The finished product&lt;/h3&gt;

&lt;p&gt;You can see the complete example &lt;a href='/example/hwc/index.html'&gt;here&lt;/a&gt;! It is a pretty contrived example but, if you have dealt with complex client-side logic before, the advantages are obviously (in my opinion).&lt;/p&gt;

&lt;h3 id='conclusion'&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;In this post, we covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The contents of the &lt;code&gt;HelloWorldController.js&lt;/code&gt; file that is first mentioned in &lt;a href='/javascript/mvc/2010/02/17/An-Introduction-To-Machine-Controller.html'&gt;Part 1&lt;/a&gt; of this series. A typical &lt;code&gt;Machine.Controller&lt;/code&gt;-derived object contains:&lt;/li&gt;

&lt;li&gt;A constructor function, with the first statement in it being a call to &lt;code&gt;init()&lt;/code&gt;. This does the internal setup for &lt;code&gt;Machine.Controller&lt;/code&gt; and should always be called first. Also don&amp;#8217;t replace it in the prototype unless you know what you&amp;#8217;re doing.&lt;/li&gt;

&lt;li&gt;In additional to any per-controller setup, a constructor will usually contain:&lt;/li&gt;

&lt;li&gt;A call to &lt;code&gt;setView()&lt;/code&gt; to designate the view rendering scheme for this controller. You can either pass in static text (which you need to update yourself via calls to &lt;code&gt;setView()&lt;/code&gt;) or designate a pre-registered ViewRenderer to handle the details for you. The details of how ViewRenderers work is for another post.&lt;/li&gt;

&lt;li&gt;One-or-more calls to &lt;code&gt;addAction()&lt;/code&gt; to bind event callbacks to elements in the subset of the DOM owned by the controller.&lt;/li&gt;

&lt;li&gt;Each call t &lt;code&gt;addAction()&lt;/code&gt; is going to need a corresponding callback. &lt;code&gt;this&lt;/code&gt; in the callback will correspond to the enclosing controller, giving you access to state information.&lt;/li&gt;

&lt;li&gt;Call &lt;code&gt;render()&lt;/code&gt; when you want to update the markup in the &lt;code&gt;domRoot&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stayed tuned for Part 3, where I&amp;#8217;ll go over one of the most useful architectural features of &lt;code&gt;machine-controller.js&lt;/code&gt;: ViewRenderers. Until then, take it easy!&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>An Introduction To machine.javascript</title>
      <link href="http://olsonjeffery.github.com/javascript/mvc/2010/02/17/An-Introduction-To-Machine-Controller.html"/>
      <updated>2010-02-17T00:00:00-08:00</updated>
      <id>http://olsonjeffery.github.com/javascript/mvc/2010/02/17/An-Introduction-To-Machine-Controller</id>
      <content type="html">&lt;p&gt;This is the first in a series of [hopefully many] blog posts on the topic of &lt;a href='http://github.com/machine/machine.javascript'&gt;machine.javascript&lt;/a&gt;, an open source framework for helping developers create testable, deployable and well-factored UIs on the client in JavaScript. It covers some of my exposure to tools in this space and an overview of what &lt;code&gt;machine.javascript&lt;/code&gt; consists of and how to use it. This post is tightly coupled to &lt;a href='/javascript/mvc/2010/02/18/An-Introduction-To-Machine-Controller-Part-2.html'&gt;Part 2&lt;/a&gt; in the series and each should not be read without considering the context of the other.&lt;/p&gt;

&lt;h3 id='my_experience_with_javascript_mvc'&gt;My experience with JavaScript MVC&lt;/h3&gt;

&lt;p&gt;As I&amp;#8217;ve gotten involved in my professional and personal capacities with rich, client-based UIs in te browser, one of the most indispensible patterns I&amp;#8217;ve had at my disposal would have to be &amp;#8220;MVC&amp;#8221;. I put MVC in scare-quotes because it is, in my opinion, one of the most overloaded terms in software development today. The most basic, valid definition for MVC in the context of this post, though, is to say that it is about creating patterns for application development that deliberately seek to segregate control and rendering logic which are optimized for the particular platform (in this case, JavaScript in the browser).&lt;/p&gt;

&lt;p&gt;With this in mind, the &lt;a href='http://www.eleutian.com'&gt;Eleutian&lt;/a&gt; team (notably Daniel Tabuenca) produced a kick-ass library that I always felt really attacked the problem of building complex, client-side applications in JavaScript in an effective, sensical fashion. It could have to do with the fact that this framework was the first I ever used in this particular solution/problem space, but I&amp;#8217;ve reviewed/experimented with several other frameworks since and never really liked any of them. Some reasons for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many of them (&lt;a href='http://www.javascriptmvc.com'&gt;JavaScript MVC&lt;/a&gt; in particular) are &lt;em&gt;very&lt;/em&gt; heavy, requiring things like having Rhino installed to do command-line scaffolding (wtf?!)&lt;/li&gt;

&lt;li&gt;Others are tightly coupled in the manner in which view/template rendering is handled. Modern JavaScript development in the browser is interesting because there are several different ways to &amp;#8220;get there&amp;#8221;, when it comes to how you programatically display content. Options include, but aren&amp;#8217;t limited to: Direct DOM manipulation via jQuery/other frameworks ( $(&amp;#8216;#container&amp;#8217;).append(&amp;#8217;&amp;#60;div&amp;#62;&amp;#60;/div&amp;#62;&amp;#8217;); ), JavaScript Templating (EJS, Pure, etc) and/or tools/plugins that take structured data and directly output markup (jQuery.datatables, jqplot, etc). Eleutian&amp;#8217;s framework was originally tightly coupled to EJS for template rendering, but this has since changed (as I will explain shortly).&lt;/li&gt;

&lt;li&gt;Some frameworks get the abstraction wrong, in my opinion. The scope of what I, the developer, want when doing client-side work is pretty narrow: aggregate events around some subset of the DOM and have a uniform way of manipulating/regenerating the markup in that subset in response to said events. The premise of &amp;#8220;smart models&amp;#8221; in an isolated browser environment (wiring up AJAX calls to the server) is way too much abstraction for me and, in the laissez-faire world of JavaScript, strikes me as very open to &amp;#8220;entering a world of pain&amp;#8221; scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From my time with the &lt;a href='http://www.eleutian.com/'&gt;Eleutian&lt;/a&gt; team, one of the things I missed the most was the MVC framework I had used when I worked there. And while I can by no means take credit for creating or expanding &lt;code&gt;machine.javascript&lt;/code&gt;, I can definitely say that I was able to harass Aaron Jensen and Dan into releasing the libraries in question as OSS (although they claim they were going to do it anyways). Hence, the &lt;a href='http://github.com/machine/machine.javascript'&gt;github repo&lt;/a&gt; and this blog post.&lt;/p&gt;

&lt;h3 id='what_is_machinejavascript'&gt;What is machine-javascript?&lt;/h3&gt;

&lt;p&gt;At the heart of it, machine-javascript consists of two components, each an individual javascript file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;machine-includer.js&lt;/code&gt; &amp;#8211; Specifies a &amp;#8220;script loader&amp;#8221; that works in a &amp;#8220;nested&amp;#8221; fashion (as opposed to &amp;#8220;flat&amp;#8221; includers like &lt;a href='http://www.labjs.com'&gt;LABjs&lt;/a&gt;). It allows you to specify your dependencies in a manner similar to how you would in server-side code and then load it all (in a cascading fashion) during the page load. Like other script loaders, it is often not practical for performance-critical/production uses, but is great for dev/debug work and provides a critical advantage: The nested, per-file &lt;code&gt;include()&lt;/code&gt; statements provide get hints for a recursive script parser to build a list of dependencies which you could use to create a single, bundled for your markup. The include() function that it creates can handle both external script loads (when passed a string) or evaluate functions passed to it. Regardless of which, both are evaluated in order of specification based upon the dependency tree created when looking at how invokations of include() are specified in files and the same external script is only loaded once.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;machine-controller.js&lt;/code&gt; &amp;#8211; Contains a prototype for the &lt;code&gt;Machine.Controller&lt;/code&gt; object, which can be inherited in your &amp;#8220;controllers&amp;#8221; and provides a straightforward framework for specifying events and rendering logic on a piece of the DOM that the controller will be associated with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Leveraging these two components, I will demonstrate how to create a simple controller with machine-javascript.&lt;/p&gt;

&lt;h3 id='a_simple_example'&gt;A Simple Example&lt;/h3&gt;

&lt;p&gt;Let&amp;#8217;s consider the simplest possible &lt;em&gt;hello world&lt;/em&gt; case, utilizing machine-javascript.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;    &lt;span class='nt'&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello, world!&lt;span class='nt'&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;script &lt;/span&gt;&lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;src=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;machine-includer.js&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In our page&amp;#8217;s &amp;#60;head&amp;#62; tag section, we have a single script include. All we are going to load in this page in an explicit, static fashion is the &lt;code&gt;machine-includer.js&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;Somewhere down in the &amp;#60;body&amp;#62;, we have a chunk of markup that looks something like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;    &lt;span class='nt'&gt;&amp;lt;script &lt;/span&gt;&lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='c1'&gt;// this is the initial setup for machine.includer&lt;/span&gt;
      &lt;span class='nx'&gt;Machine&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Includer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;configure&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='nx'&gt;scriptLocations&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;.*&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;}});&lt;/span&gt;
      
      &lt;span class='c1'&gt;// include our external dependencies&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;jquery.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;HelloWorldController.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      
      &lt;span class='c1'&gt;// and kick it all off once the page loads&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
          &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;hw&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;HelloWorldController&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
          &lt;span class='nx'&gt;hw&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;render&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
          &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#container&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;hw&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;domRoot&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
      &lt;span class='p'&gt;});&lt;/span&gt;

      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;load&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;    &lt;span class='nt'&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;div&lt;/span&gt; &lt;span class='na'&gt;id=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So this is interesting; We do some inital configuration for &lt;code&gt;machine-includer.js&lt;/code&gt;, then load our external scripts that the page is dependant upon and then instantiate an object (defined in an external dependency) and attach one of its properties to the DOM via jquery&amp;#8217;s &lt;code&gt;append()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s take each signifigant chunk on its own&amp;#8230;&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='c1'&gt;// this is the initial setup for machine.includer&lt;/span&gt;
      &lt;span class='nx'&gt;Machine&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Includer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;configure&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='nx'&gt;scriptLocations&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;.*&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;}});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is the only initialization call needed to set up &lt;code&gt;machine.includer.js&lt;/code&gt;; after this, you can safely call &lt;code&gt;include()&lt;/code&gt;. The hash that is passed into &lt;code&gt;configure()&lt;/code&gt; has one notable parameter: &lt;code&gt;scriptLocations&lt;/code&gt;. It is a series of pairs that say to the includer, &amp;#8220;Hey, if you encounter the regex pattern in the left component in an includer URL, please prepend it with the contents of the right component.&amp;#8221; This means that, if you had some hinting from the server based on environment (dev, production, etc), you could configure &lt;code&gt;machine-includer.js&lt;/code&gt; to mangle the script loads done via &lt;code&gt;include()&lt;/code&gt; so they actually called out to an external CDN or local folder, depending on the runtime environment.&lt;/p&gt;

&lt;p&gt;For example, consider if your static content was delivered by a CDN like Cloudfront in your production setting, but was served from a local Scripts directory in the same web server when run in the dev/test environments.&lt;/p&gt;

&lt;p&gt;In an ASP.NET MVC WebForms template with a strongly-typed view that had an Environment property hooked up to some mythical enum or the like (this applies just as easily to other server frameworks) the server-side template might look like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='c1'&gt;// this is the initial setup for machine.includer&lt;/span&gt;
      &lt;span class='o'&gt;&amp;lt;%&lt;/span&gt; 
        &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;prefix&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;Model&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Env&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='nx'&gt;Env&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Production&lt;/span&gt; &lt;span class='o'&gt;?&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;http://s3.yourdomain.com/path/&amp;#39;&lt;/span&gt;
          &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/Scripts/&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='o'&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class='nx'&gt;Machine&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Includer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;configure&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='nx'&gt;scriptLocations&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;^static.*&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;lt;%= prefix %&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;}});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this way, you can drive how your scripts are loaded at runtime with a simple, per-page check to the ambient environment.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='c1'&gt;// include our external dependencies&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;jquery.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;HelloWorldController.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this chunk of code, we are declaring our dependencies for this page, utilizing calls to the &lt;code&gt;include()&lt;/code&gt; function with strings for the paths to the files in question. As with &amp;#60;script&amp;#62; tags, you can pass in absolute or relative paths. But, as noted above with the &lt;code&gt;scriptLocations&lt;/code&gt; configuration, you can also establish conventions (driven by server-side configuration) for mangling the path passed to &lt;code&gt;include()&lt;/code&gt; to account for special cases.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='c1'&gt;// and kick it all off once the page loads&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
          &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;load&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; &lt;span class='c1'&gt;// actually loads the scripts&lt;/span&gt;

          &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;hw&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;HelloWorldController&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
          &lt;span class='nx'&gt;hw&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;render&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
          &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#container&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;hw&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;domRoot&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
      &lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this block we actually have some running javascript code, passed within a function to an invokation of &lt;code&gt;include()&lt;/code&gt;. One thing worth pointing out, here, is that (when taken into context with the previous block where we used &lt;code&gt;include()&lt;/code&gt; to load external scripts) calls to &lt;code&gt;include()&lt;/code&gt; are never nested within the scope of a single file, they always appear serially. Now, when passing a string URL to &lt;code&gt;include()&lt;/code&gt;, there will of course be calls to &lt;code&gt;include()&lt;/code&gt; in the file indicated by the URL, but there are never calls to &lt;code&gt;include()&lt;/code&gt; within the scope of a function passed to an existing call. Please remember this when writing your code or it&amp;#8217;ll fail and you&amp;#8217;ll be left scratching your head (speaking from experience, here).&lt;/p&gt;

&lt;p&gt;Back to the function itself, you can see that it consists of a callback for jQuery&amp;#8217;s &amp;#8220;onReady&amp;#8221; event binding using the &lt;code&gt;$(function() { });&lt;/code&gt; convention. When the document is ready (the DOM is completely loaded, mainly), we create an instance of a &lt;code&gt;HelloWorldController&lt;/code&gt;, which we can assume was imported in a previous call to &lt;code&gt;include()&lt;/code&gt; (the code for &lt;code&gt;HelloWorldController&lt;/code&gt; will be shown shortly). There is some setup that happens in the course of &lt;code&gt;HelloWorldController&lt;/code&gt;&amp;#8217;s initialization, which allows us to then invoke its &lt;code&gt;render()&lt;/code&gt; function. This is a function defined in the &lt;code&gt;Machine.Controller&lt;/code&gt; prototype that leverages some configuration done during initialization and renders the controller&amp;#8217;s desired markup in its &lt;code&gt;domRoot&lt;/code&gt; property. Subsequent calls to &lt;code&gt;render()&lt;/code&gt; will update the markup stored there.&lt;/p&gt;

&lt;p&gt;Finally we, using jQuery&amp;#8217;s &lt;code&gt;append()&lt;/code&gt; function and attach our controller&amp;#8217;s newly available &lt;code&gt;domRoot&lt;/code&gt; to an element with an id of &lt;code&gt;container&lt;/code&gt; (shown in the complete example above).&lt;/p&gt;

&lt;p&gt;One of the fringe benefits of &lt;code&gt;Machine.Controller&lt;/code&gt; is that subsequent calls to &lt;code&gt;render()&lt;/code&gt; (outside of or within &lt;code&gt;HelloWorldController&lt;/code&gt;) will automatically update the domRoot &lt;em&gt;and&lt;/em&gt; be reflected in the DOM without having call to &lt;code&gt;append()&lt;/code&gt; on your container element again. This also applies to events bound from within &lt;code&gt;HelloWorldController&lt;/code&gt; using &lt;code&gt;Machine.Controller&lt;/code&gt;&amp;#8217;s syntax for doing so.&lt;/p&gt;

&lt;p&gt;Going back to the complete example above, let&amp;#8217;s examine, once again, the external scripts loaded as dependencies for the page.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='c1'&gt;// include our external dependencies&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;jquery.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;HelloWorldController.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can guess pretty easily what&amp;#8217;s within &lt;code&gt;jquery.js&lt;/code&gt;, and since it was needed in order to append our instance of &lt;code&gt;HelloWorldController&lt;/code&gt; to the container &amp;#60;div&amp;#62; we loaded it up via &lt;code&gt;include()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But what about &lt;code&gt;HelloWorldController.js&lt;/code&gt;? This contains the definition for our controller, the contents of which will be shown in &lt;a href='/javascript/mvc/2010/02/18/An-Introduction-To-Machine-Controller-Part-2.html'&gt;Part 2&lt;/a&gt; of this series.&lt;/p&gt;

&lt;p&gt;Finally, we have:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;      &lt;span class='nx'&gt;include&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;load&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This actually triggers the script load and should come after all of the previous calls to &lt;code&gt;include()&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id='conclusion'&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;In this post, we covered the following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A brief overview of my anecdotal introduction to MVC in JavaScript and my personal opinions and nags about it.&lt;/li&gt;

&lt;li&gt;A rough description of the two pieces that make up &lt;code&gt;machine-javascript&lt;/code&gt;: &lt;code&gt;machine-includer.js&lt;/code&gt; and &lt;code&gt;machine-controller.js&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;A &amp;#8220;hello world&amp;#8221; example was shown of the HTML markup for an example page that uses the includer and controller. The contents of the actual controller script have not yet been shown (and are saved for part 2 in this series).&lt;/li&gt;

&lt;li&gt;Some exposure to the semantics of using &lt;code&gt;machine-includer.js&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;Shows how a finished controller is instantiated and attached to the DOM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this post has been enlightening for you, the reader. Parts 1 and 2 really belong together (as each is uselss without the other), but if combined it&amp;#8217;d be a classic &lt;a href='http://www.urbandictionary.com/define.php?term=tl%3Bdr'&gt;tl;dr&lt;/a&gt; article. I thought that was a good place to split them up. In any case, please continue on to &lt;a href='/javascript/mvc/2010/02/18/An-Introduction-To-Machine-Controller-Part-2.html'&gt;Part 2&lt;/a&gt; for the rest of the story!&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>I am ALT.NET Pursefight!</title>
      <link href="http://olsonjeffery.github.com/drama/2010/01/15/I-Am-AltNet-Pursefight.html"/>
      <updated>2010-01-15T00:00:00-08:00</updated>
      <id>http://olsonjeffery.github.com/drama/2010/01/15/I-Am-AltNet-Pursefight</id>
      <content type="html">&lt;p&gt;This post is only of use to those who were monitoring/involved in the ALT.NET &amp;#8220;movement&amp;#8221; circa 2007 and 2008. It was an age of high adventure where a desire, predicated on the assumption that the status quo in terms of Microsoft-driven guidance on Patterns &amp;amp; Practices and tooling was not leading to the creation of Good Software in the short and long terms, had given rise to a set of &amp;#8220;alternative&amp;#8221; orthadoxies meant to improve the lot of developers.&lt;/p&gt;

&lt;p&gt;If this situation doesn&amp;#8217;t mean anything to you, or if you arrived &amp;#8220;after the party&amp;#8221;, then this post has little value.&lt;/p&gt;

&lt;p&gt;Recently, I decided to write the following email to one Scott Bellware:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I&amp;#8217;ve been wanting to write you to get something off of my chest: I am the sole person behind the ALT.NET Pursefight blog (since discontinued), twitter account etc. It&amp;#8217;s something that&amp;#8217;s been sticking in my craw for some time and I&amp;#8217;m only now getting around to rectifying it. My apologies for my laziness on this. We&amp;#8217;ve only met once (at the &amp;#8220;Night of BDD&amp;#8221; event that you attended in Seattle where you sat there and got verbally abused by Jim Newkirk and Charlie Poole for two hours). We don&amp;#8217;t have any kind of relationship, professional or otherwise, but it&amp;#8217;s something that I&amp;#8217;ve wanted to tell you, nonetheless.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;I&amp;#8217;ve grown to respect you over time (during and after my period operating under the ALT.NET Pursefight monicker). Not just for your community work, but for striking out as an independent and pretty much putting your money where your mouth is. I figure that I would, in fact, have a lot to learn from you (by virtue of your longevity in the industry alone) and were I ever to actually contact you to try and dig out some of that knowledge for my own benefit or the benefit of the community at-large, I&amp;#8217;d be misrepresenting myself if I didn&amp;#8217;t make this disclosure. As far as my respect goes, all I can say is: you were pretty much proven right on every count with regards to your insights as to the trajectory of the &amp;#8220;ALT.NET movement&amp;#8221;, as well as on numerous technical issues: EF is indeed a travesty, amongst other things. I also agree that education is the way forward to &amp;#8220;raise the water line&amp;#8221; for the community as a whole in terms of bringing the average level of competency up for the aggregate of developers but, having experience with the &amp;#8220;minister to the heathens&amp;#8221; approach to outreach/education, I still think the process needs some work (sadly, most of the issues I observed came from trying to motivate the &amp;#8220;knowledgable&amp;#8221; people to give up their time and put aside profit/renown motives to engage in this public service). I am also, perhaps unlike you, quite dubious about the whole Software Craftsmanship thing, even though its proponents seemed to have ( perhaps from observing ALT.NET&amp;#8217;s fate) hedged their bets a bit and reduced it to a series of bland &amp;#8220;we care more&amp;#8221; truisms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;As for why I did the whole ALT.NET Pursefight thing in the first place, I thought it was needed at the time. And perhaps there was some capacity where it could have been useful or performed some function of value for the community; If that was the case, I feel like I utterly failed in it and, as such, just gave up on the whole thing. I apologize for the ad hominem attacks against you. If you still want to kick my ass, I guess you now know with whom you can make arrangements to try and do so next time you&amp;#8217;re in Seattle. In all honesty, you&amp;#8217;re the only person that I&amp;#8217;ve disclosed this information to (besides one personal friend who knew from the start), as I feel like you&amp;#8217;re the only person who bore any real amount of non-substantive criticism from me. What you do with it (wreck my professional persona, firebomb my house, etc) is up to you, I guess. That being said, I don&amp;#8217;t really feel like I have any real &amp;#8220;need&amp;#8221; to have a public coming out where I can announce to the world that I was ALT.NET Pursefight; it wouldn&amp;#8217;t achieve anything. I don&amp;#8217;t need any boost from the pseudonym to properly heckle and ridicule any of the current crop of self-aggrandizing idiots and their enablers in the community. And I doubt that I really fall into line, in retrospective, with any of the opinions expressed (I don&amp;#8217;t think I ever really took any sides, just threw tomatoes at others from safe cover) as ALT.NET Pursefight and would have to defend were I do to claim the identity. Chalk it up to youth and stupidity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;Anyways, I just wanted to share this with you so that, if I ever do meet you, I can at least buy you a beer and not feel like a douchebag while doing so. I can&amp;#8217;t expect you to want to &amp;#8220;forgive&amp;#8221; (is that even the right word?) me or what-have-you, but at least you&amp;#8217;ll know that the person who said stupid things eventually came clean.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To which he replied.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The value in making this disclosure public would be in giving the community one more example of public integrity. Every exemplary action that goes unseen doesn&amp;#8217;t contribute as much as it can. Although I appreciate starting my week with your example of courage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why did I take up the ALT.NET Pursefight! name? I can&amp;#8217;t say for sure, but I think it boils down to something like: I lacked the technical chops, at the time, to enter into and interact with the community as peer, so I assumed an anonymous personality and begin a meta-commentary on the &amp;#8220;community&amp;#8221; and its personalities. In a way, I was catering to a specific sub-group that wanted to heckle and redicule the &amp;#8220;prevailing personalities&amp;#8221; of the ALT.NET community (who, warts aside, were providing value for said community). But, regardless of whether or not I was just &amp;#8220;giving them what they wanted&amp;#8221;, I have to take personality responsibility for my actions.&lt;/p&gt;

&lt;p&gt;You can gather from the email that I was reluctant to make the public disclosure that I am making now. But Scott makes a good point on the value of doing so, the merits of which I can add nothing to.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t feel like I owe the &amp;#8220;community&amp;#8221; as an abstract any apology; It has soldiered onwards, marching blandly towards its own irrelevancy without any help/hinderance from me personally. Some good things have come out of it (although it&amp;#8217;s perhaps fallacious and premature to assume the correlation of Microsoft&amp;#8217;s changing stance towards OSS in the dev community was caused by ALT.NET the movement&amp;#8211; Although I&amp;#8217;m sure many of the prominent OSS people that they took &amp;#8220;out of circulation&amp;#8221; has helepd in changing minds internally). That being said, I do owe apologies to many individuals within the community, about whom I said stupid and unjustified things. To them: I am sorry.&lt;/p&gt;

&lt;p&gt;The future of &amp;#8220;progressive&amp;#8221; techniques in the .NET developer community still hangs in the balance, as far as I&amp;#8217;m concerned. Microsoft continues to crank out vendor lock-in focused patterns and APIs, especially if you take into context the possibility of the &amp;#8220;Silverlight for every platform&amp;#8221; mutterings and the whole EF/One-data-binding-to-rule-them-all talk coming from some bloggers. I personally feel like their open source overtures are a short/mid-term strategy to win ethical boons while still slipping in their typically sub-standard solutions and betting that the mediocre developers and managers will pick the easy wrong, rather than the hard right. To me, that&amp;#8217;s what their Open Source support is: A hedge. Whether I&amp;#8217;m correct in that assessment or not is something that history will have decide.&lt;/p&gt;

&lt;p&gt;We have to recognize this for what it is and address it as such in the sunlight of public discourse and intellectual honesty; Anonymous sniping and heckling isn&amp;#8217;t the solution. This is where I was wrong in the past and this blog post is a step towards correcting that mistake.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Saber - a Newspeak web framework</title>
      <link href="http://olsonjeffery.github.com/newspeak/2009/11/06/Saber-a-Newspeak-web-framework.html"/>
      <updated>2009-11-06T00:00:00-08:00</updated>
      <id>http://olsonjeffery.github.com/newspeak/2009/11/06/Saber-a-Newspeak-web-framework</id>
      <content type="html">&lt;p&gt;I&amp;#8217;m very pleased to announce the creation of yet another web framework, although it is the first (that I know of) for the &lt;a href='http://newspeaklanguage.org'&gt;Newspeak&lt;/a&gt; platform. It started out as an intellectual exercise to explore Newspeak and some of it&amp;#8217;s reflective capabilities and idiosyncracies (specifically the pervasive class nesting). It was a very interesting and enjoyable development experience, to be sure (although it wasn&amp;#8217;t without its own gotcha moments and difficulties). Prior to this project, I played with Newspeak a bit at the time of the first release in late February. Besides that, my only experience with this style of development is some recreational programming with Squeak (I worked through about two-thirds of the &lt;a href='http://squeak.preeminent.org/tut2007/html/'&gt;laser-game&lt;/a&gt; tutorial). Newspeak is a very young, yet capable and robust platform and I am more than impressed with what I&amp;#8217;ve encountered so far, although a lot of its much-heralded functionality has yet to be implemented. All in good time, I suppose.&lt;/p&gt;

&lt;h3 id='saber_and_web_frameworks_in_a_historical_context'&gt;Saber and web frameworks in a historical context&lt;/h3&gt;

&lt;p&gt;Saber is a web application framework that takes a somewhat different approach to web application development and modelling from other, more popular frameworks that you may have heard of. In a way, it may be a sort of counter-evolution in terms of conceptualization of how web frameworks have been structured since Rails came on the scene.&lt;/p&gt;

&lt;p&gt;In the &lt;a href='http://en.wikipedia.org/wiki/Web_application#History'&gt;Bad Old Days&lt;/a&gt;, HTTP was used exclusively as a static content presentation protocol, where URL requests typically mapped to documents in a folder under the wwwroot of some site. When server-side technology solutions (ASP, Java Servlets, CGI, etc) became more common, it ended up being some script/code handling requests, which may or may not have been routed to a script corresponding to the URL somehow. But, with the rise of Rails and the slew of other HTTP-based &amp;#8220;MVC&amp;#8221; frameworks that have followed in its wake, we now have a popular paradigm of Controllers and Actions and the basic request-handling conventions that they bring to mind. When the need for more taxonomy beyond Controller/Action became perceived as necessary, we got things like Areas or custom routing schemes to match a request for some URL to a given action, perhaps with some parameter mapping to give the whole thing a more RESTful feel.&lt;/p&gt;

&lt;p&gt;The pitfalls of the Controller/Action modelling pattern for web frameworks is something that isn&amp;#8217;t within the scope of the topic of this post, but it suffices to say that it has become enough of a nuisance after a while for any non-trivial example application that several people have come up with alternative approaches. Foremost of these in my mind is &lt;a href='http://www.sinatrarb.com'&gt;Sinatra&lt;/a&gt;, an excellent framework that models endpoints as &amp;#8220;routes&amp;#8221; (that is, some HTTP Method/URL pair that can be matched by a request) and a block of code to handle that request when the route is matched. I have experimented a bit with porting this approach to the ASP.NET world (the results of which can be found &lt;a href='http://github.com/olsonjeffery/mercury'&gt;here&lt;/a&gt;). This approach is present in several frameworks as a &amp;#8216;first-class&amp;#8217; alternative to the Controller/Action structure so popular elsewhere (from the direct url-&amp;gt;handler WSGI mapping in Google AppEngine&amp;#8217;s &lt;a href='http://code.google.com/appengine/docs/python/gettingstarted/usingwebapp.html'&gt;webapp&lt;/a&gt; framework to &lt;a href='http://trac.caffeine-it.com/openrasta'&gt;OpenRasta&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Saber subscribes to the above request/routing-centric viewpoint, but with a twist. From the Saber README:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Essentially: Instead of artificially aggregating endpoints into a Controller/Action hierarchy, Saber lets the structure of the routing handlers becoming the organizing taxonomy for the application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To further entertain this MVC straw-man, most stereotypical MVC web frameworks reveal the intent and function of their endpoint handlers by aggregating them as actions within controllers. In some static frameworks (in Java or .NET, mostly), the aggregation is also an administrative concern for convenience when using an Inversion-of-Control scheme, leading to kludgey groupings of functionality that don&amp;#8217;t scale well, in my experience.&lt;/p&gt;

&lt;p&gt;So, how does Saber acheive this taxonomy? By using a fundamental feature of Newspeak: pervasive class nesting. In Newspeak, there is no global namespace. Practically, this means that every &amp;#8220;top-level&amp;#8221; class itself acts as a module. Within this top-level class, you can nest other classes. It seemed natural, to me, to use this approach to model a web site&amp;#8217;s request handlers, with a class called &lt;code&gt;foo&lt;/code&gt; handling requests to &lt;code&gt;/foo&lt;/code&gt;, and a class nested within that one called &lt;code&gt;bar&lt;/code&gt; handling requests to &lt;code&gt;/foo/bar&lt;/code&gt;, etc. Each of these &amp;#8220;Handler&amp;#8221; classes implements one or more methods that each correspond to an HTTP method (&lt;code&gt;onGet:&lt;/code&gt; for GET, &lt;code&gt;onPost:&lt;/code&gt; for POST, etc). These Handler methods are themselves the actual endpoints for a given request.&lt;/p&gt;

&lt;p&gt;Saber also includes a &amp;#8220;toy&amp;#8221; view rendering system, &lt;span&gt;creatively&lt;/span&gt; named SaberView.&lt;/p&gt;

&lt;h3 id='so_what_does_this_look_like'&gt;So what does this look like?&lt;/h3&gt;

&lt;p&gt;At the highest level, you have a &amp;#8220;site&amp;#8221; class that acts as a model/container for your site&amp;#8217;s definition. This site contains a few administrative things (like the name of the site for the httpd, the port, etc). Besides that, it must include a nested class called SiteRoot that inherits from SaberHandler (which is the basic route Handler class in Saber). That class itself will match on requests to the root of a site. From there, you can nest classes that match to &amp;#8220;nodes&amp;#8221; in a route request. For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+ SiteRoot
  - foo
  - baz
    - bar&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This would be an example of a taxonomy of classes that would have handlers that could potentially match requests for &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/foo&lt;/code&gt;, &lt;code&gt;/baz&lt;/code&gt; or &lt;code&gt;/baz/bar&lt;/code&gt;. Once again, a handler will only be called if it implements a method corresponding to the HTTP method of a request. So if &lt;code&gt;/baz/bar&lt;/code&gt; only implements &lt;code&gt;onPost:&lt;/code&gt;, then a GET request to &lt;code&gt;/baz/bar&lt;/code&gt; will return a 404.&lt;/p&gt;

&lt;h3 id='specialized_handlers'&gt;Specialized handlers&lt;/h3&gt;

&lt;p&gt;But vanilla route handling isn&amp;#8217;t all that Saber does. It handles a number of &amp;#8220;must have&amp;#8221; features for routing-centric web frameworks, including: a NotFound handler scheme, &amp;#8216;parameter&amp;#8217; handlers and static file serving.&lt;/p&gt;

&lt;h4 id='not_found_handlers'&gt;Not found handlers&lt;/h4&gt;

&lt;p&gt;By default, Saber will return a generic 404 response if a request&amp;#8217;s url cannot be matched to a handler. Optionally, you can specify a special handler that inherits from &lt;code&gt;SaberNotFoundHandler&lt;/code&gt; that will be processed when a request cannot be matched to an existing Handler. Otherwise, it works just like any other handler with the &lt;code&gt;onGet:&lt;/code&gt;, &lt;code&gt;onPost:&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h4 id='parameter_handlers'&gt;Parameter handlers&lt;/h4&gt;

&lt;p&gt;Saber allows specifying a Handler nested within another one, inheriting from &lt;code&gt;SaberParameterHandler&lt;/code&gt; to be used as a special-case parameter matching handler. That is, given the following taxonomy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+ SiteRoot
  - foo
  - baz
    - bar
    - nameParam&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case, the &lt;code&gt;nameParam&lt;/code&gt; class is a class that inherits from &lt;code&gt;SaberParameterHandler&lt;/code&gt;. What this means is that, at request time, if the request url doesn&amp;#8217;t match to any of the other &amp;#8216;sibling&amp;#8217; handlers at the same level as the parameter handler, then the parameter handler itself will be matched. This way, it could be used as a catch-all and won&amp;#8217;t interfere with handlers at the same level. This means that requests for &lt;code&gt;/baz/bar&lt;/code&gt; would match to the &lt;code&gt;bar&lt;/code&gt; class, but requests for &lt;code&gt;/baz/john&lt;/code&gt; or somesuch would match to the &lt;code&gt;nameParam&lt;/code&gt; handler, since there is no other handler that would match the request, otherwise. Also, the value of the request (in the case of the previous example &amp;#8216;john&amp;#8217;) will be stored within the requests query fields with &lt;em&gt;the name of the handler&lt;/em&gt; as the key.&lt;/p&gt;

&lt;p&gt;Naturally, this means that only a single &lt;code&gt;SaberParameterHandler&lt;/code&gt;-inheriting class can be nested within a group of sibling handlers. Besides the above issues, the handler behaves exactly like a normal handler, including allowing other handlers to be nested within it.&lt;/p&gt;

&lt;h4 id='serving_static_content'&gt;Serving static content&lt;/h4&gt;

&lt;p&gt;And what web framework would be complete without a means with which to serve up CSS, JavaScript, etc? Saber allows for classes that inherit from &lt;code&gt;SaberStaticFileHandler&lt;/code&gt; that are nested with the SiteRoot to be mapped to physical locations on the filesystem (exposed by overriding the &lt;code&gt;documentRoot&lt;/code&gt; method on the class) and mapped to the class&amp;#8217; name. So a class inheriting from &lt;code&gt;SaberStaticFileHandler&lt;/code&gt; named &lt;code&gt;static&lt;/code&gt; and pointing to a location on the filesystem would be matched. A request for &lt;code&gt;/static/style.css&lt;/code&gt; would be matched to whatever path was specified in the &lt;code&gt;documentRoot&lt;/code&gt; with &lt;code&gt;style.css&lt;/code&gt; appended to the end.&lt;/p&gt;

&lt;h3 id='whats_notsogreat_about_saber_right_now'&gt;What&amp;#8217;s not-so-great about Saber, right now?&lt;/h3&gt;

&lt;p&gt;First and foremost: I&amp;#8217;m not terribly happy with the rather &amp;#8220;minimalistic&amp;#8221; view engine. It has two very useful features (value substition and block inheritance), but that&amp;#8217;s it. I, personally, am a very big fan of pushing as much work onto the client javascript as possible, using server-side views to deliver JSON and that&amp;#8217;s it, if possible. But there are always some situations where it makes sense to just do the rendering on the server (like some non-interactive reporting that won&amp;#8217;t feature any AJAX callbacks after the initial request). With this in mind, a slighlty more robust solution with conditionals, looping and more sophisticated value substitution (that allows passing in actual objects instead of just strings) would be nice, longterm.&lt;/p&gt;

&lt;p&gt;Also, Saber is currently tightly coupled to the underlying platform for the Newspeak environment: Squeak. This isn&amp;#8217;t a bad thing necessarily, but eventually Newspeak will move beyond this and Saber currently uses HttpService, which is used in &lt;a href='http://www.seaside.st/'&gt;Seaside&lt;/a&gt; (not to mention several collection primitives, HttpRequest/Response, etc). I&amp;#8217;m glad that the Squeak libraries are there, as they allowed me to cut some corners and concentrate on features instead of low-level plumbing, but these things will have to be replaced longterm. Whether or not Saber survives long enough to see that day is another question.&lt;/p&gt;

&lt;p&gt;Another nagging issue is that Saber doesn&amp;#8217;t support multiple sites in the same instance using the HTTP 1.1 host header. This is supported in the underlying httpd from Squeak, but isn&amp;#8217;t something that I&amp;#8217;ve gotten around to implementing.&lt;/p&gt;

&lt;p&gt;Overall, I tried to keep the scope of the project somewhat narrow (I&amp;#8217;ve only been working on it for a few weeks and I&amp;#8217;m quite pleased with the progress I&amp;#8217;ve made). I mostly wanted to get the project out &amp;#8220;into the wild&amp;#8221; in order to get some feedback on the viability of this approach. I wouldn&amp;#8217;t really recommend the nested class approach other platforms like Java or .NET, even though they support this feature. Alot of what makes nested classes appealing in Newspeak is that it&amp;#8217;s a first-class concern and is built into the IDE, so there&amp;#8217;s some tooling to reduce the friction. I wouldn&amp;#8217;t say that this same tooling/mindset exists for other platforms.&lt;/p&gt;

&lt;h3 id='how_to_see_saber_in_action'&gt;How to see Saber in action&lt;/h3&gt;

&lt;p&gt;The README.md in the &lt;a href='http://github.com/olsonjeffery/saber'&gt;Saber repository&lt;/a&gt; has some pointers on how to get started, should you be so inclined.&lt;/p&gt;

&lt;h3 id='conclusion'&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;d like to give a big thanks to the motivating people behind this project: The Newspeak team, for conceiving of this awesome vision and delivering a working prototype for people like me to hack around with. I wish this project the best and hope to find a way to get involved with helping move things forward, longterm. Also, all of the people who aren&amp;#8217;t satisfied the state of things in terms of software abstractions and patterns in general. Whether you&amp;#8217;re a pathological tinkerer like me or a more pragmatically-minded person, it&amp;#8217;s the unreasonable nerd who isn&amp;#8217;t satisfied with the reigning paradigm that actually moves the ball forward.&lt;/p&gt;

&lt;p&gt;Please note that I don&amp;#8217;t actually consider Saber to be a part of the canon of earth-shattering software innovations or theory; I just like to speak in broad, sweeping terms.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Thinking about a "Step 2" for Context/Specification-style testing</title>
      <link href="http://olsonjeffery.github.com/bdd/testing/2009/10/11/Thinking-about-step-2-for-context-spec-testing.html"/>
      <updated>2009-10-11T00:00:00-07:00</updated>
      <id>http://olsonjeffery.github.com/bdd/testing/2009/10/11/Thinking-about-step-2-for-context-spec-testing</id>
      <content type="html">&lt;p&gt;This is a post about the evolution of my thinking and practice regarding Context/Specification-style test composition. I&amp;#8217;d like to review my understanding and approach to it over time and some of the frictions that I encountered after the initial re-alignment of thinking that occurs when changing gears to this style of TDD, as opposed to more orthodox varieties. There may be nothing new here for some practitioners of TDD (if that&amp;#8217;s you: sorry for wasting your time); but for others who have made/are making the same mistakes as I or have some kind of &amp;#8220;itch&amp;#8221; in the back of their mind about how their tests just don&amp;#8217;t quite &amp;#8220;work&amp;#8221; with how they&amp;#8217;re currently writing them, perhaps this will help.&lt;/p&gt;

&lt;p&gt;I by no means claim to be an expert of any sort on BDD or test-first development in general. That being said, I consider myself a pretty active practitioner of these techniques (I fall into the &amp;#8221;&lt;a href='http://www.code-magazine.com/Article.aspx?quickid=0805061'&gt;Context/Specification&lt;/a&gt; aka &amp;#8220;Bellware-Driven-Development&amp;#8221; camp).&lt;/p&gt;

&lt;p&gt;Some time back, I received an email, asking me a question about some missing code in a pastebin I linked to in a mailing list discussion (&lt;a href='http://www.mail-archive.com/altnetseattle@googlegroups.com/msg00486.html'&gt;here&lt;/a&gt;, if you&amp;#8217;re interested). Sadly, the code is lost to the ages, but going back and reading that thread got me thinking about what the discussion was about and what I had learned since then.&lt;/p&gt;

&lt;p&gt;The thread itself was about the value of &lt;a href='http://en.wikipedia.org/wiki/Don%27t_repeat_yourself'&gt;DRY&lt;/a&gt; when composing tests in a Context/Specification style, specifically how adhering to DRY might lead one to create deep, nested class hierarchies of Contexts which serve the purpose of making test composition more convenient for the programmer, but having the consequence of obfuscating the intention of said Contexts and Specifications. Ayende has written a bit on this topic recently &lt;a href='http://ayende.com/Blog/archive/2009/09/29/scenario-driven-tests.aspx'&gt;here&lt;/a&gt;. Specifically:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of the main problem&lt;span&gt;s&lt;/span&gt; with unit testing is that we are torn between competing forces. One is the usual drive for abstraction and eradication of duplication, the second is clarity of the test itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id='an_example_domain'&gt;An example domain&lt;/h3&gt;

&lt;p&gt;Before we look at some code to illustrate this, let&amp;#8217;s talk a bit about the domain used for this exercise. For now, we&amp;#8217;ll rely on a very generic, very shallow Bank application. Briefly, it consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A &lt;code&gt;Customer&lt;/code&gt;, who has a collection of &lt;code&gt;Accounts&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The &lt;code&gt;Accounts&lt;/code&gt; are broken down into two types:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CheckingAccounts&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;SavingsAccounts&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, here are some business rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a new &lt;code&gt;Customer&lt;/code&gt; is created, they must have at least one &lt;code&gt;Account&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;Don&amp;#8217;t allow debits from &lt;code&gt;Accounts&lt;/code&gt; that send the balance into negative territory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Granted, in the real world, business rules aren&amp;#8217;t this black and white. But they&amp;#8217;ll do.&lt;/p&gt;

&lt;p&gt;Based on this, we have enough to get started with some specifications. For the purposes of this post, I&amp;#8217;ll be using C# tests written with &lt;a href='http://github.com/machine/machine.specifications'&gt;MSpec&lt;/a&gt;. If you&amp;#8217;re not familiar with MSpec, I can&amp;#8217;t help you.&lt;/p&gt;

&lt;h3 id='reasons_to_use_inheritance_when_composing_tests'&gt;Reasons to use inheritance when composing tests&lt;/h3&gt;

&lt;p&gt;Broadly speaking, there are two reasons to use parent/child relationships when composing tests:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have &amp;#8220;administrative&amp;#8221; concerns, such as configuring dependencies for some service under test (maybe setting up a DB session for an Integration test or generating mocks/stubs for something tested in isolation).&lt;/li&gt;

&lt;li&gt;You want to aggregate context, such as &amp;#8220;any context that inherits from this class is testing an entity/sccenario that is configured/modeled in some specific fashion&amp;#8221;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the end of the day, though, both of these concerns are about code reuse and not having to repeat yourself with cut&amp;#8217;n&amp;#8217;pastes of mundane, boiler plate code.&lt;/p&gt;

&lt;p&gt;Some code to illustrate the first item:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;CustomerRepositoryThatIsStubbed&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerRepository&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Mocks&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;GenerateStub&lt;/span&gt;&lt;span class='p'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;ICustomerRepository&lt;/span&gt;&lt;span class='p'&gt;&amp;gt;();&lt;/span&gt;

      &lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;ICustomerRepository&lt;/span&gt; &lt;span class='n'&gt;customerRepository&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In the above example, the class would serve up a stubbed out &lt;code&gt;ICustomerRepository&lt;/code&gt; that we could use for other services that may depend on it. This class could be used in any number of &amp;#8216;child&amp;#8217; Contexts that actually provide Specifications in order to get some predefined functionality.&lt;/p&gt;

&lt;p&gt;You can more generally use these kinds of classes to aggregate a group of Specs, perhaps by domain concern (e.g. &lt;code&gt;CustomerWithdrawalSpecs&lt;/code&gt;, &lt;code&gt;CustomerRepositoryQueryingSpecs&lt;/code&gt;, etc).&lt;/p&gt;

&lt;p&gt;Which leads into the second point noted above:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;new_customer_with_a_checking_account_with_a_hundred_dollar_balance&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;var&lt;/span&gt; &lt;span class='n'&gt;account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;CheckingAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;100.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;NewWithAccounts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;account&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;

      &lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt; &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
   
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;when_making_a_withdrawl_from_an_account_that_does_not_exceed_the_accounts_balance&lt;/span&gt; &lt;span class='p'&gt;:&lt;/span&gt;
      &lt;span class='n'&gt;new_customer_with_a_checking_account_with_a_hundred_dollar_balance&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;debitThatDoesNotExceedCustomersBalance&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;Debit&lt;/span&gt;&lt;span class='p'&gt;(-&lt;/span&gt;&lt;span class='m'&gt;60.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

      &lt;span class='n'&gt;Because&lt;/span&gt; &lt;span class='n'&gt;of&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='c1'&gt;// this could go away&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ProcessTransaction&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;debitThatDoesNotExceedCustomersBalance&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
   
      &lt;span class='n'&gt;It&lt;/span&gt; &lt;span class='n'&gt;should_withdraw_the_amount_from_the_customers_account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Balance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ShouldEqual&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;40.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
   
      &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Debit&lt;/span&gt; &lt;span class='n'&gt;debitThatDoesNotExceedCustomersBalance&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
   
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;when_making_a_withdrawl_from_an_account_that_does_not_exceed_the_accounts_balance&lt;/span&gt; &lt;span class='p'&gt;:&lt;/span&gt;
      &lt;span class='n'&gt;new_customer_with_a_checking_account_with_a_hundred_dollar_balance&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;debitThatDoesNotExceedCustomersBalance&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;Debit&lt;/span&gt;&lt;span class='p'&gt;(-&lt;/span&gt;&lt;span class='m'&gt;60.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

      &lt;span class='n'&gt;Because&lt;/span&gt; &lt;span class='n'&gt;of&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;exception&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Catch&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Exception&lt;/span&gt;&lt;span class='p'&gt;(()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;
            &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='c1'&gt;// this could go away&lt;/span&gt;
            &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ProcessTransaction&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;debitThatExceedsCustomersBalance&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
     
      &lt;span class='n'&gt;It&lt;/span&gt; &lt;span class='n'&gt;should_cause_an_error&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;exception&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ShouldNotBeNull&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

      &lt;span class='n'&gt;It&lt;/span&gt; &lt;span class='n'&gt;should_not_withdraw_the_amount_from_the_customers_account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Balance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ShouldEqual&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;100.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
   
      &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Debit&lt;/span&gt; &lt;span class='n'&gt;debitThatExceedsCustomersBalance&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Exception&lt;/span&gt; &lt;span class='n'&gt;exception&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These three classes all deal with building out actual Context for use in defining our Specifications. The first class sets up a general Use Case or &amp;#8216;shape&amp;#8217; for the behavior we want to verify and the latter classes make use of it for their own ends. That being said, there is some friction.&lt;/p&gt;

&lt;h3 id='keep_the_good_and_lose_the_bad'&gt;Keep the good and lose the bad&lt;/h3&gt;

&lt;p&gt;At first glance, there doesn&amp;#8217;t seem to be too much wrong with that approach, from an intention-revealing perspective (which ought to be foremost in your mind when writing these tests). The base class for the latter tests is right there, if you want to see what it does and its name gives a pretty good indicator of what it does, already.&lt;/p&gt;

&lt;p&gt;Soon or later, though, you may run up against a wall where this approach doesn&amp;#8217;t scale. What if you deeply nest your Contexts?&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;new_customer_with_a_checking_account_with_a_hundred_dollar_balance&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;var&lt;/span&gt; &lt;span class='n'&gt;account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;CheckingAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;100.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;NewWithAccounts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;account&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;

      &lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt; &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;NewWithAccounts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;account&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;

      &lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt; &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
   
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;and_another_customer_with_a_zero_dollar_balance&lt;/span&gt; &lt;span class='p'&gt;:&lt;/span&gt;
      &lt;span class='n'&gt;new_customer_with_a_checking_account_with_a_hundred_dollar_balance&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;var&lt;/span&gt; &lt;span class='n'&gt;account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;CheckingAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;0.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;NewWithAccounts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;account&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;

      &lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt; &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
   
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;when_transfering_funds_between_two_accounts&lt;/span&gt; &lt;span class='p'&gt;:&lt;/span&gt;
      &lt;span class='n'&gt;and_another_customer_with_a_zero_dollar_balance&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Because&lt;/span&gt; &lt;span class='n'&gt;of&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;TransferFundsFrom&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;
          &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
          &lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='m'&gt;60.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
     
      &lt;span class='n'&gt;It&lt;/span&gt; &lt;span class='n'&gt;should_add_the_funds_to_the_destination_account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;().&lt;/span&gt;&lt;span class='n'&gt;Balance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ShouldEqual&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;60.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
   
      &lt;span class='n'&gt;It&lt;/span&gt; &lt;span class='n'&gt;should_remove_the_funds_from_the_source_account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Balance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ShouldEqual&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;40.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this case, the third class (the one that actually has Specifications) only shows its relationship to its immediate parent. If these classes were split up, for whatever reason, amongst different source code files then it would become problematic to be able to easilly demonstrate what the intention was. For me, this approach was appealing because it seemed clever, at the time. But, after going down the path a ways, it didn&amp;#8217;t work out.&lt;/p&gt;

&lt;p&gt;Additionally, having several base classes that set up specific edge cases for how scenarios are represented, data-wise, is kind of putting the cart before the horse. In Context/Specification testing, you want the Contexts themselves to be just as important, if not moreso, than the Specs. It should plainly and clearly spell out &amp;#8220;Because stuff is configured in such a fashion and we did something just so..&amp;#8221;, we get a result that we expect in our Specifications.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;when_transfering_funds_between_two_accounts&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;var&lt;/span&gt; &lt;span class='n'&gt;zeroBalanceAccount&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;CheckingAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;0.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;NewWithAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;zeroBalanceAccount&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;var&lt;/span&gt; &lt;span class='n'&gt;hundredDollarsAccount&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;CheckingAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;100.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;NewWithAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;hundredDollarsAccount&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;
    
      &lt;span class='n'&gt;Because&lt;/span&gt; &lt;span class='n'&gt;of&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;TransferFundsFrom&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;
          &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
          &lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='m'&gt;60.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
     
      &lt;span class='n'&gt;It&lt;/span&gt; &lt;span class='n'&gt;should_add_the_funds_to_the_destination_account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;().&lt;/span&gt;&lt;span class='n'&gt;Balance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ShouldEqual&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;60.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
   
      &lt;span class='n'&gt;It&lt;/span&gt; &lt;span class='n'&gt;should_remove_the_funds_from_the_source_account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Accounts&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Where&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;IsChecking&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='n'&gt;Single&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
          &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Balance&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ShouldEqual&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;40.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here, we&amp;#8217;ve just taken the stuff that went in the superclass Contexts and put them into the class that has the Specifications, which pretty much puts you back at square one. The reason things like using inheritance to contain Context is appealing is because, in the above example, the test composer has to repetitively do things like create objects for the System/Behavior Under Test, wasting precious keystrokes.&lt;/p&gt;

&lt;p&gt;So how to do we mitigate this annoyance, thus acheiving the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Foremost, the Contexts reveal the intention and provide meaningful information on what behavior, exactly, is being verified.&lt;/li&gt;

&lt;li&gt;Reduce repetition as much as possible while still satisfying the previous point.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sharing information about lessons learned at this &amp;#8220;stage&amp;#8221; of competency for Context/Specification testing is where the community is, right now. Aaron Jensen blogged recently on the topic &lt;a href='http://codebetter.com/blogs/aaron.jensen/archive/2009/10/05/a-recent-conversation-about-mspec-practices.aspx'&gt;here&lt;/a&gt; (disclosure: he used to be my boss). Much of the post is the body of an email that he wrote replying to someone&amp;#8217;s question about Context/Specification testing issues. Speaking about base classes that aggregate context, he said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8221;&amp;#8230;I don&amp;#8217;t like it now. I much more prefer to just have a base class that contains any utility/meaningless cruft my specs have. You also seem to have taken this to a bit of an extreme. Would you make a regular base class just to create a single instance variable and set it to null in the constructor? Probably not. Same stuff applies here. There&amp;#8217;s no value in creating base classes unless they provide value. There&amp;#8217;s no naming or understanding benefit. As a matter of fact, they &lt;em&gt;hinder&lt;/em&gt; understanding more than anything.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The bit about pushing utility methods into base classes is a pretty valid approach to reducing keystrokes in tests while retaining an intention-revealing value to them.&lt;/p&gt;

&lt;p&gt;Consider the above example where we do all the setup in a single Context, but with the &amp;#8220;uglyness&amp;#8221; of the repatition. What if it were reworked to look more like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;CustomerAccountTransferSpecs&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;static&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt; &lt;span class='nf'&gt;CustomerWithStartingBalanceOf&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;decimal&lt;/span&gt; &lt;span class='n'&gt;startingBalance&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;var&lt;/span&gt; &lt;span class='n'&gt;account&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;CheckingAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;startingBalance&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;Customer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;NewWithAccount&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;account&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;when_transfering_funds_between_two_accounts&lt;/span&gt; &lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='n'&gt;CustomerAccountTransferSpecs&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='n'&gt;Establish&lt;/span&gt; &lt;span class='n'&gt;context&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;customerWithZeroBalance&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;CustomerWithStartingBalanceOf&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;0.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;customerWithHundredDollarsInCheckingAccount&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='n'&gt;CustomerWithStartingBalanceOf&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='m'&gt;100.0&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='p'&gt;};&lt;/span&gt;
      &lt;span class='p'&gt;....&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Aside from some (possible) nitpicks regarding what kind of account a customer gets when using the helper method, this approach provides a net benefit in terms of revealing intent and keystroke reduction. From here, the direction to push is towards stream-lining this process. Once again, Aaron Jensen has done some blogging on the &lt;a href='http://blog.eleutian.com/2007/09/29/FluentFixtures.aspx'&gt;topic&lt;/a&gt;. Also, Greg Young &lt;a href='http://codebetter.com/blogs/gregyoung/archive/2008/04/15/dddd-5-messages-have-fluent-builders.aspx'&gt;chimes in&lt;/a&gt; with a similar approach for an albeit different set of circumstances.&lt;/p&gt;

&lt;h3 id='conclusion'&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;A few things to remember:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using inheritance to DRY your way out of having to re-specify context is the wrong approach. &amp;#8220;Context explosion&amp;#8221; is something that you have to learn to deal with, but this approach will only serve to obfuscate your context, longterm. If you want to trim your keystrokes, instead consider the following:&lt;/li&gt;

&lt;li&gt;Having to re-specify context over and over &lt;em&gt;is&lt;/em&gt; a code smell. So think about the best, most intention-revealing way to present that context-building &lt;em&gt;for you&lt;/em&gt; and push it into some helper methods/fluent fixtures/etc instead of using rigid class hierarchies to represent that information.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Good luck and happy testing!&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Hello world GitHub blog post</title>
      <link href="http://olsonjeffery.github.com/meta/2009/08/17/Hello-world-GitHub-blog-post.html"/>
      <updated>2009-08-17T00:00:00-07:00</updated>
      <id>http://olsonjeffery.github.com/meta/2009/08/17/Hello-world-GitHub-blog-post</id>
      <content type="html">&lt;p&gt;Wow, five days short of a whole year since my last post on my blogger.com blog. I&amp;#8217;ve kind of had the idea in my head for some time to move my blog to GitHub. I may lose some bells and whistles, but I gain an easier way (in my opinion) to create and publish posts (and plus, markdown &amp;gt; *).&lt;/p&gt;

&lt;p&gt;Anywho, hopefully I&amp;#8217;ll post more, since I don&amp;#8217;t have any shortage of ideas kicking around that I&amp;#8217;d like to share.&lt;/p&gt;

&lt;p&gt;And now, some code to see how highlighting looks:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='boo'&gt;    &lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='n'&gt;System&lt;/span&gt;
    &lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='n'&gt;System&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Collections&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Generic&lt;/span&gt;
    
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Foo&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Bar&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
      &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;constructor&lt;/span&gt;&lt;span class='p'&gt;():&lt;/span&gt;
        &lt;span class='k'&gt;pass&lt;/span&gt;
      
      &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;Baz&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;input&lt;/span&gt; &lt;span class='k'&gt;as&lt;/span&gt; &lt;span class='n'&gt;string&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;as&lt;/span&gt; &lt;span class='n'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Foobie &amp;quot;&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='n'&gt;input&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here&amp;#8217;s to many more!&lt;/p&gt;</content>
    </entry>
  
</feed>
