<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
  <title>ReinH Blog</title>
  <subtitle>Ruby and Rails Best Practices</subtitle>
  <link href="http://reinh.com/feed/atom.xml" rel="self" />
  <link href="http://reinh.com/" />
  <updated>2008-08-30T14:03:36-04:00</updated>
  <author>
    <name>Rein Henrichs</name>
    <email>reinh@reinh.com</email>
  </author>
  <id>http://reinh.com/</id>
  
  <entry>
    <title>Incremental Stories and Micro&amp;#8209;Releases</title>
    <link href="http://reinh.com/blog/2008/08/29/incremental-stories-and-micro-releases.html" />
    <id>tag:reinh.com,2008-08-29:1220044463</id>
    <updated>2008-08-29T17:14:23-04:00</updated>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Agile-Estimating-Planning-Robert-Martin/dp/0131479415&quot;&gt;Agile estimating and planning&lt;/a&gt; is difficult. One of the practices that we are learning and adopting at Hashrocket that has truly improved our ability to ship is &lt;a href=&quot;http://www.dtsato.com/blog/2008/08/26/agile-2008-estimating-considered-wasteful-introducing-micro-releases/&quot;&gt;&lt;strong&gt;micro-releases&lt;/strong&gt;&lt;/a&gt;. The idea, championed by author Joshua Kerievsky, is that constantly planning and shipping small, feature based incremental releases within the iterative cycle drives the delivery of tangible business value. In other words, the most important stuff gets shipped sooner.&lt;/p&gt;
&lt;p&gt;Committing to micro-releases ensures that we are constantly working on delivering the highest priority features that represent real business value in an agile, incremental way. Complex stories that won&amp;#8217;t fit into a micro-release cycle are broken down into stories that deliver core value and supporting stories that can be deferred to a later iteration.&lt;/p&gt;
&lt;h3&gt;A Complex Story&lt;/h3&gt;
&lt;div class='story box negative' id=&quot;story-1&quot;&gt;
&lt;h4 class='story-title column span-14'&gt;
As A User I Want To View A List Of Projects&lt;br/&gt;
&lt;span class=&quot;small&quot;&gt;So that I can find a project that interests me&lt;/span&gt;
&lt;/h4&gt;
&lt;h4 style=&quot;text-align:right;&quot; class=&quot;story-number alt column span-1 last&quot;&gt;#1&lt;/h4&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-acceptance clear&quot;&gt;Acceptance:&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;All projects shown in list&lt;/li&gt;
	&lt;li&gt;List is paginated&lt;/li&gt;
	&lt;li&gt;List sorts by age by default&lt;/li&gt;
	&lt;li&gt;List is sortable by the following criteria
	&lt;ul&gt;
		&lt;li&gt;Age&lt;/li&gt;
		&lt;li&gt;Owner&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;li&gt;List is filterable by the following criteria
	&lt;ul&gt;
		&lt;li&gt;Status&lt;/li&gt;
		&lt;li&gt;Category&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-cost&quot;&gt;Cost: 4 Points&lt;/h5&gt;
&lt;/div&gt;
&lt;p&gt;This is a reasonably good story. It is clear, concise and deliverable. Its acceptance criteria are testable. It adds real business value. A short time ago ago I would have been quite happy to write stories just like this. That&amp;#8217;s not the case today.&lt;/p&gt;
&lt;p&gt;Now that our development process is becoming more geared towards focused micro-releases, the value of incremental stories is becoming exceedingly clear. Writing incremental stories allows us to break complex stories apart into a first increment focused on delivering core value and a set of secondary stories that can be added as later increments to deliver supplementary value.&lt;/p&gt;
&lt;h3&gt;A Simple Primary Story&lt;/h3&gt;
&lt;div class='story box negative'&gt;
&lt;h4 class='story-title column span-14'&gt;
As A User I Want To View A List Of Projects&lt;br/&gt;
&lt;span class=&quot;small&quot;&gt;So that I can find a project that interests me&lt;/span&gt;
&lt;/h4&gt;
&lt;h4 style=&quot;text-align:right;&quot; class=&quot;story-number alt column span-1 last&quot;&gt;#1&lt;/h4&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-acceptance clear&quot;&gt;Acceptance:&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;All projects shown in list&lt;/li&gt;
	&lt;li&gt;List is paginated&lt;/li&gt;
	&lt;li&gt;List is sorted by age&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-cost&quot;&gt;Cost: 1 Point&lt;/h5&gt;
&lt;/div&gt;
&lt;p&gt;This story is smaller and simpler but it delivers most of the value of the original complex story. Users can browse a list and find projects. Additional value is certainly provided by selecting sort and filtering criteria. But that&amp;#8217;s the point: these provide &lt;strong&gt;additional&lt;/strong&gt; value. The simple primary story is an increment that delivers on the core value behind this feature: users want to discover projects. It&amp;#8217;s the minimum functionality needed to start using the feature.&lt;/p&gt;
&lt;h3&gt;Some Simple Supplementary Stories&lt;/h3&gt;
&lt;div class='story box negative'&gt;
&lt;h4 class='story-title column span-14'&gt;
As A User I Want To Sort The Project List&lt;br/&gt;
&lt;span class=&quot;small&quot;&gt;So that I can better discover projects based on certain criteria&lt;/span&gt;
&lt;/h4&gt;
&lt;h4 style=&quot;text-align:right;&quot; class=&quot;story-number alt column span-1 last&quot;&gt;#1.1&lt;/h4&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-acceptance clear&quot;&gt;Requires:&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;A list of projects&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story- acceptance&quot;&gt;Acceptance:&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;List is sortable by the following criteria
	&lt;ul&gt;
		&lt;li&gt;Age&lt;/li&gt;
		&lt;li&gt;Owner&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-cost&quot;&gt;Cost: 1 Point&lt;/h5&gt;
&lt;/div&gt;
&lt;div class='story box negative'&gt;
&lt;h4 class='story-title column span-14'&gt;
As A User I Want To Filter The Project List&lt;br/&gt;
&lt;span class=&quot;small&quot;&gt;So that I can browse only projects that match a given criterion&lt;/span&gt;
&lt;/h4&gt;
&lt;h4 style=&quot;text-align:right;&quot; class=&quot;story-number alt column span-1 last&quot;&gt;#1.2&lt;/h4&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-requires clear&quot;&gt;Requires:&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;A list of projects&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-acceptance&quot;&gt;Acceptance:&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;List is filterable by the following criteria
	&lt;ul&gt;
		&lt;li&gt;Status&lt;/li&gt;
		&lt;li&gt;Category&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;margin-bottom:0;&quot; class=&quot;story-cost&quot;&gt;Cost: 2 Points&lt;/h5&gt;
&lt;/div&gt;
&lt;p&gt;One interesting and important observation is that the primary story is a one point story while the secondary stories total to three points. This means that these secondary stories represent fully three fourths of the original value of the complex story. In other words, shipping on the core value of the feature becomes much, much easier once it&amp;#8217;s broken up into increments.&lt;/p&gt;
&lt;h3&gt;Ship Leaner Features, Sooner&lt;/h3&gt;
&lt;p&gt;Breaking complex stories into simpler incremental stories becomes especially important in situations where your iterations are extremely time-sensitive. This is precisely the case in our &lt;a href=&quot;http://www.hashrocket.com/products&quot;&gt;3-2-1 Launch&lt;/a&gt; projects. Breaking stories into increments allows us to deliver more of the application&amp;#8217;s core value sooner. It also helps clients make real-time decisions about the importance of the primary and secondary value stories separately. Once they can get their hands on the core functionality they often re-prioritize the secondary stories more effectively.&lt;/p&gt;
&lt;p&gt;In the case of this particular story, once the basic list and pagination were out there &amp;#8211; and once project search (another core value feature) was implemented &amp;#8211; it became clear that the secondary project listing stories only duplicated functionality. These secondary stories are cooling off in the icebox as we speak. Meanwhile, we shipped a feature four times leaner and four times sooner.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Hack &amp;&amp; Ship</title>
    <link href="http://reinh.com/blog/2008/08/27/hack-and-and-ship.html" />
    <id>tag:reinh.com,2008-08-27:1219887069</id>
    <updated>2008-08-27T21:31:09-04:00</updated>
    <content type="html">&lt;p&gt;When the &lt;a href=&quot;http://ogtastic.com/&quot;&gt;OG Consulting&lt;/a&gt; &lt;a href=&quot;http://b.logi.cx/&quot;&gt;guys&lt;/a&gt; were down at &lt;a href=&quot;http://hashrocket.com/&quot;&gt;Hashrocket&lt;/a&gt; working on our latest 3-2-1, they introduced us to a pair of bash scripts called &lt;strong&gt;hack&lt;/strong&gt; and &lt;strong&gt;ship&lt;/strong&gt; that they use to streamline their everyday git workflow. They&amp;#8217;re so useful that we adopted them immediately and we&amp;#8217;ve been using them religiously ever since. I estimate that these little scripts save me about an hour a day and, what&amp;#8217;s more, they make it easy to follow the &lt;strong&gt;commit early, commit often&lt;/strong&gt; mindset that&amp;#8217;s so useful to the agile&amp;nbsp;process.&lt;/p&gt;
&lt;h3&gt;Simple Software Process&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s our typical workflow (before hack and ship):&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;p&gt;Start a feature in &lt;a href=&quot;https://www.pivotaltracker.com&quot;&gt;Pivotal Tracker&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Checkout a working branch for this feature&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Write a test&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Write an implementation to make the test pass&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Repeat 3 and 4 until the feature is complete&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Commit changes to git with a &lt;a href=&quot;http://www.tpope.net/node/106&quot;&gt;useful commit message&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Checkout the master branch&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Update the master branch&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Checkout the working branch&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Rebase the master branch into the working branch&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Checkout the master branch&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Merge the working branch into the master branch&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Push the changes to the origin repository (usually on &lt;a href=&quot;https://github.com/&quot;&gt;github&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Repeat.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is pretty simple (if a bit longwinded). We each probably do this dozens of times a day. Could it be simpler? You bet!&lt;/p&gt;
&lt;h3&gt;Simplified Software Process&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;d like to introduce you to the Simplified Software Process:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://weblogs.java.net/blog/chet/archive/2008/01/crystal_methodo.html&quot;&gt;&lt;img src=&quot;/images/Process3.gif&quot; class=&quot;box&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While it may not be a very good process, it does have one thing going for it: it&amp;#8217;s &lt;strong&gt;simple&lt;/strong&gt;. We like simple. So when we saw Rick Bradley&amp;#8217;s super simple bash scripts for automating these common git tasks, we jumped on them. These scripts are designed to work with the basic git workflow we outlined above. And they have awesome names.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s &lt;a href=&quot;http://gist.github.com/7641&quot;&gt;&lt;strong&gt;hack&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;script src=&quot;http://gist.github.com/7641.js&quot;&gt;&lt;/script&gt;&lt;p&gt;And &lt;a href=&quot;http://gist.github.com/7642&quot;&gt;&lt;strong&gt;ship&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;script src=&quot;http://gist.github.com/7642.js&quot;&gt;&lt;/script&gt;&lt;p&gt;Now our process looks like this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;p&gt;Start a feature in Pivotal Tracker&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Checkout a working branch for this feature&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Write a test&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Write an implementation to make the test pass&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Repeat 3 and 4 until the feature is complete&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Commit changes to git with a useful commit message&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;&lt;code&gt;hack&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;&lt;code&gt;ship&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Repeat.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We even wrote ourselves &lt;a href=&quot;http://gist.github.com/7640&quot;&gt;&lt;strong&gt;a little alias&lt;/strong&gt;&lt;/a&gt; to make this even easier:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/7640.js&quot;&gt;&lt;/script&gt;&lt;p&gt;Which brings the workflow down to three easy steps:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;p&gt;Test&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;Implement&lt;/p&gt;&lt;/li&gt;
	&lt;li&gt;&lt;p&gt;&lt;code&gt;ssp&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Combine this with a Continuous Integration build like &lt;a href=&quot;http://cruisecontrolrb.thoughtworks.com/&quot;&gt;cruisecontrol.rb&lt;/a&gt; and a deployment to a staging server that takes less than a minute &amp;#8211; we love &lt;a href=&quot;http://engineyard.com/&quot;&gt;EngineYard&lt;/a&gt; &amp;#8211; and you have the perfect recipe for agile, iterative, test-driven, micro-release oriented development. I&amp;#8217;ve never been happier with my development process.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Hack &amp;&amp; Test &amp;&amp; Ship</title>
    <link href="http://reinh.com/blog/2008/08/28/hack-and-and-test-and-and-ship.html" />
    <id>tag:reinh.com,2008-08-28:1219941001</id>
    <updated>2008-08-28T12:30:01-04:00</updated>
    <content type="html">&lt;p&gt;Devoted reader &lt;a href=&quot;http://b.logi.cx/&quot;&gt;Kevin Barnes&lt;/a&gt; of OGC pointed out in a comment to &lt;a href=&quot;http://reinh.com/blog/2008/08/27/hack-and-and-ship.html&quot;&gt;my last post&lt;/a&gt; that people make mistakes. This is news to me. In consideration of this, we have decided that it is important to test between hacking and shipping to ensure that any merging that goes on doesn&amp;#8217;t result in a broken build due to other people&amp;#8217;s mistakes.&lt;/p&gt;
&lt;p&gt;When multiple teams are working on a project, two teams can commit mutually incompatible changes. These changes may be in different areas and may not cause actual merge conflicts but may still break the build. Git is dumb. It won&amp;#8217;t fix these for you. This is why it&amp;#8217;s important to run your tests after you merge.&lt;/p&gt;
&lt;p&gt;I have thus updated the hack and ship protocol to include &lt;a href=&quot;http://gist.github.com/7640&quot;&gt;&lt;strong&gt;this important new step&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;script src=&quot;http://gist.github.com/7640.js&quot;&gt;&lt;/script&gt;&lt;p&gt;Running one last test before you merge your changes into master will also be a final catch-all and allow you to fix any problems before merging back to master. You can even &lt;code&gt;git commit --amend&lt;/code&gt; them to prevent anyone else from seeing your own mistakes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; &lt;code&gt;hack &amp;amp;&amp;amp; ship&lt;/code&gt; won&amp;#8217;t ship if there are merge conflicts in the hack step. &lt;code&gt;hack&lt;/code&gt; returns a non-zero exit code and the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; prevents ship from running. Likewise, &lt;code&gt;hack &amp;amp;&amp;amp; test &amp;amp;&amp;amp; ship&lt;/code&gt; won&amp;#8217;t ship unless &lt;code&gt;hack&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; are both successful.&lt;/p&gt;
&lt;p&gt;Thanks, Kevin.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Rocking the Hoedown</title>
    <link href="http://reinh.com/blog/2008/08/10/rocking-the-hoedown.html" />
    <id>tag:reinh.com,2008-08-10:1218391358</id>
    <updated>2008-08-10T14:02:38-04:00</updated>
    <content type="html">&lt;p&gt;&lt;img src=&quot;/images/hoedown/hoedown-speaker.png&quot; class=&quot;box right&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;dropcap w&quot;&gt;W&lt;/span&gt;e had a great time at the Ruby Hoedown this weekend. The &lt;a href=&quot;http://hashrocket.com&quot;&gt;Hashrocket&lt;/a&gt; crew was out in force (and there was much debauchery in the Hashrocket RV). We got to meet or get better acquainted with a lot of great rubyists and hear a lot of entertaining, informative talks.&lt;/p&gt;
&lt;h3&gt;Jim and Joe&amp;#8217;s Mock Dialog&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3046/2747232825_923bf6eb27_m.jpg&quot; class=&quot;box&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;a href=&quot;http://onestepback.org/&quot;&gt;Jim Weirich&lt;/a&gt; and &lt;a href=&quot;http://objo.com/&quot;&gt;Joe O&amp;#8217;Brien&lt;/a&gt; presented their talk about mocks and stubs in the form of a short play in three acts. This was very timely for me since mocking properly in tests is area we have been discussing quite a bit at Hashrocket.&lt;/p&gt;
&lt;p&gt;One thing they said that struck a chord was that complex mocks are a code smell that can clue you in to problems or hot spots for refactoring in the code under test.&lt;/p&gt;
&lt;p&gt;The presentation style was fresh and the tips they provided should be very valuable to anyone using mocks in testing (which should be everyone).&lt;/p&gt;
&lt;h3&gt;Ruby Best Practice Patterns&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/hoedown/rein-hoedown-talk.png&quot; class=&quot;box right&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
I&amp;#8217;m afraid I played a little trick on poor Jeremy and my dear audience. Instead of spending an hour giving examples of patterns and practices, I thought it might be fun to take a more satirical slant on the material. The resulting talk, &lt;cite&gt;Unfactoring From Patterns: Job Security Through Code Obscurity&lt;/cite&gt;, turned out to be a modest success (if I do say so myself) and I think rather more entertaining to boot.&lt;/p&gt;
&lt;p&gt;I did have time to show a few actual patterns but the dialog during the question and answer period was especially valuable. David Black, Yehuda Katz and others made some great points and I really enjoyed getting a chance to discuss one of my favorite topics with such a receptive and informed audience.&lt;/p&gt;
&lt;h3&gt;We Ain&amp;#8217;t Got No Keynote&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3020/2750897640_74a18f4807_m.jpg&quot; class=&quot;box&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
Chris decided to forgo the slides to tell us a more personal story about his growth from a lowly PHP hacker to the successful rubyist, entreprenuer and open-source champion that he is today. Chris is an exemplar for me of the right way to go about creating a personal and company brand.&lt;/p&gt;
&lt;p&gt;Chris&amp;#8217;s years of passion for tinkering, experimenting and exploring really have payed off in a big way. I think his story could rightly be considered inspirational. I&amp;#8217;m sure a lot of people left his talk and started side projects this very weekend. I really enjoyed his talk (even if he did tell people not to buy my book).&lt;/p&gt;
&lt;h3&gt;Flog Your Tests, Test Your Flog&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3268/2750731456_95a4c0e43d_m.jpg&quot; class=&quot;box right&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
Testing is such a crucial part of my process that I was very excited to hear Rick Bradley&amp;#8217;s account of his rather epic battle to add tests to flog. The irony here, of course, is that flog itself is a testing tool.&lt;/p&gt;
&lt;p&gt;This talk combined two of my favorite topics: testing and refactoring. Rick&amp;#8217;s war stories had some great takeaways: the importance of integration tests to characterize the behavior of the existing system, the ways in which code that is written test first differs from code that is written without tests, the utter importance of testing all the f&amp;#8212;king time. Bryal Liles will have more to say on that last topic in a bit.&lt;/p&gt;
&lt;p&gt;I really can&amp;#8217;t say enough about Rick&amp;#8217;s talk. Hashrocket often takes on applications with little or no testing for our Rescue Missions and Rick&amp;#8217;s deliberate, careful, comprehensive methodology is exactly the process we try to follow when we refactor and resuscitate our clients&amp;#8217; code back to health. Rick could very well write the Hashrocket Rescue Mission manual.&lt;/p&gt;
&lt;h3&gt;MIDI Machinations and Hungry Hungry Hippos&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2379/2330883047_19ee04ab8d_m.jpg&quot; class=&quot;box left&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
Giles Bowkett is a mad genius. Perhaps more importantly, he&amp;#8217;s an artist who can ship. He lured us all to a talk about archaeopteryx, his amazing MIDI  generator, and then proceeded to smack us all with the enlightenment stick.&lt;/p&gt;
&lt;p&gt;I won&amp;#8217;t spoil his talk for people who haven&amp;#8217;t seen it. Suffice it to say that it was far more than I expected. Giles&amp;#8217;s opinions on software development are unique and somewhat iconoclastic. Be careful, the code he writes might blow some people&amp;#8217;s minds.&lt;/p&gt;
&lt;p&gt;Giles&amp;#8217;s &lt;a href=&quot;http://gilesbowkett.blogspot.com/2008/04/my-approach-to-giving-presentations.html&quot;&gt;presentation style&lt;/a&gt; is engaging and he can be down right hilarious at times. Also, hippos are scary!&lt;/p&gt;
&lt;h3&gt;Wrap It Up!&lt;/h3&gt;
&lt;p&gt;Taking a road trip down to the Hoedown with the Hashrocket crew was one of the best conference experiences I&amp;#8217;ve had so far. The talks were great, but I think the after-conference festivities were the real hilight. Watching Obie and Jason play beer pong on a table constructed of pool noodles (watch the video), playing werewolf with a crew of drunken rubyists and spending time with some of my favorite conference friends. Who could ask for more? Also, Jeremy has big plans for next year&amp;#8217;s Hoedown. It involves words like &amp;#8220;free&amp;#8221; and &amp;#8220;Nashville&amp;#8221; &amp;#8211; I would be inclined to add &amp;#8220;awesome&amp;#8221; as well.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>REST &amp; Rails</title>
    <link href="http://reinh.com/2007/11/12/rest-and-rails.html" />
    <id>tag:reinh.com,2007-11-13:1194974956</id>
    <updated>2007-11-13T12:29:16-05:00</updated>
    <content type="html">&lt;p&gt;I am giving a presentation on Rails, REST, and the Resource Oriented Architecture today entitled &amp;#8220;REST &amp;amp; Rails: Web Services for the Rails World&amp;#8221;. Check out &lt;a href=&quot;http://assets.reinh.com/talks/REST-and-Rails.pdf&quot;&gt;the slides&lt;/a&gt;.&lt;/p&gt;
&lt;a href=&quot;http://assets.reinh.com/talks/REST-and-Rails.pdf&quot; title=&quot;REST &amp;amp; Rails&quot;&gt;&lt;img src=&quot;http://assets.reinh.com/images/REST-and-Rails.gif&quot; title=&quot;REST &amp;amp; Rails&quot;/&gt;&lt;/a&gt;</content>
  </entry>
  
  <entry>
    <title>To Design A Blog (act 1)</title>
    <link href="http://reinh.com/blog/2008/02/25/to-design-a-blog.html" />
    <id>tag:reinh.com,2008-02-25:1203970944</id>
    <updated>2008-02-25T15:22:24-05:00</updated>
    <content type="html">&lt;p&gt;Your blog&amp;#8217;s role as personal soapbox is obvious; its role in establishing identity is often overlooked. As a designer, your blog speaks volumes not only by what it says, but also by how it says it. If you can&amp;#8217;t design your own blog &amp;ndash; they will say &amp;ndash; how can you design anything else? It was with this in mind that I set out to redesign my own blog.&lt;/p&gt;
&lt;p&gt;As an entry point for colleagues and potential clients, your blog&amp;#8217;s first impression is crucial. Snap judgements will be made that you may never be able to escape. Your design must inform your readers as to your abilities with grace and flair. It must establish your visual style distinctly and succinctly. It must be both well orchestrated and well rehearsed. It must, in short, be great.&lt;/p&gt;
&lt;h3&gt;The Design Process&lt;/h3&gt;
&lt;p&gt;Before setting pen to paper, hand to mouse or fingers to keyboard, I began by thinking about what kind of response I wanted to elicit from my readers. I decided that want it to be warm and inviting, rich in information, and clean and elegant; it should be visually consistent, easy to read, and easy to navigate; most importantly, it should look like me.&lt;/p&gt;
&lt;p&gt;This lead to a few clear design goals:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Strong, consistent typography&lt;/li&gt;
	&lt;li&gt;Simple, uncomplicated layout&lt;/li&gt;
	&lt;li&gt;Minimal but effective use of color&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The design itself went through a number of iterations, beginning with simple pen-and-paper sketches. At the beginning, I imposed a few constraints to help focus my efforts: Single column, 800px width, gridded layout, three fonts. The content would reign supreme. Consistent typography would establish a visual hierarchy.&lt;/p&gt;
&lt;h3&gt;In The Beginning Was The Typography&lt;/h3&gt;
&lt;div class=&quot;img&quot;&gt;
&lt;a href=&quot;/images/redesign/ReinH-01.png&quot;&gt;&lt;img src=&quot;/images/redesign/thumbs/ReinH-01.png&quot; id=&quot;figure-1-1&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
    &lt;p&gt;(Figure 1.1)&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Sorting out the typography goes a long way towards giving your design a strong, cohesive style. It is important to chose two or three fonts (and no more) and to use them consistently. It is also important to use consistent font sizing to establish a visual hierarchy.&lt;/p&gt;
&lt;p&gt;I decided on Helvetica (specifically Helvetica Neue when available) for headers and Verdana for body text. Helvetica was chosen for its readability at medium to large point sizes and flat out gorgeousness. Verdana was chosen for its ubiquity and readability on screen at small to medium point sizes.&lt;/p&gt;
&lt;h3&gt;Rock Out With Your Layout&lt;/h3&gt;
&lt;p&gt;Most blogs use a two-column layout with a sidebar on the right to display subordinate information. Here, I choose a more minimal approach: a single column with information presented serially according to importance. The home page is streamlined to encourage the reader to discover subordinate content, as will navigation links at the top.&lt;/p&gt;
&lt;p&gt;Also, the typography was further refined. A serif font is added for subtitles and meta information (like post date). Finally. the main heading font is pumped a bit to help the major sections pop.&lt;/p&gt;
&lt;div class=&quot;img&quot;&gt;    &lt;a href=&quot;/images/redesign/ReinH-02.png&quot;&gt;&lt;img src=&quot;/images/redesign/thumbs/ReinH-02.png&quot; id=&quot;figure-1-2&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
    &lt;p&gt;(Figure 1.2)&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;A quick look at &lt;a href=&quot;/images/redesign/ReinH-02.png&quot;&gt;Figure 1.2&lt;/a&gt; will reveal that the initial read is much improved. The main content sections (the latest post and the list of recent posts) stand out as clearly differentiated. There remain, however, some issues with the font sizing and the spacing of elements. Also, the footer&amp;#8217;s columns appear rather haphazardly placed.&lt;/p&gt;
&lt;p&gt;Coming up in act two, the layout and typography get cleaned up and we add a splash of color. Don&amp;#8217;t miss it!&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Custom Textile Tags For Great Justice</title>
    <link href="http://reinh.com/blog/2008/04/09/customize-textile-tags-for-great-justice.html" />
    <id>tag:reinh.com,2008-04-09:1207788961</id>
    <updated>2008-04-09T20:56:01-04:00</updated>
    <content type="html">&lt;p&gt;fig. 1.1 | elem-typo-style.png&lt;/p&gt;
&lt;p&gt;Taking some inspiration (and code) from the quirky but lovable _why&amp;#8217;s original post on &lt;a href=&quot;http://redhanded.hobix.com/inspect/usingRedcloth3.html&quot;&gt;adding yer custom blocks&lt;/a&gt; to RedCloth and the inimitable Geoff Grosenbach&amp;#8217;s foray into the world of &lt;a href=&quot;http://nubyonrails.com/articles/about-this-blog-custom-textile&quot; title=&quot;About This Blog: Custom Textile | Ruby on Rails for Newbies&quot;&gt;custom textile figure tags&lt;/a&gt;, we&amp;#8217;ve build a custom tag (or prefix) for this blog&amp;#8217;s own figures, like &lt;a href=&quot;/images/elem-typo-style.png&quot; class=&quot;figure-1-1&quot;&gt;figure-1-1)&lt;/a&gt; there on the right.&lt;/p&gt;
&lt;p&gt;RedCloth&amp;#8217;s textile implementation uses some simple metaprogramming to create its own tags, which allows you to (more or less) easily create new tags to suit your own needs. The basic formula is: write a &lt;code&gt;textile_#{ tag }&lt;/code&gt; method, where &lt;code&gt;tag&lt;/code&gt; is the name of the tag you want to create. This method takes four arguments, tag, atts, cite and content, which are parsed from the textile by the RedCloth engine.&lt;/p&gt;
&lt;p&gt;For our purposes, we&amp;#8217;re only concerned with content and atts, so I&amp;#8217;ll leave the rest as an exercise for the gentle reader. The html we&amp;#8217;re trying to create looks like this:&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;figure-1-1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;ta&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/images/image.jpb&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;ta&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/images/thumbs/image.jpg&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;alt&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Figure 1.1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;ta&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;ta&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;ta&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Figure 1.1&lt;span class=&quot;ta&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The tag we want to use to create it looks like this:&lt;/p&gt;
&lt;code&gt;fig. 1.1 | image.jpg&lt;/code&gt;&lt;p&gt;That&amp;#8217;s quite a bit shorter and more elegant. Jumping right in to the good stuff, the method definition for our new tag looks like this:&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;textile_fig&lt;/span&gt;(tag, atts, cite, content)
  span_class = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;img &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; atts =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class=&amp;quot;([^&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]+)&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
    span_class += &lt;span class=&quot;gv&quot;&gt;$1&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  (figure_number, img_url) = content.split(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).map { |w| w.strip }
  figure_name = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Figure &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;figure_number&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  figure_id = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;figure-&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;figure_number&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.tr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)

  &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;
  &amp;lt;div class=&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;span_class&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot; id=&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;figure_id&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot;&amp;gt;
    &amp;lt;a class=&amp;quot;fig&amp;quot; href=&amp;quot;/images/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;img_url&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot;&amp;gt;
      &amp;lt;img src=&amp;quot;/images/thumbs/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;img_url&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot; alt=&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;figure_name&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot; /&amp;gt;
    &amp;lt;/a&amp;gt;
    &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;figure_name&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
  &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;#8217;s break that down.&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;span_class = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;img &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; atts =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class=&amp;quot;([^&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]+)&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
  span_class += &lt;span class=&quot;gv&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This adds any classes in atts (in the form of &lt;code&gt;class=&quot;foo&quot;&lt;/code&gt;) to the base class, img.&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;(figure_number, img_url) = content.split(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).map { |w| w.strip }
figure_name = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Figure &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;figure_number&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
figure_id = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;figure-&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;figure_number&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.tr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This breaks &amp;#8220;fig 1.1 | image.jpg&amp;#8221; down into two parts by splitting on the &amp;#8220;|&amp;#8221; and then normalizes them a bit to be used later.&lt;/p&gt;
&lt;p&gt;Finally, the relevant parts are jammed into the html prototype and spit back as the method&amp;#8217;s return value for insertion into your textile document (and for great justice, of course).&lt;/p&gt;
&lt;p&gt;fig. 1.2 | ReinH-07.png&lt;/p&gt;
&lt;p&gt;A later post might show the way &lt;code&gt;__END__&lt;/code&gt;, &lt;code&gt;DATA&lt;/code&gt; and &lt;code&gt;if __FILE__ == $PROGRAM_NAME&lt;/code&gt; were used with the TextMate Ruby Bundle&amp;#8217;s &amp;amp;#x2318;R command to preview the output of the textile tag as it was being written for a faster workflow or the jQuery used to activate the thumbnail&amp;#8217;s hover effect while an inline link like &lt;a href=&quot;/images/ReinH-07.png&quot; class=&quot;figure-1-2&quot;&gt;figure-1-2)&lt;/a&gt; is hovered. But I wouldn&amp;#8217;t hold your breath.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>To Design A Blog (act 2)</title>
    <link href="http://reinh.com/blog/2008/02/26/to-design-a-blog-2.html" />
    <id>tag:reinh.com,2008-02-26:1204079296</id>
    <updated>2008-02-26T21:28:16-05:00</updated>
    <content type="html">&lt;p&gt;fig. 1.1 | ReinH-02.png&lt;/p&gt;
&lt;p&gt;In our &lt;a href=&quot;http://reinh.com/2008/02/25/to-design-a-blog-1.html&quot;&gt;first installment&lt;/a&gt;, the typography and layout of the blog were mostly decided. With this ground work in place, it&amp;#8217;s time to start focusing on the details. But first, it&amp;#8217;s time to give our eyes and brain a chance to relax and reset. Staring at the same design for hours tends to give you tunnel-vision and we want to be able to look at the site afresh.&lt;/p&gt;
&lt;p&gt;Now that we&amp;#8217;re ready to continue, the most obvious issue is the arrangement of the sections in the footer. The rest of the design follows a strict grid system but the haphazard placement of the bottom columns is jarring to the eye and the whitespace between them is also problematic. &lt;a href=&quot;/images/ReinH-02.png&quot; class=&quot;figure-1-1&quot;&gt;figure-1-1)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;fig. 1.2 | ReinH-03.png&lt;/p&gt;
&lt;p&gt;A third column is added and the columns are properly aligned with the grid layout once again &lt;a href=&quot;/images/ReinH-03.png&quot; class=&quot;figure-1-2&quot;&gt;figure-1-2)&lt;/a&gt;. Great success! The remaining changes are all relatively minor and mainly involve tweaks to font size, color, and spacing. Bonus points if you can spot them.&lt;/p&gt;
&lt;p&gt;Now then: Welcome to the new blog! Enjoy your stay.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Adding Epicycles: Copernicus on Software Development</title>
    <link href="http://reinh.com/blog/2008/07/28/adding-epicycles-copernicus-on-software-development.html" />
    <id>tag:reinh.com,2008-07-28:1217288895</id>
    <updated>2008-07-28T19:48:15-04:00</updated>
    <content type="html">&lt;p class=&quot;first&quot;&gt;&lt;span class=&quot;dropcap t&quot;&gt;T&lt;/span&gt;he geocentric model of the solar system is a very old one. First postulated by Plato and Aristotle in the 6th century BC, the idea that the Earth is at the center of the universe was later refined and standardized in Claudius Ptolemy&amp;#8217;s main astronomical book, &lt;cite&gt;Almagest&lt;/cite&gt;. It is also an excellent example of a very common design failure in software development.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NB: The following contains a completely gratuitous lesson on the history of sclence. If you don&amp;#8217;t like learning things, I guess you can &lt;a href=&quot;#loser&quot;&gt;skip a bit&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Ptolemy&amp;#8217;s Faulty Assumption&lt;/h3&gt;
&lt;p&gt;It seems like a pretty obvious idea: sun, stars, planets&amp;#8230; everything &lt;em class=&quot;standard&quot;&gt;looks&lt;/em&gt; as if it goes around the Earth. Indeed, it was almost two thousand years before Copernicus was able to provide a convincing alternative.&lt;/p&gt;
&lt;h3&gt;Ptolemy&amp;#8217;s Great Design Failure&lt;/h3&gt;
&lt;p&gt;As people began to make better and better observations of the motions of the various heavenly bodies, they began to notice that their movements were often far more complex than the Ptolemaic system could allow. The planets were particularly troublesome in this regard.&lt;/p&gt;
&lt;p&gt;The logical step when a hypothesis no longer fits with observation is to reconsider that hypothesis and possibly discard it in place of a more fitting candidate. This is precisely what did not happen when Ptolemy set out to catalog the arrangements and movements of the celestial spheres.&lt;/p&gt;
&lt;p&gt;What he did instead was add smaller circles that the planets move in, and then have these circles move on top of their orbital circles. These circles on top of circles &amp;#8211; or &lt;em class=&quot;standard&quot; lang=&quot;la&quot;&gt;epicycles&lt;/em&gt; &amp;#8211; form the basis of Ptolemy&amp;#8217;s new and &amp;#8220;improved&amp;#8221; geocentric model.&lt;/p&gt;
&lt;p&gt;Ptolemy&amp;#8217;s greatest mistake was not made in adopting the geocentric model in the first place. It was made in not abandoning it when it no longer fit observed fact. Rather than throw out his bad design, he added more and more layers of bad design to try to fit the new observations.&lt;/p&gt;
&lt;h3&gt;Copernicus&amp;#8217;s Great Refactor&lt;/h3&gt;
&lt;p&gt;This process of adding more and more complexity onto complexity continued through iteration after iteration for almost two thousand years until Copernicus stepped in. He fixed the bad design at the root of the ridiculously complex and unwieldy Ptolemaic system by putting the Sun at the center. This simple change had a profoundly simplifying effect on our understanding of the motion of the planets and other heavenly bodies.&lt;/p&gt;
&lt;p&gt;Copernicus&amp;#8217;s heliocentric model is in retrospect a rather simple and obvious paradigm shift. Nevertheless, it marked the start of the Scientific Revolution and is often regarded as the starting point of modern astronomy.&lt;/p&gt;
&lt;h3 id=&quot;loser&quot;&gt;Copernicus on Software Development&lt;/h3&gt;
&lt;p&gt;What does all of this mean for software developers? It means that if your system is built on a bad design, trying to accomodate that problem will only lead you to add more and more levels of bad design. Eventually the whole system will come crashing down under the weight of this accumulated technical debt.&lt;/p&gt;
&lt;p&gt;This process of iteratively adding layers of complexity and bad design to attempt to shore up a faulty assumption or hopelessly flawed abstraction is called &lt;a href=&quot;http://c2.com/cgi/wiki?AddingEpicycles&quot;&gt;Adding Epicycles&lt;/a&gt; in honor of Ptolemy and his great design failure. The right thing to do is to follow Copernicus&amp;#8217;s lead and correct the faulty assumption or poor abstraction that is at the heart of your design failure. The sooner you do this, the sooner you can start simplifying your code.&lt;/p&gt;
&lt;p&gt;Correcting a critical design flaw will often cause these layers of circle upon circle upon preposterous circle of complexty to vanish, leaving your code clean and clear and simple. Just try not to anger the Pope.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Git It, Got It? Good!</title>
    <link href="http://reinh.com/blog/2008/02/19/git-it-got-it-good.html" />
    <id>tag:reinh.com,2008-02-19:1203458828</id>
    <updated>2008-02-19T17:07:08-05:00</updated>
    <content type="html">
&lt;p&gt;Last week, I gave a presentation on the &lt;a href=&quot;http://git.or.cz&quot;&gt;git&lt;/a&gt; version control system. Apparently it went pretty well. The &lt;a href=&quot;http://assets.reinh.com/talks/GIT.pdf&quot;&gt;slides are available&lt;/a&gt; for those who are interested.&lt;/p&gt;
</content>
  </entry>
  
</feed>
