<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>davedolan.com</title>
	<atom:link href="http://davedolan.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://davedolan.com/blog</link>
	<description>Website not included.</description>
	<lastBuildDate>Fri, 20 Jul 2012 22:04:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Solved! Moving the ECB to the Title column in a Document Library without breaking it</title>
		<link>http://davedolan.com/blog/?p=304</link>
		<comments>http://davedolan.com/blog/?p=304#comments</comments>
		<pubDate>Fri, 20 Jul 2012 21:14:55 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[SharePoint Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Computed Fields]]></category>
		<category><![CDATA[sharepoint]]></category>
		<category><![CDATA[XSLT]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=304</guid>
		<description><![CDATA[I&#8217;ve been searching around, and apparently so have a few other people for a way to move the link/menu from the File Name column in a Document Library to another column and preserve all of the integration functionality. There were SharePoint Designer based hacks that SORT of did this by letting you move it by [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been searching around, and apparently so have a few other people for a way to move the link/menu from the File Name column in a Document Library to another column and preserve all of the integration functionality.</p>
<p>There were SharePoint Designer based hacks that SORT of did this by letting you move it by setting the ListItemMenu property of a particular column&#8230; but this broke two things:<br />
   1) Clicking on the document takes you to the properties instead of the document.<br />
   2) The Open with &#8220;Microsoft Word | Excel | etc&#8221; part didn&#8217;t work. </p>
<p>No solution had thus been forthcoming so I buckled down and did it.  Instead of posting it here, I put it on CodeProject.com.  <a href="http://www.codeproject.com/Articles/424763/Zen-and-the-art-of-XSLT-rendering-fields-SharePoin">Check it out.</a></p>
<p>Not only did I enable the Title column with the ECB, but it defaults back to the file name if there is no title. </p>
<p>Hopefully someone finds it useful.   In my case it was useful because I was dealing with a couple of thousand imported documents whose file names had no bearing on their human readable Titles.  </p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=304</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SPUtility.TransferToSuccessPage : Here is The Missing Documentation</title>
		<link>http://davedolan.com/blog/?p=284</link>
		<comments>http://davedolan.com/blog/?p=284#comments</comments>
		<pubDate>Tue, 10 Jul 2012 14:57:22 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[SharePoint Development]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=284</guid>
		<description><![CDATA[As you may well know, <a href="http://msdn.microsoft.com/en-us/library/aa543474.aspx" title="MSDN Documentation on SPUtility.TransferToSuccessPage (opens in a new window)" target="_blank">SPUtility.TransferToSuccessPage</a>, it's very poorly documented.  There are millions of blog posts out there that touch on it, mention it, and complain about its lack of official documentation, so I won't belabor the point. I will, however, document it for you.]]></description>
				<content:encoded><![CDATA[<p>Ok, so the SPUtility class is chock full of useful little doodads and widgets that try to make life easier for SharePoint developers. Actually, scratch that, it&#8217;s there to make life easier for the Microsoft team who develops SharePoint itself, but they&#8217;ve kindly let us have a bunch of public methods. One of the nifty features is the TransferToSuccessPage method and as you can <a href="http://msdn.microsoft.com/en-us/library/aa543474.aspx" title="MSDN Documentation on SPUtility.TransferToSuccessPage (opens in a new window)" target="_blank">see here</a>, it&#8217;s very poorly documented. On top of that, it has some less than obvious behavior, so that lack of documentation is sometimes painful. There are millions of blog posts out there that touch on it, mention it, and complain about its lack of official documentation, so I won&#8217;t belabor that point; however, here&#8217;s the things you have to know when using it (specifically, the four string overload):</p>
<p><code lang="c-sharp"><br />
SPUtility.TransferToSuccessPage(message, nextUrl, linkText, linkUrl);<br />
</code><br />
<br/></p>
<p>I typically use it like this</p>
<pre class="brush: csharp; title: Code; notranslate">
      
      SPUtility.TransferToSuccessPage(
                    &quot;Successfully fooed your bar.&quot; +
                    &quot; Click {0} to go back to the web root.&quot; + &quot;
                    &quot; Click Ok to proceed back to the list.&quot;,
                     someSPList.DefaultViewUrl
                        .Replace(Web.ServerRelativeUrl, 
                        string.Empty), 
                     &quot;Here&quot;, 
                     Web.Url);


      // +s in the strings are for
      // your viewing pleasure, I don't 
      // usually do that
    </pre>
<ul>
<li>The &#8216;nextUrl,&#8217; which is where you go when you click &#8216;OK&#8217; needs to be relative to the site (SPWeb) root, NOT the site collection root, and NOT the server root, and NOT full URL. You can see above I&#8217;ve taken a server-relative URL and stripped out the server relative URL of the site.  This is because the &#8216;next url&#8217; is crafted like this, (with the + operator) in the code:
<p><code><br />
   currentSPContext.Web.Url + nextUrl;<br />
</code><br />
<br/>
</li>
<li>The {0} in the &#8216;message&#8217; parameter is what is replaced by the generated link. It specifically creates an a-tag like this<br />
    <code><br />
      &lt;a href="{linkUrl}"&gt;{linkText}&lt;/a&gt;<br />
    </code><br />
    You can specify a full URL, but if you specify a relative URL it will be relative to ~/_layouts/success.aspx. In case you didn&#8217;t notice, ~ is the WEB APPLICATION root. Not the site collection root. (They may be the same on your dev box, throwing some confusion your way when you go to production.) This is because SPUtility actually just straight up calls Server.Transfer(&#8220;~/_layouts/success.aspx&#8221;) which has no knowledge of SharePointyness like site collections and such.<br />
<br/>
</li>
<li>If you do not include a {0} in your message string, the last two parameters, linkText and linkUrl, are ignored (for all intents and purposes that is. Success.aspx still fiddles with them but it doesn&#8217;t affect your output)<br />
<br/>
</li>
<li>
This will <strong>NOT</strong> work in a workflow or a SharePoint event handler because it requires an HttpContext, and those things don&#8217;t usually have one.<br />
<br/>
</li>
<li>Because it calls Server.Transfer, It WILL throw a first-chance ThreadAbortException so don&#8217;t call it from within a &#8220;catch-all&#8221; try block unless you plan to ignore the ThreadAbortException. See the <a href="http://msdn.microsoft.com/en-us/library/y4k58xk7.aspx" title="MSDN Docs on Server.Transfer (new window)" target="_blank">MSDN Docs on Server.Transfer</a> for info.<br />
<br/>
</li>
</ul>
<p>There you have it.</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=284</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SPFile.Checkout() and modifying meta data properties</title>
		<link>http://davedolan.com/blog/?p=276</link>
		<comments>http://davedolan.com/blog/?p=276#comments</comments>
		<pubDate>Fri, 15 Jun 2012 13:23:23 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[SharePoint Development]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=276</guid>
		<description><![CDATA[It seems like it should be pretty straightforward. (But then again, nothing ever is when it comes to SharePoint development.) You check a file out, modify its metadata properties and check it back in.  I spent something on the order of three hours trying to figure out why that kept blowing up on me when I found a subtle stupid thing that, of course, isn't explicitly documented.]]></description>
				<content:encoded><![CDATA[<p>It seems like it should be pretty straightforward. (But then again, nothing ever is when it comes to SharePoint development.) You check a file out, modify its metadata properties and check it back in.  I spent something on the order of three hours trying to figure out why that kept blowing up on me when I found a subtle stupid thing that, of course, isn&#8217;t explicitly documented.</p>
<p>I thought this code should have worked&#8230;</p>
<p><strong>C#</strong></p>
<pre class="brush: csharp; title: Code; notranslate">

    var list = Web.Lists[listName];
    var item = list.GetItemByUniqueId(new Guid(uniqueId));

    Web.AllowUnsafeUpdates = true;
    var folder = item.File.ParentFolder;

    var checkoutRequired = list.ForceCheckout;

    if (checkoutRequired) {
        item.File.CheckOut();
    }

    var file = folder.Files.Add(listItem.File.Name, 
        listItem.File.OpenBinaryStream(), true,
        &quot;Published by the system after approvals, Pending check-in.&quot;, true);

    if (checkoutRequired) {
         file.CheckIn(&quot;Automated Go Live Check-in by the Workflow Process&quot;);
         file.CheckOut();
    }

   // todo: set all the metadata here
   var linkUrlValue = new SPFieldUrlValue();
   linkUrlValue.Description = &quot;Log Link&quot;;
   linkUrlValue.Url = WorkflowInformation.EventLogLink;
   item[&quot;LogLink&quot;] = linkUrlValue;

   // explode! &quot;document modified by 'domain\username' at {Now}&quot;
   item.UpdateOverwriteVersion(); 
                    
   if(checkoutRequired)
       file.CheckIn(&quot;Automated Go Live Check-in by the Workflow Process&quot;, 
            SPCheckinType.OverwriteCheckIn);
                    
   Web.AllowUnsafeUpdates = false;
                    
</pre>
<p>&#8230;But it didn&#8217;t. It kept blowing up. I tried various different things, and I couldn&#8217;t figure out what was going on. Then I noticed something subtle that all of the examples out there did: They used the file.Item property of the checked out document instead of the original item. I still don&#8217;t know why this makes a difference, but if you use it, it works. If you use the &#8216;original&#8217; item reference instead of the file.Item, it yaks. Below is the only slightly different, yet infinitely more &#8216;working&#8217; code.</p>
<p><strong>C#</strong></p>
<pre class="brush: csharp; title: Code; notranslate">

     var list = Web.Lists[listName];
    var item = list.GetItemByUniqueId(new Guid(uniqueId));

    Web.AllowUnsafeUpdates = true;
    var folder = item.File.ParentFolder;

    var checkoutRequired = list.ForceCheckout;

    if (checkoutRequired) {
        item.File.CheckOut();
    }

    var file = folder.Files.Add(listItem.File.Name, 
        listItem.File.OpenBinaryStream(), true,
        &quot;Published by the system after approvals, Pending check-in.&quot;, true);

    if (checkoutRequired) {
         file.CheckIn(&quot;Automated Go Live Check-in by the Workflow Process&quot;);
         file.CheckOut();
    }

   // the CRAZY thing here is you can't use another 
   // reference to the item if the place requires a checkout, even if 
   // it's the one from whence you originally got the file reference 
   // in the first place.
   // You MUST use the file.Item reference to the item or it breaks when 
   // you set the metadata.

   // Your humble author and narrator spent 3 hours trying to figure this out.
                    

   // todo: set all the metadata here
   var linkUrlValue = new SPFieldUrlValue();
   linkUrlValue.Description = &quot;Log Link&quot;;
   linkUrlValue.Url = WorkflowInformation.EventLogLink;
   file.Item[&quot;LogLink&quot;] = linkUrlValue;
   file.Item.UpdateOverwriteVersion();
                    
   if(checkoutRequired)
       file.CheckIn(&quot;Automated Go Live Check-in by the Workflow Process&quot;,   
            SPCheckinType.OverwriteCheckIn);
                    
   Web.AllowUnsafeUpdates = false;
                    
</pre>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=276</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The end of the world?</title>
		<link>http://davedolan.com/blog/?p=266</link>
		<comments>http://davedolan.com/blog/?p=266#comments</comments>
		<pubDate>Tue, 24 Jan 2012 03:40:57 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=266</guid>
		<description><![CDATA[Back when I was a kid, I remember having something called, (astonishingly politically incorrectly,) the &#8220;Indian Weather Rock.&#8221; It was a knick-knack that sat on a shelf somewhere and the trick was that it would tell you about the weather. You put it outside when you wanted a reading: if the rock was wet, it&#8217;s [...]]]></description>
				<content:encoded><![CDATA[<p>Back when I was a kid, I remember having something called, (astonishingly politically incorrectly,) the &#8220;Indian Weather Rock.&#8221;  It was a knick-knack that sat on a shelf somewhere and the trick was that it would tell you about the weather.  You put it outside when you wanted a reading: if the rock was wet, it&#8217;s raining. If it&#8217;s white, it was snowing&#8230; etc.  It was an amazing piece of human engineering.  </p>
<p>I thought, with all of the tumultuous events of today, be they financial systems collapsing, Mayan calendars running out of squares into which we can write the year, famous people changing careers, disastrous political machinations taking shape left and right, what the world needs is a digital way to understand exactly what kind of mess we&#8217;re in.  So, I&#8217;ve put together what may be the most comprehensive computing device I&#8217;ve ever made, and let me tell you, it&#8217;s almost NEVER wrong.  Go <a href="http://davedolan.com/fyi" title="Magic Device">here (click)</a> and check out some of it&#8217;s <a href="http://en.wikipedia.org/wiki/Facepalm" title="Wikipedia's definition of magic">unequivocal magic.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=266</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>B+ Trees for the masses</title>
		<link>http://davedolan.com/blog/?p=254</link>
		<comments>http://davedolan.com/blog/?p=254#comments</comments>
		<pubDate>Wed, 09 Nov 2011 19:18:24 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=254</guid>
		<description><![CDATA[Roger has done, in the generic, what nobody I&#8217;ve found to date has: He&#8217;s implemented an open sourced, B+ Tree library for .NET that scales well and is completely thread safe. I&#8217;ve tried making one myself, and while I did manage to implement a b+ tree, it wasn&#8217;t threadsafe and linear scaling into the hundreds [...]]]></description>
				<content:encoded><![CDATA[<p>Roger has done, in the generic, what nobody I&#8217;ve found to date has: He&#8217;s implemented an <a href="http://csharptest.net/projects/bplustree/">open sourced, B+ Tree library for .NET</a> that scales well and is completely thread safe.  I&#8217;ve tried making one myself, and while I did manage to implement a b+ tree, it wasn&#8217;t threadsafe and linear scaling into the hundreds of millions of items&#8230; this one is.  </p>
<p>I&#8217;ve chatted with another Mr. Mehdi Gholam who has his own working but not-so-generic version of a B+ Tree in <a href="http://www.codeproject.com/KB/database/RaptorDB.aspx">RaptorDb</a>, and seen countless people asking for one all over the place in message boards and forums.  Well there it is.   I know it&#8217;s not much hearing me say it, but free software isn&#8217;t free for the guy who writes it, so&#8230; thanks, Roger. Great work!</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=254</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bring on the rocks.</title>
		<link>http://davedolan.com/blog/?p=249</link>
		<comments>http://davedolan.com/blog/?p=249#comments</comments>
		<pubDate>Mon, 12 Sep 2011 13:13:23 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=249</guid>
		<description><![CDATA[If you&#8217;ve worked hard to acquire a talent, or you&#8217;ve busted your rear end in the gym, if you&#8217;ve spent hours, days, or weeks creating some kind of art or a kickass computer game, I have no problem with you telling me about it. There&#8217;s nothing wrong with being labelled ego-centric or being called a [...]]]></description>
				<content:encoded><![CDATA[<p>If you&#8217;ve worked hard to acquire a talent, or you&#8217;ve busted your rear end in the gym, if you&#8217;ve spent hours, days, or weeks creating some kind of art or a kickass computer game, I have no problem with you telling me about it. There&#8217;s nothing wrong with being labelled ego-centric or being called a &#8216;show off&#8217; by the people who haven&#8217;t done these things themselves. It should be inspiring to other people, not cause them to throw rocks. Jealousy is a lot uglier than pride. Bring on the proud people, and the rocks. </p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=249</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Runaround: An old school puzzle game (My first XNA game.)</title>
		<link>http://davedolan.com/blog/?p=239</link>
		<comments>http://davedolan.com/blog/?p=239#comments</comments>
		<pubDate>Fri, 08 Jul 2011 23:42:37 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=239</guid>
		<description><![CDATA[This is actually a rewrite of a game I made when I was 13 on my good old Mac Classic (it was black and white.) It plays the same in this version, except back then my brother was designing the levels so they were a lot harder and cooler. Click here to try it out [...]]]></description>
				<content:encoded><![CDATA[<p>This is actually a rewrite of a game I made when I was 13 on my good old Mac Classic (it was black and white.) It plays the same in this version, except back then my brother was designing the levels so they were a lot harder and cooler.</p>
<p>
<a href="http://davedolan.com/Runaround/publish.htm">Click here to try it out</a>
</p>
<p>
<img src="http://davedolan.com/blog/wp-content/uploads/2011/07/Runaround.png" alt="Screenshot" />
</p>
<p>
It automatically checks for updates, so when I get around to writing new ones, they&#8217;ll come down automatically.</p>
<p>I made it easy to modify the levels, and if you&#8217;re enterprising enough to create an 18 line text file, you can make your own:
</p>
<h3>Object</h3>
<p>  Get all of the jewels (gold for now, the tiles suck) and get to the exit (which will open once you have all of them.) Push blocks into holes to fill them in so you can cross. Blocks can also go through one way doors if there is something acceptable on the other side.</p>
<h3>Controls</h3>
<p><b>Arrows:</b> Move<br/><br />
<b>Space: </b> Kill yourself<br/></p>
<h3>Adding new maps:</h3>
<p>
Map files are simple text files of 18 lines with 18 characters per line.  Each character corresponds to a tile.<br />
The tile to character map is listed below.
</p>
<p>
Copy the template below into a new text file, name it LevelX.map where X is the number of level it is. (like Level12.map for level 12.)  They have to be in sequence. Put the LevelX.map in the Content folder. It&#8217;s a clickonce app so I&#8217;ll have to figure out where the content folder is. An easy way to find it is search for Level1.map from the start menu.  Yeah kids, it&#8217;s XNA so windows only.
</p>
<p>
Edit each of the characters in the map file as shown in the chart below. Just change the one in the template to be whatever you want it to be.  Note, it IS possible to make a map that you can&#8217;t beat, so that part is up to you.
</p>
<pre>
chr	title		  
---------------
(.) Empty         
(N) PlayerUp      
(S) PlayerDown    
(W) PlayerLeft    
(E) PlayerRight   
(T) Tree 
($) Jewel 
(@) Rock   
(-) Hole          
(+) MovableBlock   
(L) OneWayLeft     
(R) OneWayRight    
(U) OneWayUp       
(D) OneWayDown    
(O) ClosedExit    
(X) OpenExit     

Map File Template (MUST be 18x18)  (this is an example map template)

@@@@@@@@@@@@@@@@@@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@................@
@@@@@@@@@@@@@@@@@@
</pre>
<p>Email me your cool map files to dave dotdolan at gmail, or post them in the comments.</p>
<p>Recent Changes:</p>
<p>Made map files be 18&#215;18 (previously was 16&#215;16)<br />
Fixed a bug in pushing bricks through one way doors.<br />
Refactored the code so that it&#8217;s closer to an MVCish pattern -> still not quite there<br />
new rock tile<br />
added sounds other than system beeps</p>
<p>Todo:<br />
Status screen -> Number of moves, Crystals Left, current level, (death count?)<br />
Opening splash screen (pick your level -> level preview/selection screen)<br />
transition effects (pushing the block, dying, getting some gold)<br />
animated tiles</p>
<p>Future:<br />
level editor that looks nicer than text files.<br />
scrollable boards that exceed 18 x 18
</p>
<p>I&#8217;m going to eventually post the source somewhere but it&#8217;s nothing really interesting. Email me if you want it.</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=239</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Whole Shebang: Implementing a general purpose language interpreter using GOLD Parser Builder and the new BSN Engine</title>
		<link>http://davedolan.com/blog/?p=166</link>
		<comments>http://davedolan.com/blog/?p=166#comments</comments>
		<pubDate>Sat, 20 Nov 2010 19:18:01 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[BSN]]></category>
		<category><![CDATA[gold]]></category>
		<category><![CDATA[parser]]></category>
		<category><![CDATA[REPL]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=166</guid>
		<description><![CDATA[I’m not exactly sure what it is about programming languages that I find so interesting, but for some reason I just can’t seem to shake the fascination I have for them. Perhaps it is the relatively simple algorithms and techniques that are used to perform what appears to the casual observer to be ‘black magic.’ How do they get input code, which can be constructed in any number of different ways, at virtually any length, to do what the user (programmer) wants? I’ll show you how I built my own interpreter using Gold Parser Builder website, and Arsène von Wyss’s brand new BSN-Engine.]]></description>
				<content:encoded><![CDATA[<p><em>Update: The source code for this project has been added to a <a href="http://code.google.com/p/simple3-interpreter/">Google Code repository</a> and will be updated there.</em></p>
<p><em>Second update:</em>  The article appears, further updated, on <a href="http://www.codeproject.com/KB/recipes/bsn_interpreter.aspx" title="link to the CodeProject article">CodeProject</a>.  Go check it out there! (I&#8217;ve removed it from this site.) </p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=166</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Misadventure in (someone else&#8217;s) GoF Land</title>
		<link>http://davedolan.com/blog/?p=157</link>
		<comments>http://davedolan.com/blog/?p=157#comments</comments>
		<pubDate>Sun, 24 Jan 2010 05:18:51 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[SQL Code]]></category>
		<category><![CDATA[GoF]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[WTF]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=157</guid>
		<description><![CDATA[It's ok to decouple your design from your implementation, as long as you eventually get to the implementation.]]></description>
				<content:encoded><![CDATA[<p>So, here I go again.  I don&#8217;t want my sparsely populated blog to turn into a collection of articles from <a href="http://thedailywtf.com/">the Daily WTF</a>, but I do want to use a real world example, with the names changed to protect the innocent and guilty, to illustrate a point.  </p>
<p>Design patterns, object oriented design, and the employment thereof can be just as much a cure in search of a disease as they are a cure for a disease.  I&#8217;ve recently run into this lock, stock, and barrel in a project with my unnamed employer.</p>
<p>There is this project, let&#8217;s call it FLEA, which is a relatively straightforward web forms application. Written as a front end to handle some day to day process for a particular customer, it was made out to be some kind of shimmering example of, well what the architect might have said &#8220;Stuff I read on the back cover of a book in the lavatory.&#8221;  </p>
<p>It had &#8220;everything&#8221; from service locators, coding against interfaces, and perhaps most glaringly, a monstrous construct that was referred to as &#8220;The Repository Pattern on steroids.&#8221; </p>
<p>It&#8217;s one thing to permit reuse of code by decoupling interface from implementation, but it&#8217;s quite another to hobble the developer by only making available interfaces that operate on fully populated domain objects.</p>
<p>I saw places where they would set a flag in a table record by loading an object, all of it&#8217;s sub-objects, and sub-objects, with carefully constructed IF-THEN logic to subvert graph loops, then set &#8216;myPerson.Disabled = true;  PersonRepository.Save(myPerson);&#8217;.  Now its fine if you present that interface, then  detect that only the Disabled flag changed, and update just that, but what I found was quite another beast:  It proceeded to delete half of the sub-objects, re-add them, then ignore the rest of them, and do a multi-table update of the full object (without using a join, anywhere in the logic) creating a new database connection for every other call.  Needless to say, this worked brilliantly when the thing only loaded 2 or 3 master objects but when it was scaled to include ten thousand users, disabling a user, and I use this phrase QUITE LITERALLY sent the server out to lunch.  You could go to the corner store and back before it finished running a top-down depth loop of connection grabbing calls to update stuff.</p>
<p>It&#8217;s still not probably quite clear the degree of repository extremism I&#8217;m talking about here:</p>
<p>We had:<br />
PersonRepository (with methods to GetAll, GetByLocation, GetById, Update, and Delete)<br />
PersonLocationRepository (which was called repeatedly for every person loaded, even when displaying them in a dialog box, to avoid having to learn what a join is.)<br />
PersonLocationActivityRepository<br />
ActivityRepository<br />
PlacesRepository<br />
PersonEthnicityRepositiry<br />
PersonJobCodeRepository<br />
PersonHRRecordRepository<br />
PersonMotherInLawRepository (Ok, I&#8217;m making that up.)<br />
plus about 20 more (not exaggerating, I swear.)</p>
<p>That variety alone is not a problem. But calling LoadPerson or whatever the actual routine was called invoked a service locator, which loaded a bunch of other things, which called a service layer, which called a business logic layer, which then loaded a repository, which loaded a DAL object for each one of these things, DEEP. So that loading a person ended up instantiating a generic service loader factory, which created a service layer factory, and then proceeded to call a business logic layer factory, to create a DAL factory, and eventually instantiate a DAL object, to read the ethinicity of a person. Then all of those were destroyed, and the PersonHrRecord was loaded with a new chain of the same stuff.  </p>
<p>Loading the user administration page literally kicked off 300,000 database connections, and called half a million stored procedures, loaded ALL of the data client side, and filtered out the results with fancy anonymous method calls to IList enumerators.  And just because they realized what a hulking mess this was on the database, all of the results were chucked into ViewState, which to save time was chucked into the Session.</p>
<p>I, along with two others, retooled the entire project using Linq To SQL in about a month of half time working on this, but wow it was amazing.  </p>
<p>If it would have been a well crafted joke, it would have been too meticulously executed to be even considered funny.</p>
<p>My conclusion is that it&#8217;s actually bad because of the way they made the database calls. Not the patterns themselves. There was also a demonstrable lack of understanding of what the implications of iteratively looping and loading are for performance.</p>
<p>The theory, I was told, was to make it reusable.  From a design perspective, it looked like they might have been able to do that, but when I looked at what the actual layers were doing, apart from what they looked like in UML diagrams, MAN was it a mess. </p>
<p>Put another way, it&#8217;s one thing to design your application for reusablity, but quite another to implement it in the same spirit.  At the outset of the project, it probably was originally, long ago, in a galaxy far away, a good idea to design a service layer separate from business logic layer, and a DAL layer, etc.  But to just stop there and make the rest &#8216;work somehow&#8217; without concern for the consequences of the ways the data actually got into the bottom bits.. and the way that it was unfiltered until the top bits, that was just silly.  Of course I shouldn&#8217;t blame the pattern, but if they hadn&#8217;t been aiming for that methodology, as opposed to the operations that they were actually performing underneath it, it might have been a better ending.  </p>
<p>Sure it&#8217;s common to say &#8216;That&#8217;s just an implementation detail&#8217; when you&#8217;re designing, and scoff it at for a while until it comes time to implement it, but holy crap, when it comes time to implement it, all you HAVE are the implementation details.  At that point they not only deserve SOME attention, but ALL of it.</p>
<p>This is the difficulty with GoF: Pretty Conceptual Pictures. People think they understand these, and it gives them the confidence to go implement this stuff without learning the other fundamentals.  Like, well, SQL.    (I&#8217;ve actually heard things like &#8220;I&#8217;m a C# developer, I don&#8217;t really DO SQL!&#8221; If I had my way, I&#8217;d put them in a corner with a command line OSQL.exe tool for the next three months and not let them come back until they&#8217;d gone through Books Online from top to bottom three times after that statement.) Pretty pictures like this also make it easy to gloss over an actual lack of planning on the bottom so that management doesn&#8217;t know they&#8217;ve bought into a dud until the delivered app kills the clients database farm.</p>
<p>The goal of an application is to have it work.  Whatever abstractions you put on it to make it &#8216;easier to develop&#8217; are not billable features to the client.  You do not get extra line items on the proposal for Service Locator Patterns, and certainly that&#8217;s not a justification for screwing up the actual project. </p>
<p><strong>Customer&#8217;s Boss:</strong> &#8220;This thing is a piece of crap, it kills our servers!&#8221;<br />
<strong>Developer:</strong> &#8220;But it was completely decoupled from the implementation!&#8221;<br />
<strong>Customer&#8217;s Boss</strong>: &#8220;Oh, right, sorry, I guess you did actually deliver what we ordered. I&#8217;m glad you know what you&#8217;re doing when it comes to object oriented design. So many people focus solely on the final product, without so much as a thought devoted to the design process. Clearly you have attended one of our finest higher educational institutions to know such things. And besides, I didn&#8217;t realize you were a SENIOR developer, I should be yelling at a grunt code right now. You shouldn&#8217;t be troubled with implementation details.&#8221;<br />
<strong>Developers Boss:</strong> &#8220;I smell a RAISE for one of our brightest SENIOR developers!&#8221;<br />
<strong>Developer</strong>: Nancy Kerrigan and I are going to Disney Land!<br />
<br/></p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=157</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;m a convert&#8230; Well, lets say I&#8217;m Converting</title>
		<link>http://davedolan.com/blog/?p=149</link>
		<comments>http://davedolan.com/blog/?p=149#comments</comments>
		<pubDate>Fri, 16 Oct 2009 18:35:35 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[model view controller]]></category>
		<category><![CDATA[mvc]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=149</guid>
		<description><![CDATA[ASP.NET MVC. I know I&#8217;m not the first on this train. I don&#8217;t know why it took me so long&#8230; Ok, yes I do, and I&#8217;m going to tell you, in a longer than average anecdotal story about the problem: Ruby-on-Rails. People talk about Ruby like it&#8217;s the best thing since sliced Swiss cheese. And [...]]]></description>
				<content:encoded><![CDATA[<p>ASP.NET MVC.  I know I&#8217;m not the first on this train.  I don&#8217;t know why it took me so long&#8230; Ok, yes I do, and I&#8217;m going to tell you, in a longer than average anecdotal story about the problem: Ruby-on-Rails.  People talk about Ruby like it&#8217;s the best thing since sliced Swiss cheese<a href="http://zerohedge.com">.</a>  And Rails, well that&#8217;s just grilled cheese sandwiches!</p>
<p>Some people talk that way, anyway. I realize that it may be developer-reputational suicide, but I have to come clean: either I&#8217;m not enough of a geek to appreciate it, or no, it&#8217;s not [the best thing since the proverbial sliced stuff.]  Some of Ruby is great, in that it can do some things quickly with little ‘ceremonial preparation,’ but then again the syntax is so abrupt and boxy that it actually appears HARDER for me to read than C#.  This is in complete contradiction to those who assert that Ruby is so nice that you don&#8217;t even have to comment it. (Because it’s so obvious what the code is doing just by looking!)  Maybe I&#8217;m just afraid of change, or talking my book, but I&#8217;m not feeling Ruby, and Rails, (which was the quintessential example of the MVC pattern,) well they kinda left me with a less than sweet taste about the MVC concept.  </p>
<p>I know what you&#8217;re thinking here, and you&#8217;re right. It&#8217;s not a fair leap to make from &#8220;Rails is not My Thing&#8221; to the &#8220;MVC Pattern Sucks.&#8221;  I try to be rational, and reasonable, but clearly here I wasn&#8217;t. Sorry about that.</p>
<p>Now back to ASP.NET MVC.  It&#8217;s the coolest thing since sliced ASP.NET.</p>
<p>The concept of MVC made sense to me. Inversion of Control, Separation of Concerns, Dependency Injection, convention over configuration, testability&#8230; even back from my Rails tribulations. But I still didn&#8217;t feel it.  It was someone else&#8217;s sense making not mine.</p>
<p>So then I decided I&#8217;d try to learn this jQuery thing&#8230; and I started playing around with raw HTML pages, throwing some jQuery into them in script tag after tag, and suddenly it hit me&#8230; Handling updates client side was great, simple, and often light. If all I had to do was juggle CSS classes and read a few fields here and there, Post a single variable now and again, I didn’t need the whole ball of wax!  But, using web forms, you don’t have much of a choice.  It was not fun having to register client scripts every time with a control’s server generated client name to go with controls that used the INamingContainer model.  I started using the CssClass attribute quite improperly to get a grip on elements that should just have been simple enough to grab by ID.  And then finally, the last straw was when I ran into a string of ViewState validation errors.  Now, if you&#8217;re using ViewState, fine, there is a good reason to want ASP.NET to validate it. But I wasn&#8217;t using it, and ViewState was just an incidental side effect of the fact that web forms hate people who are using JavaScript.</p>
<p>So now that I had developed a new passion for everything jQuery, from the flashy jQuery UI, to simple things, I had to find a way to keep feeding it.  Such ‘fancy’ sounding things were kids play now, like automatically italicizing certain text artifacts for fun and profit, or making post backs nothing but a service call or two. Services, as it turned out, were very comparable to Controllers, and in fact, could be serviced just as easily by Controllers as they could by ‘real services.’  Models were already familiar &#8212; I know about the repository pattern, I’ve done that quite a lot, even before I’d ever heard of ASP.NET MVC or indeed even Ruby on Rails. So the only things left to ‘get’ were the fact that both the view and the model were to be instantiated by the controller and called and returned (respectively.)  The idea wasn’t foreign to me, but it now suddenly clicked.  “Wait! This works, and I don’t have to worry about some of the things I spent time worrying about before.”  Not to mention that the integration with Visual Studio is great. Another big bonus was the URL structure was nicer.</p>
<p>It took me a bit to realize that I was supposed to write custom html helpers, or still better, encapsulate  the helper stuff into the equivalent of a ViewModel class that will do the html helping it its own logic.</p>
<p>So, I realize there is nothing really profound or new I’ve been talking about here, but I just have been so moved by ASP.net MVC that I had to say something about it.  I think I’ll try to stick with using it wherever I can.  The One Complaint that I do have with it is that SharePoint doesn’t support it, and I support SharePoint. Oh well. I always knew SharePoint wasn’t perfect either.</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&#038;p=149</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
