<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>tobinharris.com - Blog</title>
  <id>tag:www.tobinharris.com,2008:mephisto/blog</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  
  <link href="http://www.tobinharris.com/blog" rel="alternate" type="text/html" />
  <updated>2008-07-20T05:00:00+00:00</updated>
  <link rel="self" href="http://www.tobinharris.com/blog/atom.xml" type="application/atom+xml" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site.</feedburner:browserFriendly><entry><title type="text">Links for 2008-07-19 [del.icio.us]</title><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/340404417/tobinharris" /><updated>2008-07-20T00:00:00-05:00</updated><id>http://del.icio.us/tobinharris#2008-07-19</id><summary type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.psd2html.com/order-now.html"&gt;Order PSD to HTML Service Online | PSD2HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/17/separation-of-concerns-by-example-part-5.aspx"&gt;Separation of Concerns by example: Part 5 - GrabBag&amp;lt;T&amp;gt;&lt;/a&gt;&lt;br/&gt;
the class&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ayende.com/hibernating-rhinos.aspx"&gt;Ayende @ Rahien - Hibernating Rhinos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.psd2html.com/order-now.html"&gt;Order PSD to HTML Service Online | PSD2HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/17/separation-of-concerns-by-example-part-5.aspx"&gt;Separation of Concerns by example: Part 5 - GrabBag&amp;lt;T&amp;gt;&lt;/a&gt;&lt;br/&gt;
the class&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ayende.com/hibernating-rhinos.aspx"&gt;Ayende @ Rahien - Hibernating Rhinos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><feedburner:origLink>http://del.icio.us/tobinharris#2008-07-19</feedburner:origLink></entry><entry><title type="text">Links for 2008-07-17 [del.icio.us]</title><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/338701618/tobinharris" /><updated>2008-07-18T00:00:00-05:00</updated><id>http://del.icio.us/tobinharris#2008-07-17</id><summary type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.bestlifeonline.com/cms/publish/finance/Mark_Cuban_s_Three_Rules_for_Building_a_Company.shtml"&gt;Best Life Magazine: Work &amp;amp; Finance: Mark Cuban's Three Rules for Building a Company&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.bestlifeonline.com/cms/publish/finance/Mark_Cuban_s_Three_Rules_for_Building_a_Company.shtml"&gt;Best Life Magazine: Work &amp;amp; Finance: Mark Cuban's Three Rules for Building a Company&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><feedburner:origLink>http://del.icio.us/tobinharris#2008-07-17</feedburner:origLink></entry><entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-07-17:1545</id>
    <published>2008-07-17T18:56:00Z</published>
    <updated>2008-07-17T19:08:04Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/338920167/18s-video-osx-xp-spaces-net" rel="alternate" type="text/html" />
    <title>18s Video: OSX + XP + Spaces + .NET</title>
<content type="html">
            &lt;p&gt;I'm really starting to enjoy the Mac OSX + VMWare + Windows for .NET and Rails development.&lt;/p&gt;
&lt;p&gt;This video shows some of the cool features that OSX Spaces + VMWare gives.&lt;/p&gt;

&amp;lt;object height="538" codebase="http://www.apple.com/qtactivex/qtplugin.cab" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="336"&gt;

&amp;lt;param name="src" value="MyMovie.mov"&gt;
&amp;lt;param name="AutoPlay" value="false"&gt;
&amp;lt;param name="Controller" value="true"&gt;


&amp;lt;embed pluginspage="http://www.apple.com/quicktime/download/" type="video/quicktime" src="http://www.tobinharris.com/assets/2008/7/17/OSXXP_1.mov" controller="true" autoplay="false" height="400" width="550" /&gt;
&amp;lt;/object&gt;

&lt;ul&gt;
&lt;li&gt; Using keyboard shortcuts to slide different desktops in and out.&lt;/li&gt;
&lt;li&gt; One desktop is OSX Leopard, the other Windows XP&lt;/li&gt;
&lt;li&gt; Using Expose to allow mouse movement to trigger window selector, or dekstop selector&lt;/li&gt;
&lt;li&gt; Dragging and dropping files between Windows and OSX&lt;/li&gt;
&lt;li&gt; Did you notice I had 2 instances of *Visual Studio 2008*, 2 instances of *Microsoft Word 2007*, and *SQL Management studio* running on XP!?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All this on a 30" iMac 2.4Ghz with 4GB Ram. It's cool stuff :) &lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/7/17/18s-video-osx-xp-spaces-net</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-07-17:1544</id>
    <published>2008-07-17T10:27:00Z</published>
    <updated>2008-07-17T17:32:14Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/338859495/a-friendly-passenger" rel="alternate" type="text/html" />
    <title>Friendliest console installer EVER!</title>
<content type="html">
            &lt;p&gt;This is the friendliest console-based-installer I've ever used:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/7/17/friendly_installer.png" alt="Phusion Passenger Installer" /&gt;&lt;/p&gt;

&lt;p&gt;I love the way it keeps the stress down by saying stuff like: "But don't worry, this installer will tell you how to ...". Very friendly indeed.&lt;/p&gt;

&lt;p&gt;It's for &lt;a href="http://www.modrails.com/index.html"&gt;Phusion Passenger&lt;/a&gt; - a module for hosting &lt;a href="http://www.rubyonrails.org"&gt;Ruby on Rails&lt;/a&gt; apps in  &lt;a href="http://httpd.apache.org/"&gt;Apache&lt;/a&gt;. Credit to the makers. 
It makes hosting Rails &lt;em&gt;totally simple&lt;/em&gt;. I just switched from using mod&lt;em&gt;proxy&lt;/em&gt;balancer and mongrel, and it's a walk in t' park so far.  &lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/7/17/a-friendly-passenger</feedburner:origLink></entry>
  <entry><title type="text">Links for 2008-07-16 [del.icio.us]</title><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/337743710/tobinharris" /><updated>2008-07-17T00:00:00-05:00</updated><id>http://del.icio.us/tobinharris#2008-07-16</id><summary type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.sugarsync.com/products/mobile_access.html"&gt;Sync Mobile Access Software Solution for Sharing Files on Mobile, Blackberry and iPhone - SugarSync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.getdropbox.com/"&gt;Dropbox - Home - Secure backup, sync and sharing made easy.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.sugarsync.com/products/mobile_access.html"&gt;Sync Mobile Access Software Solution for Sharing Files on Mobile, Blackberry and iPhone - SugarSync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.getdropbox.com/"&gt;Dropbox - Home - Secure backup, sync and sharing made easy.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><feedburner:origLink>http://del.icio.us/tobinharris#2008-07-16</feedburner:origLink></entry><entry><title type="text">Links for 2008-07-15 [del.icio.us]</title><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/336763955/tobinharris" /><updated>2008-07-16T00:00:00-05:00</updated><id>http://del.icio.us/tobinharris#2008-07-15</id><summary type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=77800&amp;#77800"&gt;Amazon Web Services Developer Connection : Member only access to files ...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html"&gt;Amazon Simple Storage Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=62i9Sodwp5o"&gt;YouTube - Bon Iver -- Flume&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=77800&amp;#77800"&gt;Amazon Web Services Developer Connection : Member only access to files ...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html"&gt;Amazon Simple Storage Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=62i9Sodwp5o"&gt;YouTube - Bon Iver -- Flume&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><feedburner:origLink>http://del.icio.us/tobinharris#2008-07-15</feedburner:origLink></entry><entry><title type="text">Links for 2008-07-14 [del.icio.us]</title><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/335767413/tobinharris" /><updated>2008-07-15T00:00:00-05:00</updated><id>http://del.icio.us/tobinharris#2008-07-14</id><summary type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://sourceforge.net/project/showfiles.php?group_id=132486&amp;package_id=145568&amp;release_id=610530"&gt;SourceForge.net: Files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sqliteadmin.orbmu2k.de/"&gt;SQLite Administrator - International Milestone Beta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://sourceforge.net/project/showfiles.php?group_id=132486&amp;package_id=145568&amp;release_id=610530"&gt;SourceForge.net: Files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sqliteadmin.orbmu2k.de/"&gt;SQLite Administrator - International Milestone Beta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><feedburner:origLink>http://del.icio.us/tobinharris#2008-07-14</feedburner:origLink></entry><entry><title type="text">Links for 2008-07-13 [del.icio.us]</title><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/334810566/tobinharris" /><updated>2008-07-14T00:00:00-05:00</updated><id>http://del.icio.us/tobinharris#2008-07-13</id><summary type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ui.alltop.com/"&gt;UI&lt;/a&gt;&lt;br/&gt;
Summary site of top usability blogs.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.upassoc.org/upa_publications/user_experience/past_issues/2008-1.html#schrag"&gt;UPA User Experience Magazine: Volume 7, Issue 1, 2008&lt;/a&gt;&lt;br/&gt;
UX User Experiance magazine. Online PDFs and articles.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.iol.ie/~bodonovan/campus/locator.htm"&gt;Latitude/Longitude Finder Utility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ayende.com/wiki/Rhino+Commons.ashx"&gt;Rhino Commons - Ayende @ Wiki&lt;/a&gt;&lt;br/&gt;
Rhino mocks. Ayendes great collection of tools for working with NHIbernate, Dependecy Injection, Threads etc etc&lt;/li&gt;
&lt;/ul&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ui.alltop.com/"&gt;UI&lt;/a&gt;&lt;br/&gt;
Summary site of top usability blogs.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.upassoc.org/upa_publications/user_experience/past_issues/2008-1.html#schrag"&gt;UPA User Experience Magazine: Volume 7, Issue 1, 2008&lt;/a&gt;&lt;br/&gt;
UX User Experiance magazine. Online PDFs and articles.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.iol.ie/~bodonovan/campus/locator.htm"&gt;Latitude/Longitude Finder Utility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ayende.com/wiki/Rhino+Commons.ashx"&gt;Rhino Commons - Ayende @ Wiki&lt;/a&gt;&lt;br/&gt;
Rhino mocks. Ayendes great collection of tools for working with NHIbernate, Dependecy Injection, Threads etc etc&lt;/li&gt;
&lt;/ul&gt;</content><feedburner:origLink>http://del.icio.us/tobinharris#2008-07-13</feedburner:origLink></entry><entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-07-12:1530</id>
    <published>2008-07-12T18:14:00Z</published>
    <updated>2008-07-13T05:23:21Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/334181586/vware-fusion-tip-use-osx-spaces-for-seamless-switching" rel="alternate" type="text/html" />
    <title>VMWare Fusion Tip: Use OSX Spaces for seamless switching </title>
<content type="html">
            &lt;p&gt;I just discovered a tip that’s made my VMWare fusion experience &lt;b&gt;loads better&lt;/b&gt;.&lt;/p&gt;


	&lt;p&gt;I like using my XP/Vista VM in full screen mode, but it’s a pain using Apple-H to hide the machine to get back into &lt;span class="caps"&gt;OSX&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;A better way is to use Spaces and allocate one space for VMWare fusion.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Start your XP/Vista/Ubuntu virtual machine as usual&lt;/li&gt;
		&lt;li&gt;Enable spaces in your System Preferences&lt;/li&gt;
		&lt;li&gt;Also, allocate one space to your virtual machine in the dialog&lt;/li&gt;
		&lt;li&gt;Setup a hot key for transitioning between spaces (Shit-Apple-Arrow is what I use).&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;It’s much nicer, and you get the beautiful slide transitions between spaces :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/7/12/vware-fusion-tip-use-osx-spaces-for-seamless-switching</feedburner:origLink></entry>
  <entry><title type="text">Links for 2008-07-10 [del.icio.us]</title><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/332374892/tobinharris" /><updated>2008-07-11T00:00:00-05:00</updated><id>http://del.icio.us/tobinharris#2008-07-10</id><summary type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://goodagile.com/scrumprimer/index.html"&gt;GoodAgile Scrum Training -&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.infoq.com/articles/dynamic-business-applications"&gt;InfoQ: Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications&lt;/a&gt;&lt;br/&gt;
stems, based on their interaction w&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jungledisk.com/"&gt;Jungle Disk - Reliable online storage powered by Amazon S3 - JungleDisk&lt;/a&gt;&lt;br/&gt;
Recommended backup utitlity that leans on Amazon S3. Apparently very slick.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://petdance.com/ack/"&gt;ack -- better than grep, a power search tool for programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.terracotta.org/"&gt;Home - Org - Terracotta&lt;/a&gt;&lt;br/&gt;
Network Attached Memory. Possible alternative to memcached?&lt;/li&gt;
&lt;li&gt;&lt;a href="http://devlicio.us/blogs/billy_mccafferty/archive/tags/NHibernate/default.aspx"&gt;NHibernate - Billy McCafferty&lt;/a&gt;&lt;br/&gt;
S#arp looks cool! It's a ASP.NET MVC + NHibernate achitecture + framework.&lt;/li&gt;
&lt;/ul&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://goodagile.com/scrumprimer/index.html"&gt;GoodAgile Scrum Training -&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.infoq.com/articles/dynamic-business-applications"&gt;InfoQ: Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications&lt;/a&gt;&lt;br/&gt;
stems, based on their interaction w&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jungledisk.com/"&gt;Jungle Disk - Reliable online storage powered by Amazon S3 - JungleDisk&lt;/a&gt;&lt;br/&gt;
Recommended backup utitlity that leans on Amazon S3. Apparently very slick.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://petdance.com/ack/"&gt;ack -- better than grep, a power search tool for programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.terracotta.org/"&gt;Home - Org - Terracotta&lt;/a&gt;&lt;br/&gt;
Network Attached Memory. Possible alternative to memcached?&lt;/li&gt;
&lt;li&gt;&lt;a href="http://devlicio.us/blogs/billy_mccafferty/archive/tags/NHibernate/default.aspx"&gt;NHibernate - Billy McCafferty&lt;/a&gt;&lt;br/&gt;
S#arp looks cool! It's a ASP.NET MVC + NHibernate achitecture + framework.&lt;/li&gt;
&lt;/ul&gt;</content><feedburner:origLink>http://del.icio.us/tobinharris#2008-07-10</feedburner:origLink></entry><entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-07-08:1522</id>
    <published>2008-07-08T04:49:00Z</published>
    <updated>2008-07-08T04:52:37Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/330178249/what-open-source-stack-do-the-gurus-use" rel="alternate" type="text/html" />
    <title>What Open Source stack do the gurus use?</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://www.ohloh.net/"&gt;Ohlo&lt;/a&gt; looks like a cool site for seeing what technologies people are using in their projects.&lt;/p&gt;

&lt;p&gt;I started listing &lt;a href="http://www.ohloh.net/accounts/tobinharris/stacks"&gt;my .NET and RoR stack&lt;/a&gt; here (I feel out of date already!).&lt;/p&gt;

&lt;p&gt;Watch the "Grok open source" video on the &lt;a href="http://www.ohloh.net/"&gt;home page&lt;/a&gt;, I was sold in minutes :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/7/8/what-open-source-stack-do-the-gurus-use</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-07-08:1521</id>
    <published>2008-07-08T04:48:00Z</published>
    <updated>2008-07-08T04:49:29Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/330178250/nice-use-of-google-maps-in-registration" rel="alternate" type="text/html" />
    <title>Nice use of Google maps in registration</title>
<content type="html">
            &lt;p&gt;Cool use of Google maps for selecting where you live or work during site registration. &lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/7/8/geo.png" alt="Google maps for registration" /&gt;
&lt;strong&gt;Registration snippet from the &lt;a href="http://www.ohloh.net"&gt;Ohlo&lt;/a&gt; site&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I was toying with using this approach for a venture I'm working on, but had never seen anyone use it. Will be interesting to see how easy doing things like store locators and location-based searches etc.&lt;/p&gt;

&lt;p&gt;P.S - &lt;a href="http://www.ohloh.net"&gt;Ohlo&lt;/a&gt; looks cool!&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/7/8/nice-use-of-google-maps-in-registration</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-07-06:1518</id>
    <published>2008-07-06T02:59:00Z</published>
    <updated>2008-07-06T03:02:35Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/328251736/state-machines-entities-fluent-interfaces-and-visualisation" rel="alternate" type="text/html" />
    <title>Generate State Machine diagrams from your POCO Entities</title>
<content type="html">
            &lt;p&gt;Have you ever come across those &lt;a href="http://smc.sourceforge.net/"&gt;tools&lt;/a&gt; &lt;a href="http://aabs.wordpress.com/2008/06/26/state-machines-in-c-30-using-t4-templates/"&gt;that&lt;/a&gt; &lt;a href="http://www.nunnisoft.ch/nunnifsmgen/en/home.jsp"&gt;let&lt;/a&gt; you generate code from state machine diagrams or state tables? Just for fun, I thought I'd try turning that idea on it's head:&lt;/p&gt;

&lt;p&gt;"Don't use a modeling tool or DSL to generate code. Instead, use a fluent interface to express state machines in your POCO entities. Then, automatically generate diagrams from the code, and use these to facilitate communication with project stakeholders. "&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I haven't posted the full code up here, just snippets&lt;/em&gt;*&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create State Machine framework with fluent interface&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started by writing a lightweight State Machine framework (&amp;lt;100 LOC). This is quite easy really. I gave it a fluent interface that allows state transitions to be expressed in readable code (see below).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create POCO entity&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Then created an example domain entity that used the framework. I gave it some states, set up tranistions between those states, and added a method to trigger a transition. &lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/7/4/po_1.png" alt="Business Entity Code" /&gt;&lt;/p&gt;

&lt;p&gt;The event is the &lt;code&gt;Raise()&lt;/code&gt; method, which attempts to make a transition. The transition succeeds if it is a legal path and no validation errors occur.
&lt;code&gt;ValidationDraftToRaised()&lt;/code&gt; is called automatically by the framework at runtime, during the transition. If there are validation errors, the transition fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Auto-Generate Statechart&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I can generate a state chart for any entity in my system.&lt;/p&gt;

&lt;p&gt;This chart was produced automatically from the code above. It is produced at runtime by using reflecting on the POCO to see what states and transitions we set up using the fluent interface.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/7/4/po_3.png" alt="State Chart" /&gt;&lt;/p&gt;

&lt;p&gt;The generator actually outputs in &lt;a href="http://www.graphviz.org/doc/info/lang.html"&gt;dot&lt;/a&gt; notation, and is great for representing state machines. Below is an example of use, I'm just showing the interface, rather than the implementation. &lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/7/4/po_2.png" alt="StateMachine DOT printer" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does this idea have legs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There's something very cool about coding the state machine with a fluent interface right inside the POCO, and then automatically generating a visual graph to facilitate discussion and communication. I like the fact that the knowledge is encapsulated in the POCO entities; no additional tools, state matrices or languages are required during the build cycle. &lt;/p&gt;

&lt;p&gt;All that said, I'm not buying this this idea yet. It is kind of fun, but having FSM semantics mingling with business domain semantics makes me a little uncomfortable. Also, if my light FSM framework needs to handle more complex cases (superstates, for example), then this approach might be even more invasive.     &lt;/p&gt;

&lt;p&gt;Thoughts anyone?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I persue this experiment, I have a few other ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Machine Self Diagnosis&lt;/strong&gt;. It will be able to check for common problems with the state machine setup: a &lt;code&gt;State&lt;/code&gt; that never gets transitioned to, guard clauses that will never be called etc. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unit Testing Integration&lt;/strong&gt; I'd like to expose those problems to NUnit, so that the unit testing catches any misuse of the DSL. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Something like this&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void TestPurchaseOrderStateMachine()
{
    foreach( CheckResult result in StateMachine.Check( typeof( PurchaseOrder ) )
    {
       Assert.IsTrue( result.Ok, result.Error );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which might output something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; 10 Assertions. 3 Ok. 2 Failed.
 State Machine Error. PurchaseOrder state "Cancelled" will never be transitioned to.
 State Machine Error. Guard method "ValidateRaisedToCancelled" will never be invoked.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's it for now, any thoughts welcome!&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/7/6/state-machines-entities-fluent-interfaces-and-visualisation</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-30:1505</id>
    <published>2008-06-30T06:12:00Z</published>
    <updated>2008-06-30T06:26:57Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/323593624/some-kind-of-dsl-for-gui-state-machines" rel="alternate" type="text/html" />
    <title>A simpler DSL for GUI state machines</title>
<content type="html">
            &lt;p&gt;I can't seem to get State Machines off my brain this week, sad isn't it?&lt;/p&gt;

&lt;p&gt;I find that I use them so rarely, yet I have a nagging feeling they could be so incredibly useful. I think it's ultimately because they could let me separate concerns.   &lt;/p&gt;

&lt;p&gt;Take today for example, I was building run-of-the-mill ASP.NET wizard/form with roughly the following steps. This GUI workflow is to implement  a simple online survey that people can submit.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/6/30/state1.jpg" alt="State Machine" /&gt;&lt;/p&gt;

&lt;p&gt;I started out without even thinking about state machines. I just had the use-case docs on my desk, and was hacking some ASP.NET page together. It was getting messy fast. &lt;/p&gt;

&lt;p&gt;I &lt;em&gt;really&lt;/em&gt; wanted to use some implementation of the state pattern. But, one gripe is that implementations of the state pattern tend to take so much plumbing code to express the state transitions. &lt;a href="http://msdn.microsoft.com/en-us/library/aa478972.aspx"&gt;This article&lt;/a&gt; demonstrates my point, I just didn't have time to invest in that much "stuff" (not wanting to diss the author, much of it looks fantastic, I just wanted something easier). Even drawing a state diagram takes too much time IMHO. &lt;/p&gt;

&lt;p&gt;I was trying to dream up a simpler way of expressing this state machine kind of thing in code, and so far have come up with the following. Note that so far I'm &lt;em&gt;only&lt;/em&gt; communicating states and transitions, but it's a start:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Start -&amp;gt; [Introduction || AlreadyDone]        
Introduction -&amp;gt; Terms -&amp;gt; Scores &amp;lt;-&amp;gt; Nomination &amp;lt;-&amp;gt; Confirm -&amp;gt; Thanks 
[Terms, Scores, Nomination] -&amp;gt; Saved for Later
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If I could make this into C# I could then express the &lt;strong&gt;15 possible transitions in only 3 lines of code!!&lt;/strong&gt; I like that a LOT. In case you're wondering what the symbols mean, here's a brief explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-&amp;gt;&lt;/code&gt; for a one way transition&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;-&amp;gt;&lt;/code&gt; for a two way transition (essentially 2 separate transitions)&lt;/li&gt;
&lt;li&gt;Grouping similar transitions using &lt;code&gt;[a, b, c]-&amp;gt;d&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've just got started thinking and playing with this stuff, and I hope I can take it somewhere useful!  &lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/30/some-kind-of-dsl-for-gui-state-machines</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-26:1493</id>
    <published>2008-06-26T18:36:00Z</published>
    <updated>2008-07-02T04:03:44Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/321249496/c-aint-blunt" rel="alternate" type="text/html" />
    <title>C# aint blunt!</title>
<content type="html">
            &lt;p&gt;I'm finally getting time to dig into &lt;a href="http://www.manning.com/skeet/"&gt;C# in Depth&lt;/a&gt; and try some stuff out. It's pleasing to see some of the terse constructs we now have.As a small example, this is great:&lt;/p&gt;

&amp;lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&amp;lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: 9px;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
&amp;lt;/style&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt; TotalPrice
{
     get
     {
         &lt;span class="kwrd"&gt;return&lt;/span&gt; 
            Lines.Sum(l =&amp;gt; l.Price * l.Quantity * (IsVat ? 1.175m : 1) );
     }
}&lt;/pre&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/26/c-aint-blunt</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-26:1492</id>
    <published>2008-06-26T02:58:00Z</published>
    <updated>2008-06-26T03:05:05Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/320750344/instant-messanger-for-coders" rel="alternate" type="text/html" />
    <title>Instant Messanger For Coders?</title>
<content type="html">
            &lt;p&gt;I had a look around for an instant messaging client for coders, but couldn't find one. &lt;/p&gt;

&lt;p&gt;Features I want for starters are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross platform&lt;/li&gt;
&lt;li&gt;Allowing pasting of large amounts of code (&amp;lt;=100 lines, at least)&lt;/li&gt;
&lt;li&gt;Code highlighting for c#, VB.NET, Ruby, Javascript, HTML etc etc&lt;/li&gt;
&lt;li&gt;Pasting of screen shots&lt;/li&gt;
&lt;li&gt;Public channels (like IRC) on particular topics, where people can collaborate&lt;/li&gt;
&lt;li&gt;All public discussions centrally stored and searchable &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyone know of such a thing?&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/26/instant-messanger-for-coders</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-26:1491</id>
    <published>2008-06-26T02:54:00Z</published>
    <updated>2008-06-26T02:54:31Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/320750345/313-votes-of-no-confidence-for-entity-framewor-that-s-sad" rel="alternate" type="text/html" />
    <title>Sad :-( Over 313 Votes of no confidence for ADO .NET Entity Framework</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://efvote.wufoo.com/forms/ado-net-entity-framework-vote-of-no-confidence/"&gt;This&lt;/a&gt; makes me sad.  So far over &lt;a href="http://efvote.wufoo.com/reports/entity-framework-vote-of-no-confidence-signatories/#public"&gt;313 people&lt;/a&gt; have given a vote of no confidence in the ADO .NET Entity Framework, and it's rising by the hour.&lt;/p&gt;

&lt;p&gt;It's sad for two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's a public kicking of someone's hard work. It probably wasn't meant to be that way, but that's how I see it. I feel for the development team. &lt;/li&gt;
&lt;li&gt;Microsoft &lt;em&gt;seem&lt;/em&gt; to have screwed EF up. If that's the case, developers will be led away from best practice, and a great opportunity to educate people has been missed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've not downloaded and studied the Entity Framework, so I wouldn't personally vote until I've made my own judgement.&lt;/p&gt;

&lt;p&gt;On the plus side, if EF truly does fall short of the bar, then the problems might be addressed and we might all get the high quality tool we want, that encompasses best practice drawn from the last few decades of experience. &lt;/p&gt;

&lt;p&gt;It's a shame it's taken this kind of stunt to raise the awareness, I just hope everyone gets their happy ending.&lt;/p&gt;

&lt;p&gt;Looking forward to downloading EF and finding out for myself!&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/26/313-votes-of-no-confidence-for-entity-framewor-that-s-sad</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-23:1484</id>
    <published>2008-06-23T17:20:00Z</published>
    <updated>2008-06-23T17:34:00Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/318758581/database-garbage-collection-for-business-entities" rel="alternate" type="text/html" />
    <title>Database Garbage Collection (for Business Entities)</title>
<content type="html">
            &lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/6/23/bin1_1.jpg" alt="bin" /&gt;
When I walk around customer offices, I see that they have rules for cleaning stuff up:&lt;/p&gt;

&lt;p&gt;If an employee starts filling out an annual-leave request form, but then changes their mind, the form goes in the bin. If a half-completed pension application form never gets sign off, it might be filed for 3 years, and then the IFA puts it in the bin. &lt;/p&gt;

&lt;p&gt;As soon as you write something on a piece of paper, it is persistent. Paper is a reliable storage mechanism for keeping your "Anuual Leave Request" around, even if you need to nip out for a 3 hour meeting. &lt;/p&gt;

&lt;p&gt;Should software applications do things differently? Shouldn't our web forms all auto-save? This led me to think that &lt;a href="http://www.tobinharris.com/2008/6/19/not-persisting-invalid-entities-is-rubbish"&gt;business entities should be saved at any time, regardless of whether they are valid or not&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If saving entities at any time is a good idea, then we need some way to clean up the ones that are forgotten, abandoned, or lost. Otherwise our databases will just fill up with crap that is of no use or interest. The business will dictate how and when things are cleaned up, because it knows the most efficient and legal ways of keeping things tidy. &lt;/p&gt;

&lt;p&gt;If you believe that most business rules belong in the business entity, then you might agree that this kind of business knowledge should gravitate around business entities also. I'm calling this topic Entity Garbage Collection for now. That said, if you're entities are persisted into a relational database, then it's also a kind of Database Garbage Collection.
&lt;img src="http://www.tobinharris.com/assets/2008/6/23/garbage_2.jpg" alt="Entity Garbage Collection" /&gt;&lt;/p&gt;

&lt;p&gt;If I were implementing Entity Garbage Collection, I'd probably want something like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class PensionApplication
{
   State[] states = new(){ Draft, Approved, Rejected, Archived };

    //anything in Draft state that's not been touched 
    //for 3 months gets binned
    void GarbageCollect_Draft()
    {
        if( UpdatedAt &amp;gt; 3.Months.Ago )
             GarbageCollect(this);
    }  

    //anything in archived state gets binned after 6 years
    void GarbageCollect_Archived()
    {
        if( ArchivedAt &amp;gt; 6.Years.Ago)
             GarbageCollect(this);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dada! We now have fire-and-forget entity GC; you can specify garbage collection rules for each state that the Pension Application is in. 
One  thing I like about this is that it &lt;strong&gt;makes entity garbage collection a first class citizen in the domain model&lt;/strong&gt;, and clearly visible for each entity. &lt;/p&gt;

&lt;p&gt;How and when the &lt;code&gt;GarbageCollection()&lt;/code&gt; is called is a separate problem. &lt;/p&gt;

&lt;p&gt;Perhaps the DB might have a sproc that runs nightly to delete any entities in the "Garbage" state. You could write some background task would run every night/week to run the GarbageCollection checks on each entity. Alternatively, you might use .NET attributes to specify GC rules, and have a GC subsystem reflect on those Attributes and build it's own, more performance friendly, routines in the database. &lt;/p&gt;

&lt;p&gt;As with my other random musings this week, I'm just thinking out loud and haven't actually tried any of this. Hopefully I'll get to play with it in sandbox sometime soon (probably along with some other ideas I've been toying with, and I'll be using NHibernate too I expect).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thoughts?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other, equally random, but related musings this week are:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.tobinharris.com/2008/6/23/state-pattern-for-entities"&gt;Business entities should existing in various States&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tobinharris.com/2008/6/22/is-the-state-pattern-broken"&gt;The regular State pattern may not be most suitable for business entities&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/23/database-garbage-collection-for-business-entities</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-23:1482</id>
    <published>2008-06-23T03:05:00Z</published>
    <updated>2008-06-23T03:07:43Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/318337994/state-pattern-for-entities" rel="alternate" type="text/html" />
    <title>A .NET state pattern for business entities </title>
<content type="html">
            &lt;p&gt;I started playing around with some ideas for a simple implementation of the State pattern. I wanted something that would allow business entities to exist in various states, and have different validations and business logic in different states.&lt;/p&gt;

&lt;p&gt;This implementation is a starting point. I've not applied it to anything real-world yet, so it might be completely naive. Thought I'd chuck it out there for opinions regardless!&lt;/p&gt;   
&amp;lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&amp;lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: 0.95em;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
&amp;lt;/style&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="rem"&gt;/// An issue in an issue tracking system&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Issue : StateMachine&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="rem"&gt;//define states applicable to this entity&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    State Draft;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    State Raised;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    State Closed;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    State Cancelled; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="rem"&gt;//entity properties&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Description;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime? FirstOpenedAt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; History;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Issue()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        &lt;span class="rem"&gt;//init allowable states and their transitions&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        Draft.CanBe(Raised, Cancelled).Initial();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        Raised.CanBe(Closed, Cancelled);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;        &lt;span class="rem"&gt;//init properties&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        History = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;    &lt;span class="rem"&gt;//custom validations automagically run &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    &lt;span class="rem"&gt;//during state transition from Draft to Raised&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;    &lt;span class="kwrd"&gt;void&lt;/span&gt; Validate_Draft_To_Raised()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;( String.IsNullOrEmpty(Description))&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;            ValidationErrors.Add(&lt;span class="str"&gt;"Description must be entered"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Raise()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;( ChangeState(Raised) )&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;            FirstOpenedAt = DateTime.Now;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;            History.Add(&lt;span class="str"&gt;"Issue was raised"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Close()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;( ChangeState(Closed) )&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;            History.Add(&lt;span class="str"&gt;"Issue was closed"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Cancel()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;( ChangeState(Cancelled) )&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;            History.Add(&lt;span class="str"&gt;"Issue was cancelled"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/23/state-pattern-for-entities</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-22:1480</id>
    <published>2008-06-22T04:26:00Z</published>
    <updated>2008-06-22T04:26:35Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/317638555/is-the-state-pattern-broken" rel="alternate" type="text/html" />
    <title>Is the State pattern broken?</title>
<content type="html">
            &lt;p&gt;I've been looking at the state pattern today, with the goal of allowing business entities to behave differently depending on their state. So, an Order in "Shipped" state would have a completely different behavior to an order in "Placed" state; I might not be able to update an order in Shipped state, but I could if it were merely "Placed".&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/6/22/state_figurea.jpg" alt="State Pattern" /&gt;&lt;/p&gt;

&lt;p&gt;In Design Patterns [GOF], the intent of State is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Allow an object to alter its behaviour when its internal state changes. The object will appear to change class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Perfect. But, when I had a crack at implementing it, I got a bit peeved. Here's a few reasons why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Too many classes&lt;/strong&gt;; An order entity with states Draft, Raised, Packed, Shipped and InQuery would require 7 classes: One for the context, one for state base class, and one each for the states themselves. This doesn't &lt;em&gt;feel&lt;/em&gt; right to me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Violation of DRY&lt;/strong&gt;? I'm repeating the interface declarations several times over. If I weren't using this pattern, I'd have only 1 class. I'm just not sure that, in my simple cases at least, the extra conceptual baggage is worth it.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lack of cohesion&lt;/strong&gt;. The context is delegating to the various states, and in turn each of those states contains business rules. Would it be better to keep all business logic in one place, or is State an elegant variation of the "rule object" pattern and in fact more cohesive? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lack of real-world use&lt;/strong&gt;. I don't see the State pattern used that much, certainly nowhere near as much as Singleton, Strategy, Factory, Iterator, Mediator, Observer and many others. I tried a brief .NET Reflector search, but couldn't find one use of this pattern in the .NET framework. A &lt;a href="http://www.google.com/codesearch?hl=en&amp;amp;lr=&amp;amp;q=State+&amp;amp;sbtn=Search"&gt;google code search&lt;/a&gt; came up with more possible uses.&lt;/p&gt;

&lt;p&gt;Before I get slammed for this post, I am smart enough to see some good things about the State pattern: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I like the fact that it uses composition over inheritance to handle state-specific behaviour. &lt;/li&gt;
&lt;li&gt;I like the fact that the pattern makes states a first class citizen, that's explicit. &lt;/li&gt;
&lt;li&gt;I also like the fact that individual states are testable.   &lt;/li&gt;
&lt;li&gt;There's a hint of OCP here, you can add more states (extend the class) without modifying it.  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I must admit, I'm not really qualified to GOF bash :) And, I haven't got the experience with this pattern to truly say I don't like it. However, I would like to find a way of implementing the state pattern in c# so that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entities can only transition to allowable states&lt;/li&gt;
&lt;li&gt;You can have different behaviors in each state&lt;/li&gt;
&lt;li&gt;You don't need to create lots of classes&lt;/li&gt;
&lt;li&gt;You can keep business rules in one place Entity&lt;/li&gt;
&lt;li&gt;It feels natural!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any thoughts?&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/22/is-the-state-pattern-broken</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-19:1469</id>
    <published>2008-06-19T20:42:00Z</published>
    <updated>2008-06-19T21:10:04Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/316186411/not-persisting-invalid-entities-is-rubbish" rel="alternate" type="text/html" />
    <title>Not persisting invalid entities is rubbish!</title>
<content type="html">
            &lt;p&gt;Here's a persistence idiom I don't like:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;em&gt;Only save entities if and when they are valid. Invalid entities don't get saved.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In case you're wondering what I'm talking about, here is an example of it in code.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Order
{
    public void Save()
    {
        if( this.OrderItems.Count == 0 )
            throw new  BusinessRuleViolation("Must have order lines!")

        if( this.TotalPrice &amp;gt; 1000000 &amp;amp;&amp;amp; ! this.IsApproved )
            throw new BusinessRuleViolation("Orders for over £1,000,000 have to be approved");

        orderDAO.Save(this);
    } 

    //insert more code here...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here, we only save if the business thinks it's a valid thing to save. &lt;/p&gt;

&lt;p&gt;One reason for this approach is to stop crap data making it into the database. Garbage in means garbage out, so don't put garbage in. I've used this approach many times in the past, but I'm starting to think it's a &lt;strong&gt;bad idea&lt;/strong&gt;. Perhaps we should allow invalid entities to be saved? &lt;/p&gt;

&lt;p&gt;Saving something has nothing to do with it being valid or not. When we put the two things together, aren't we're mixing persistence concerns with business rule concerns? Why should I let business rules block me from saving something? Isn't that simply ridiculous!? They're unrelated!&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/6/19/Hat_and_Stand.jpg" alt="Hat and Stand solv different problems" /&gt;&lt;/p&gt;

&lt;p&gt;Back to the garbage analogy, can't we just put garbage in and &lt;em&gt;ignore&lt;/em&gt; it? At least until it we've made it into something useful. &lt;/p&gt;

&lt;p&gt;This approach seems to be gaining acceptance. Google Docs and Microsoft Office always save work in progress, even if we decide not to keep the document. Keeping the document is now a different concern than saving it.   &lt;/p&gt;

&lt;p&gt;Going back to the order example, separating persistence from business-rule validity might look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Order
{
    public void Save()
    {
       orderDAO.Save(this);
    }


    public void PlaceOrder()
    {   
        if( this.OrderItems.Count == 0 )
            throw new  BusinessRuleViolation("You cant save an order with no order lines")

        if( this.TotalPrice &amp;gt; 1000000 &amp;amp;&amp;amp; ! this.IsApproved )
            throw new BusinessRuleViolation("Orders for over £1,000,000 have to be approved");

        this.State = OrderState.Placed;
    } 

    //insert more code here...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, we can save an order regardless of it's state, and we can execute the PlaceOrder() business logic regardless without having to save the object. Concerns have been separated. &lt;em&gt;Notes - An improvement on this would be if the Save() method lived on a Repository of course.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;Persistence, Business Logic and Validation&lt;/h4&gt;

&lt;p&gt;This fits in with some other patterns/idioms I like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business objects are totally allowed to get into a "bad" state. In fact, they are often born in an invalid state.&lt;/li&gt;
&lt;li&gt;Business objects can be persisted (saved) no-matter what state they're in.&lt;/li&gt;
&lt;li&gt;Business objects only raise exceptions when you try and do something illegal (like call PlaceOrder() on an order that isn't ready). &lt;/li&gt;
&lt;li&gt;Business objects are packed with behavior and business rules.&lt;/li&gt;
&lt;li&gt;Business objects can let you know what's up with them - they can be Validated()&lt;/li&gt;
&lt;li&gt;Business objects might have many states, each with it's own Validate() method and logic for transitioning between states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are the side-effects of this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can save objects anytime and anywhere.&lt;/li&gt;
&lt;li&gt;Invalid objects are stored in the same place as valid ones.&lt;/li&gt;
&lt;li&gt;You don't have to worry about storing objects in different places (such as the session) just because they're not "ready". &lt;/li&gt;
&lt;li&gt;You have a record of what people started, not just what they finished (find all orders over 1 month old that were under construction but never placed).&lt;/li&gt;
&lt;li&gt;Objects are always work in process. They are always in some lifecycle state. &lt;/li&gt;
&lt;li&gt;Other business processes have to be careful to only work with objects that are in a valid state (don't try to ship orders that are "under construction")&lt;/li&gt;
&lt;li&gt;You might need to do some housekeeping to make sure that old, incomplete and invalid items are deleted. There will be many of them hanging around.&lt;/li&gt;
&lt;li&gt;On large systems, you might need to do &lt;em&gt;aggressive&lt;/em&gt; housekeeping. &lt;/li&gt;
&lt;li&gt;Database constraints are virtually a no no, the database won't be enforcing business rules, at least not with standard mechanisms.&lt;/li&gt;
&lt;li&gt;You might want to use the state pattern, which could result in a slight object-graph explosion   &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My heart isn't totally set on all this, I'm really just toying with ideas here. I do, however, feel there's something good about all this. &lt;/p&gt;

&lt;p&gt;Feel free to shoot me down, but in the meantime I'm definately gonna play with this in a sandbox environment :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/19/not-persisting-invalid-entities-is-rubbish</feedburner:origLink></entry>
  <entry xml:base="http://www.tobinharris.com/">
    <author>
      <name>tobinharris</name>
    </author>
    <id>tag:www.tobinharris.com,2008-06-19:1468</id>
    <published>2008-06-19T07:06:00Z</published>
    <updated>2008-06-19T07:32:38Z</updated>
    <category term="Blog" />
    <link href="http://feeds.feedburner.com/~r/blog_of_tobin/~3/315796200/nhibernate-in-action-my-favourite-chapter" rel="alternate" type="text/html" />
    <title>NHibernate in Action: My favourite chapter</title>
<content type="html">
            &lt;p&gt;Having &lt;a href="http://www.tobinharris.com/blog"&gt;done a preliminary review&lt;/a&gt; of NHibernate in Action, Chapter 10 last night, I'm now  working on the actual edits. &lt;strong&gt;It's been fun!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.tobinharris.com/assets/2008/6/18/P1010677_small.jpg" alt="Chapter 10 - NHibernate in Action" /&gt;&lt;/p&gt;

&lt;p&gt;This is a great chapter, in fact, I think it's my favourite. It focuses on architectural issues, and I always find those the most fascinating. We're talking about separation of concerns, layering applications, whilst giving lots of code samples and real-world advice. &lt;/p&gt;

&lt;p&gt;This chapter cleverly starts with a "big ball of mud" example, where one method involves executing a use case, including data access, session management and business rules. The chapter then goes on to show how you can tease apart the responsibilities, pushing them into separate layers. It's one of the clearest approaches to describing these activities I've come across. &lt;/p&gt;

&lt;p&gt;Chapter 10 also talks using NHibernate along with ASP.NET sessions, and how you can leverage some of the newer features of NHibernate. &lt;/p&gt;

&lt;p&gt;I was at first surprised that Kuate chose to use the &lt;a href="http://en.wikipedia.org/wiki/Data_Access_Object"&gt;DAO pattern&lt;/a&gt; in the examples, rather than the &lt;a href="http://martinfowler.com/eaaCatalog/repository.html"&gt;Repository pattern&lt;/a&gt; (ala DDD). In retrospect this isn't a book about DDD, so explaining those concepts might have used too much ink. DAO still gives a clean separation of concerns, and nicely expresses the techniques involved whilst not requiring huge amounts of background explanation. A good choice. (Note that I did chuck in a small explanation of overlap between these approaches)&lt;/p&gt;

&lt;p&gt;This chapter also talks about business transactions that span multiple requests. I'm gonna read it again, because not sure I'm completely in agreement yet! I'll be asking Pierre Henri to help me ensure I've understood it correctly. It seems that the book is recommending the session-per-conversation pattern, but that means keeping state around for a long time, and that sets off alarm bells for me. &lt;/p&gt;

&lt;p&gt;All in all this chapter is great, it nicely intertwines the knowledge and techniques presented in the rest of the book with some good architectural principles. I'm up to page 22, so only 15 more to go!  &lt;/p&gt;
          </content>  <feedburner:origLink>http://www.tobinharris.com/2008/6/19/nhibernate-in-action-my-favourite-chapter</feedburner:origLink></entry>
</feed>
