<?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/"
  >

<channel>
  <title>CodeGear TeamB Blogs Master Site Feed</title>
  <link>http://blogs.teamb.com/feeds</link>
  <description>Shows all posts, comments, and pages from all blogs on this WPMU powered site</description>
  <pubDate>Tue, 16 Jun 2009 11:55:48 +0000</pubDate>
  <generator>http://wordpress.org/?v=2.6.2</generator>
  <language>en</language>
  <item>
    <title>Columbus Give Camp</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/06/16/38321/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/06/16/38321/#comments</comments>
    <pubDate>Tue, 16 Jun 2009 11:55:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38321</guid>
    <description><![CDATA[If you&#8217;re a geek in the Central Ohio area, please consider volunteering for Columbus Give Camp, if your schedule permits.
]]></description>
      <content:encoded><![CDATA[<p>If you&#8217;re a geek in the Central Ohio area, please consider volunteering for <a href="http://www.columbusgivecamp.org/GiveCamp/">Columbus Give Camp</a>, if your schedule permits.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38321&amp;akst_action=share-this" onclick="akst_share('38321', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F16%2F38321%2F', 'Columbus+Give+Camp'); return false;" title="Post to del.icio.us, etc." id="akst_link_38321" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Columbus%20Give%20Camp&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F16%2F38321%2F" id="akst_email_38321" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>In LINQ, Beware of Skip(0)</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/06/10/38313/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/06/10/38313/#comments</comments>
    <pubDate>Wed, 10 Jun 2009 19:29:44 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38313</guid>
    <description><![CDATA[Calling IQueryable&#60;T&#62;.Skip(0) seems like it should be "free." In other words, since it will have no effect on the resulting data, there should be little to no performance cost for calling it. But this is demonstrably not true in LINQ to Entities, and it occurs to me that LINQ providers are not required to optimize [...]]]></description>
      <content:encoded><![CDATA[<p>Calling <code>IQueryable&lt;T&gt;.Skip(0)</code> <em>seems</em> like it should be "free." In other words, since it will have no effect on the resulting data, there should be little to no performance cost for calling it. But this is demonstrably not true in LINQ to Entities, and it occurs to me that LINQ providers are not required to optimize it away. Therefore, it is probably a good idea to avoid making such a call at all, so that you do not have to concern yourself with whether the provider will generate a slower query if you do it.</p>
<p>Unfortunately, it is not just your own code you need to be concerned with. It turns out that some fairly popular LINQ helpers do this. For example, <a href="http://blog.wekeroad.com/blog/aspnet-mvc-pagedlistt/">Rob Connery&#8217;s PagedList&lt;T&gt;</a> type does it:</p>
<blockquote>
<pre><code><strong>public </strong>PagedList(IQueryable&lt;T&gt; source, <strong>int</strong> index, <strong>int</strong> pageSize)
{
    <strong>this</strong>.TotalCount = source.Count();
    <strong>this</strong>.PageSize = pageSize;
    <strong>this</strong>.PageIndex = index;
    <strong>this</strong>.AddRange(source.Skip((index - 1) * pageSize).Take(pageSize).ToList());</code></pre>
</blockquote>
<p>Index, in this code, is the 1-based page you&#8217;d like to display. When index is 1, the code calls Skip(0), and you get less efficient SQL. Fixing the problem is quite simple:</p>
<blockquote>
<pre><code>    <strong>this</strong>.PageIndex = index;
    var pageData = index &gt; 1 ?
        source.Skip((index - 1) * pageSize).Take(pageSize) : source.Take(pageSize);
    this.AddRange(pageData.ToList());</code></pre>
</blockquote>
<p>Naturally, this only optimizes SQL generation for the first page of results, but since this is by far the most common page a user might display, it can net you a substantial win in server performance.</p>
<p><a href="http://www.squaredroot.com/2008/07/08/PagedList-Strikes-Back/">Troy Goode&#8217;s updated PagedList type</a>, which I have recommended in the past (and still do, with this tweak!), has the same problem. The solution is almost identical, although Troy&#8217;s type is 0-based rather than 1-based. <strong>Update:</strong> <a href="http://pagedlist.codeplex.com/">Troy has now posted an update</a> containing this fix, among many other changes.</p>
<p>The root of the problem in the SQL generation is that when you call Skip(0), LINQ to Entities, in at least some cases, generates SQL like this:</p>
<blockquote><p><code>)  <strong>AS </strong>[Project3]<br />
<strong>WHERE </strong>[Project3].[row_number] &gt; 0<br />
<strong>ORDER BY</strong> [Project3].[TimeRecordDate] <strong>DESC</strong></code></p></blockquote>
<p>The reference to <code>row_number</code> can have a substantial performance impact. In one case I tried with a SQL Server table containing just over 1 million rows, a simple query ran with sub-second performance without this WHERE clause, and over 4 seconds with the WHERE clause, even though the result set was exactly the same.</p>
<p>Now, is this a bug in LINQ to Entities? Or LINQ itself? It&#8217;s hard to say. Both frameworks are doing exactly what you tell them to, even though it doesn&#8217;t make a lot of sense. It seems like a missed opportunity for optimization, but I&#8217;m open to the possibility that there might be some desirable effect of this that I have simply missed. For my own purposes, I am content to simply not call Skip(0) at all.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38313&amp;akst_action=share-this" onclick="akst_share('38313', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F10%2F38313%2F', 'In+LINQ%2C+Beware+of+Skip%280%29'); return false;" title="Post to del.icio.us, etc." id="akst_link_38313" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=In%20LINQ%2C%20Beware%20of%20Skip%280%29&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F10%2F38313%2F" id="akst_email_38313" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Early Turbo Pascal History on Hanselminutes</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/05/14/38310/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/05/14/38310/#comments</comments>
    <pubDate>Thu, 14 May 2009 17:27:45 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38310</guid>
    <description><![CDATA[In the most recent episode of Hanselminutes, Scott chats with founders of Mustang Software (creators of Wildcat! BBS) Jim Harrer and Scott Hunter about the BBS era. Wildcat! was written in Turbo Pascal, and Harrer and Hunter state that it was one of the first major applications developed in that language. In the first part [...]]]></description>
      <content:encoded><![CDATA[<p>In the most recent episode of Hanselminutes, <a href="http://www.hanselminutes.com/default.aspx?showID=179">Scott chats with founders of Mustang Software (creators of Wildcat! BBS) Jim Harrer and Scott Hunter about the BBS era</a>. Wildcat! was written in Turbo Pascal, and Harrer and Hunter state that it was one of the first major applications developed in that language. In the first part of the show, they discuss going to California to meet with the Turbo Pascal team, visiting Anders Hejlsberg&#8217;s house, and more early history.</p>
<p>It&#8217;s worth a listen if you&#8217;re interested in the history of the product which started Borland and evolved into Delphi.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38310&amp;akst_action=share-this" onclick="akst_share('38310', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F14%2F38310%2F', 'Early+Turbo+Pascal+History+on+Hanselminutes'); return false;" title="Post to del.icio.us, etc." id="akst_link_38310" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Early%20Turbo%20Pascal%20History%20on%20Hanselminutes&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F14%2F38310%2F" id="akst_email_38310" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using DayPilot with ASP.NET MVC</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/05/12/38297/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/05/12/38297/#comments</comments>
    <pubDate>Tue, 12 May 2009 12:45:31 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38297</guid>
    <description><![CDATA[I&#8217;m going to demonstrate how to use the open-source DayPilot Lite calendar control in an ASP.NET MVC application. I will discuss the capabilities of the control and consider the general problem of how to use controls designed for "plain" ASP.NET in MVC applications. I&#8217;m including a demo solution which you can download and run yourself.
Download [...]]]></description>
      <content:encoded><![CDATA[<p>I&#8217;m going to demonstrate how to use the open-source <a href="http://www.daypilot.org/daypilot-lite.html">DayPilot Lite calendar control</a> in an ASP.NET MVC application. I will discuss the capabilities of the control and consider the general problem of how to use controls designed for "plain" ASP.NET in MVC applications. I&#8217;m including a demo solution which you can download and run yourself.<a href="/files/2009/05/daypilot_1277.zip"></a></p>
<p><strong>Download the demo solution: </strong><a href="/files/2009/05/daypilot_1277.zip">DayPilot ASP.NET MVC demo</a></p>
<p>We needed a calendar control for an ASP.NET MVC application. In particular, we needed a control which would show a number of events and when they occur within a particular day, "Outlook-style." I&#8217;ll include a screenshot of the demo application here, since it&#8217;s the best way to explain the type of control we were looking for:</p>
<div id="attachment_38298" class="wp-caption aligncenter" style="width: 295px"><a href="/files/2009/05/daypilot_1274.png"><img src="/files/2009/05/daypilot_1274-285x300.png" alt="DayPilot example" width="285" height="300" /></a><p class="wp-caption-text">DayPilot example</p></div>
<h3>Possible Alternatives to DayPilot</h3>
<p>In my experience, the type of control which works best with ASP.NET MVC is a control which is completely ignorant of ASP.NET, and all the <a href="http://blog.wekeroad.com/blog/i-spose-ill-just-say-it-you-should-learn-mvc/">lies such as ViewState and postbacks</a> which accompany it. In particular, I&#8217;ve had a good deal of success with controls designed for the jQuery JavaScript framework, which is included, by default, with ASP.NET MVC applications. Unfortunately, I was unable to find a jQuery control which data what we needed. The closest I found was <a href="http://www.bytecyclist.com/projects/jmonthcalendar/">jMonthCalendar</a> which cannot display a single day in the manner illustrated above. I would still prefer a jQuery-based solution if one ever turns up.</p>
<p>I did, however, find a couple of controls designed for "plain" ASP.NET which, from an end-user point of view, it exactly what we needed. One was the DayPilot control illustrated above, the other was <a href="http://www.telerik.com/products/aspnet-ajax/scheduler.aspx">the scheduler component included with Telerik&#8217;s control suite</a>. Telerik&#8217;s control claims some support for MVC, but this is really limited to loading calendar data asynchronously, which was not actually what we wanted to do. Also, Telerik&#8217;s control can only be purchased as part of their suite, which is rather expensive if you only need the calendar/scheduler control. Paying for the entire suite would not be a problem for us if it was filled with controls we needed, designed for the environment (MVC) we use. While Telerik seems serious about supporting MVC, they are in the early stages right now, so it is difficult to justify paying for a large suite in order to get a single control, which I would have to use in a mostly-unsupported way. The Telerik control has many more features than the DayPilot control, and, in my opinion, looks a little nicer.</p>
<p>The DayPilot calendar is available in two different editions. There is an open source edition, which is free, and a non-open-source edition, which <a href="http://www.daypilot.org/compare-versions.html">adds features</a>. The principal difference is that the date version includes editing (via postbacks) and UpdatePanel support, which are not really useful in an ASP.NET MVC application anyway. As with Telerik&#8217;s control, I have to adapt the control for use within ASP.NET MVC. So we selected the open source version, even though the paid version is priced reasonably.</p>
<h3>Adapting DayPilot to ASP.NET MVC</h3>
<p>In order to use the DayPilot control in ASP.NET MVC, I wanted to use markup which would look familiar to ASP.NET MVC developers:</p>
<blockquote>
<pre><code>&lt;%= Html.DayPilot(Model, <strong>new</strong> DayPilotViewOptions
                             {
                                 HourHeight = 30
                             }) %&gt;</code></pre>
</blockquote>
<p>This means that I needed to write an Html helper which will render the control based on the data passed in Model and return the literal HTML markup. In order to make that easier, I created two new types, DayPilotData and DayPilotViewOptions, in order to encapsulate access to the properties of the control. The reason I created two different types was to separate the concerns of data for the events (which will be set up in the controller) and display of the control (which is the concern of the view). The types are trivial, so I&#8217;m not going to show them in this post, but you can examine them in the demo solution. There is an overload to this Html helper which does not include the options argument in case you are happy with the defaults.</p>
<blockquote>
<pre><code><strong>        public static string</strong> DayPilot(
            <strong>this</strong> HtmlHelper helper,
            DayPilotData model,
            DayPilotViewOptions options)
        {
            <strong>var</strong> calendar = <strong>new</strong> DayPilotCalendar();
            <strong>if</strong> (model != null)
            {
                model.CopyTo(calendar);
            }
            <strong>if</strong> (options != null)
            {
                options.CopyTo(calendar);
            }
            <strong>var</strong> sb = <strong>new</strong> System.Text.StringBuilder();
            sb.Append("&lt;div class=\"dayPilot\"&gt;"); // allows working around td cellpadding bug in css
            <strong>using</strong> (<strong>var</strong> sw = <strong>new</strong> System.IO.StringWriter(sb))
            {
                <strong>using</strong> (<strong>var</strong> tw = <strong>new</strong> HtmlTextWriter(sw))
                {
                    calendar.RenderControl(tw);
                }
            }
            sb.Append("&lt;/div&gt;");
            <strong>return</strong> sb.ToString();
        }</code></pre>
</blockquote>
<p>Note the div. The current version of DayPilot astonishingly, as of this writing, does not put a class anywhere in its rendered markup. Since the stylesheet for the default ASP.NET MVC site conflicts with DayPilot, to some degree, I wrapped the whole control in a div so that I could fix the layout in CSS.</p>
<p>Another way which I could have used the control in ASP.NET MVC would be to register a tag prefix and use code behind/code generation, as with standard ASP.NET. I&#8217;ve registered a tag prefix in the demo solution in case you want to try that yourself. Be aware, however, that setting up codebehind and code generation files in an MVC application is somewhat less than simple; doing it right requires, among other things, manual editing of the csproj file. So I do recommend using the control in the way I&#8217;ve illustrated.</p>
<p>Finally, here&#8217;s the source code for the action which supplies data for the control. Since this is a demo solution, I&#8217;m generating random events:</p>
<blockquote>
<pre><code><strong>        public</strong> ActionResult Index()
        {
            <strong>var</strong> r = <strong>new</strong> Random();
            <strong>var</strong> q = <strong>from</strong> i <strong>in</strong> Enumerable.Range(1, 4)
                    <strong>let</strong> start = DateTime.Today.AddHours(r.Next(47))
                    <strong>select new</strong> DayPilotDataItem
                    {
                        Id = i,
                        Start = start,
                        End = start.AddHours(1),
                        Text = string.Format("Event {0}", i)
                    };
            <strong>var</strong> model = <strong>new</strong> DayPilotData
            {
                StartDate = DateTime.Today,
                Days = 2,
                Data = q
            };
            <strong>return</strong> View(model);
        }</code></pre>
</blockquote>
<p>Of course, it&#8217;s just as easy to select data from a database.</p>
<p>The current version of DayPilot has a kind of a weird limitation: You cannot make it smaller, in the vertical dimension, than 30 pixels per hour. Based on some inspection of the source code, I think this is fixable if you are comfortable altering the source. But be aware of the limitation.</p>
<p>There are more DayPilot features which I have not covered, but that should be enough to get you on your way. If you have any questions, post them in comments, and I&#8217;ll see whdat I can do to help out.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38297&amp;akst_action=share-this" onclick="akst_share('38297', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F12%2F38297%2F', 'Using+DayPilot+with+ASP.NET+MVC'); return false;" title="Post to del.icio.us, etc." id="akst_link_38297" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20DayPilot%20with%20ASP.NET%20MVC&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F12%2F38297%2F" id="akst_email_38297" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Understanding LINQ Errors</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/05/05/38274/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/05/05/38274/#comments</comments>
    <pubDate>Tue, 05 May 2009 11:26:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38274</guid>
    <description><![CDATA[If you spend enough time with the PagedList class that I&#8217;ve been using for paging in the method which supplies data to jqGrid, it&#8217;s a near-certainty that sooner or later you will see a LINQ error with Count in the call stack. The error may seem confusing, because it has nothing to do with Count. [...]]]></description>
      <content:encoded><![CDATA[<p>If you spend enough time with the PagedList class that I&#8217;ve been using for paging in <a title="LINQ Extensions" href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">the method which supplies data to jqGrid</a>, it&#8217;s a near-certainty that sooner or later you will see a LINQ error with Count in the call stack. The error may seem confusing, because it has nothing to do with Count. Commentor Graeme has been experimenting with <a href="/files/2009/04/griddemo_1256.zip">my demo solution</a>, and <a href="http://blogs.teamb.com/craigstuntz/2009/04/27/38243/#comment-6168">has run into just this issue</a>:</p>
<blockquote><p>Finding your blogs very helpful - superbly written - just found out about jqgrid last night and have integrated your code into my project.</p>
<p>One thing that didn’t work for me though was the dates fix above…</p>
<p>adding</p>
<p><code>.ToString(System.Globalization.CultureInfo.CurrentUICulture)</code></p>
<p>onto the end of my <code>DateTime </code>values makes everything render Ok but when I try doing a search, it fails. Debugging shows the error is</p>
<p>Method ‘<code>System.String ToString(System.IFormatProvider)</code>’ has no supported translation to SQL.</p>
<p>at the <code>TotalItemCount = source.Count();</code> line of the PagedList.cs file.</p>
<p>Any ideas?</p></blockquote>
<p>In order to understand this error, we need to remember several important things about LINQ:</p>
<ul>
<li>LINQ is lazy. Creating or modifying an IQueryable with methods like <code>Where</code>, <code>Take</code>, <code>OrderBy</code>, etc. does not actually execute the query. The query will only be executed when you call a LINQ method which requires execution to produce its results — like <code>Count</code>.</li>
<li>When a LINQ query expression includes something which looks like a method call, the method is not invoked directly. Instead, what is actually produced is an <a href="http://msdn.microsoft.com/en-us/library/bb397951.aspx"><code>Expression</code></a> representing that method. If the LINQ provider happens to be LINQ to Objects, the method will eventually be invoked when the query is executed. But if it happens to be LINQ to SQL or LINQ to Entities, the method may never be invoked, and instead might be replaced (if possible) with equivalent SQL.</li>
<li>Most LINQ providers do not support every possible LINQ query expression. Most providers don&#8217;t even support the entire LINQ API, and only LINQ to Objects can be presumed to support all method calls on an object in a query. In some cases, <a title="Supported and Unsupported Methods (LINQ to Entities)" href="http://msdn.microsoft.com/en-us/library/bb738550.aspx">as with LINQ to Entities, this is documented</a>. With other providers, you may have to guess/experiment. Any LINQ provider which has to translate a LINQ query expression into SQL syntax can only really support methods which it is hard-coded to recognize. Worse, it is not even uncommon for providers to support one overload of a particular method but not a different overload of the same method. See, for example, the LINQ to Entities document I just linked or the <code>ToString</code> method, which is generally supported in LINQ to Entities/SQL, but has a special overload on the <code>DateTime </code>type which is not supported. Worse still, method calls may be supported in some contexts but not others. Graeme reports that LINQ to SQL accepted the <code>ToString</code> overload in the context of a <code>Select</code>, but not in the context of a <code>Where</code>. This makes sense from an implementation point of view, but means programmers have to be extraordinarily careful about what we include in our LINQ queries, especially when they are constructed dynamically.</li>
</ul>
<p>By now it should be obvious what is going on here: The particular overload of <code>ToString</code> which I used in my example is supported in LINQ to Objects but not in LINQ to SQL in a <code>Where</code> expression. My demo solution used a repository based on LINQ to Objects, so the query I showed worked correctly there. But it does not work with LINQ to SQL. Because LINQ is lazy, you will not actually see an error about this until the query is translated into SQL by the LINQ provider, and that does not happen until the call to <code>Count</code> in <code>PagedList</code>.</p>
<p>This means that when you write a LINQ query expression using LINQ to SQL, LINQ to Entities, etc., you are essentially working in a partially dynamic language. Unless you study the documentation very, very carefully, you will not know for certain until runtime if your query will be accepted by the provider.</p>
<p>So how could we work around this problem?</p>
<ul>
<li>Use a different method or a different overload which is supported by the LINQ provider used in your project. This is fine if an appropriate method/overload exists.</li>
<li>Give up on doing the formatting in C# and use JavaScript instead. This will work, but it&#8217;s a bit like using beheading to cure acne. C# is, after all, a general-purpose programming language. We should not have to give up on formatting a date.</li>
<li>Bring the query into LINQ to Objects using a method such as <code>AsEnumerable</code>. Obviously, we would want to apply the paging and ordering first. In this method, we would execute one query (using LINQ to SQL or something) which would retrieve an ordered list of records for the specified page, using <code>AsEnumerable</code> to transform the results into a List. We would then execute a LINQ to Objects query against this list in order to perform the formatting. This will actually work OK, although it can end up being a good bit of code to write for what should be a fairly simple task.</li>
<li>Write a new LINQ provider which understands the method in question. This seems like an enormous amount of work, but I&#8217;ll include it for completeness.</li>
<li>Separate the concerns of serialization and querying. You can tell by the 50-cent words that this is the solution I prefer. <img src='http://blogs.teamb.com/feeds/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>Remember, the original query worked just fine. It is only the serialization to JavaScript which caused unexpected results. One way to fix this is to hide the members which are problematic to serialize and replace them with a string version of same:</p>
<blockquote>
<pre><code><strong>private class</strong> JavaScriptDateFixer
{
    [NonSerialized]
    <strong>internal </strong>DateTime _date;
    <strong>public int</strong> Id { <strong>get; set; </strong>}
    <strong>public int</strong> IntProperty { <strong>get; set; </strong>}
    <strong>public string </strong>StringProperty { <strong>get; set</strong>; }
    <strong>public string </strong>DateProperty { <strong>get </strong>{ <strong>return </strong>_date.ToString(System.Globalization.CultureInfo.CurrentUICulture); } }
}

<strong>public</strong> ActionResult GridDemoData(<strong>int </strong>page, <strong>int </strong>rows,<strong> string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
{
    <strong>var </strong>repository = <strong>new </strong>Repository();
    <strong>var </strong>model = <strong>from </strong>entity <strong>in </strong>repository.SelectAll().OrderBy(sidx + " " + sord)
                <strong>select new </strong>JavaScriptDateFixer
                {
                    Id = entity.Id,
                    IntProperty = entity.IntProperty,
                    StringProperty = entity.StringProperty,
                    _date = entity.DateProperty
                };
    <strong>return </strong>Json(model.ToJqGridData(page, rows, <strong>null</strong>, search,
        <strong>new</strong>[] { "IntProperty", "StringProperty", "DateProperty" }));
}
</code></pre>
</blockquote>
<p>Note that even though this code looks quite different, this does almost exactly the same thing as the code I&#8217;ve replaced. The only real difference is that I&#8217;ve delayed the call to ToString until after the query is executed. That&#8217;s enough to keep LINQ to SQL or LINQ to Entities happy.</p>
<p>So with this fix is everything fine? Maybe. I really like LINQ; I think it&#8217;s an extraordinarily powerful tool. But here we have hit upon what I consider to be the single biggest problem with LINQ. The combination of very limited support for all possible query expressions in common LINQ providers like LINQ to SQL and building queries dynamically can be very dangerous. Unless you test all possible query permutations, you cannot be completely confident that any query you build will actually execute successfully. In typical dynamic language programming, you mitigate this problem by writing unit tests. But unit tests are not supposed to connect to a database. Unfortunately, the limitation here is that the point of translation to SQL. So any unit test which mocked the LINQ provider, say, using LINQ to Objects or some other in-memory representation would not actually encounter the limitations we are trying to test.</p>
<p>I have yet to see a really good solution for unit testing LINQ to SQL or LINQ to Entities, one which would combine the desired attributes of not actually connecting to the database while surfacing any potential problems in SQL generation. I suspect that such a beast may never exist for LINQ to SQL, but for LINQ to Entities it seems at least possible. One could write an Entity Framework provider which returns mocked instances of entities. Any LINQ syntax not understood by the Entity Framework would be caught before the mock provider was ever invoked. This is a feature I would like to see in a future version of the Entity Framework.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38274&amp;akst_action=share-this" onclick="akst_share('38274', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F05%2F38274%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Understanding+LINQ+Errors'); return false;" title="Post to del.icio.us, etc." id="akst_link_38274" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Understanding%20LINQ%20Errors&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F05%2F38274%2F" id="akst_email_38274" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>jQuery Index Inconsistency</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/30/38271/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/30/38271/#comments</comments>
    <pubDate>Thu, 30 Apr 2009 12:15:02 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38271</guid>
    <description><![CDATA[The jQuery :nth-child selector has an "index" argument which is 1-based. But the jQuery "index" method, which is arguably the converse of the selector, returns a 0-based result. This is very easy to work around once you&#8217;re aware of it, but it&#8217;s surprising in a library which is, generally, designed both well and consistently.
Share This [...]]]></description>
      <content:encoded><![CDATA[<p>The jQuery <a title="      * Main Page     * Downloading jQuery     * How jQuery Works     * FAQ     * Tutorials     * Using jQuery with Other Libraries     * Variable Types  API Reference      * jQuery Core     * Selectors     * Attributes     * Traversing     * Manipulation     * CSS     * Events     * Effects     * Ajax     * Utilities     * jQuery UI  Plugins      * Plugin Repository     * Authoring  Support      * Mailing List and Chat     * Submit New Bug  About jQuery      * Contributors     * History of jQuery     * Sites Using jQuery     * Browser Compatibility     * Licensing     * Donate  Toolbox      * What links here     * Related changes     * Upload file     * Special pages     * Printable version     * Permanent link  Views      * Article     * Discussion     * Edit     * History  Personal tools      * Log in / create account  Selectors/nthChild" href="http://docs.jquery.com/Selectors/nthChild#index">:nth-child selector has an "index" argument which is 1-based</a>. But the jQuery "index" method, which is arguably the converse of the selector, <a title=" Core/index" href="http://docs.jquery.com/Core/index#subject">returns a 0-based result</a>. This is very easy to work around once you&#8217;re aware of it, but it&#8217;s surprising in a library which is, generally, designed both well and consistently.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38271&amp;akst_action=share-this" onclick="akst_share('38271', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F30%2F38271%2F', 'jQuery+Index+Inconsistency'); return false;" title="Post to del.icio.us, etc." id="akst_link_38271" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=jQuery%20Index%20Inconsistency&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F30%2F38271%2F" id="akst_email_38271" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Deleting Records</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/29/38266/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/29/38266/#comments</comments>
    <pubDate>Wed, 29 Apr 2009 15:46:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38266</guid>
    <description><![CDATA[This is the fifth post in a series on using jqGrid with ASP.NET MVC. Today, we’re going to begin examining the grid&#8217;s editing features by implementing deletes. If you’re new to the series, you might want to start at the beginning.
The delete feature of jqGrid is, oddly, almost entirely undocumented, even though there quite a [...]]]></description>
      <content:encoded><![CDATA[<p>This is the fifth post in a series on using jqGrid with ASP.NET MVC. Today, we’re going to begin examining the grid&#8217;s editing features by implementing deletes. If you’re new to the series, you might want to start at <a title="Introduction" href="/craigstuntz/2009/04/14/38200/">the beginning</a>.</p>
<p>The delete feature of jqGrid is, oddly, almost entirely undocumented, even though there quite a few examples of different methods of <a href="http://www.secondpersonplural.ca/jqgriddocs/index.htm">editing</a>, and inserts are documented, to a lesser extent. But it does exist; I just had to read the source code to figure out how it works.</p>
<p>JqGrid has three different methods of editing data. The cell edit feature allows the user to edit a single cell the grid at a time, and saves the data when the cell loses focus. The row edit feature works similarly, but does not save the data until the row loses focus. The form edit feature shows a modal dialog instead of editing the values inline. Of these three, the form edit feature is the only one which supports deletes. However, you can still use one of the other "modes" for editing, if you like. Just be aware that when you do a delete, you will be in the form edit code. Also, deletes won&#8217;t work if you change the grid&#8217;s configuration to disable the form edit feature.</p>
<p>In order to allow the user to delete a row, I need to:</p>
<ul>
<li>Add a delete button to the grid&#8217;s toolbar. I could, of course, use a custom button or something instead of the grid&#8217;s toolbar if I chose to do so.</li>
<li>Specify a URL for the delete action</li>
<li>Implement a delete action on the controller</li>
</ul>
<p>I can accomplish the first two tasks by making a slight change to the JavaScript that configures the grid:</p>
<blockquote><p><code>}).<a href="http://www.secondpersonplural.ca/jqgriddocs/_2er0j2mvk.htm">navGrid</a>(pager, { edit: false, add: false, del: <strong>true</strong>, search: false }<strong>, {}, {}, {url: "Delete"}</strong>);</code></p></blockquote>
<p>I&#8217;ve highlighted the parts I&#8217;ve changed in boldface. Changing the "<code>del</code>" property to true turns on the toolbutton. The fifth argument is an object specifying options for the delete action, of which I have only specified the URL. This is important: The only places you can specify the URL for delete are in the arguments to the <code>delGridRow</code> method or in the toolbar&#8217;s configuration. There is not a "delete URL" property of the grid itself.</p>
<p>If you don&#8217;t specify a delete URL in this way, the grid will presume that you want to send delete requests to the URL you have specified for editing rows. There will be an "<code>oper</code>” value in the submitted form indicating that the request is a delete rather than an edit. But I prefer to use a separate URL for delete, because I think that fits more naturally in the ASP.NET MVC paradigm.</p>
<p>Now let&#8217;s write an action to handle the delete:</p>
<blockquote>
<pre><code>[AcceptVerbs(HttpVerbs.Post)]
<strong>public </strong>ActionResult Delete(<strong>int </strong>id)
{
    <strong>var </strong>repository = <strong>new </strong>Repository();
    <strong>var </strong>deleted = repository.Delete(id);
    <strong>if </strong>(!deleted)
    {
        Response.StatusCode = 500;
        <strong>return </strong>Content("Record not found.");
    }
    <strong>return </strong>Json(true);
}</code></pre>
</blockquote>
<p>Again, I&#8217;ll note that I&#8217;m using a mock repository for this demo so that you can compile and run the solution without needing to set up a database. Since the mock repository is based on IList, the Delete method of the repository returns a Boolean indicating whether or not the requested record was found, since that is how IList behaves. It would probably be more correct to return a partial view in the event of an error rather than specifying the contents directly, but error handling is a subject I hope to cover in more depth later on. For the time being, simply changing the StatusCode will tell the grid when something does not work.</p>
<p>If the delete was successful, I return "true." By default, the grid ignores returned data when the operation is successful. However, you can handle the grid&#8217;s afterSubmit event, which will be passed any data you do return. So what you choose to return, and what you do with it, is entirely up to you.</p>
<p>With all that in place, deletes work as expected. I&#8217;m not going to update the demo solution just yet, because I&#8217;ll be covering edits and inserts <a href="http://catb.org/jargon/html/R/Real-Soon-Now.html">real soon now</a>. But first I need to <a title="Understanding LINQ Errors" href="http://blogs.teamb.com/craigstuntz/2009/05/05/38274/">revisit formatting and explain more about LINQ</a>".</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38266&amp;akst_action=share-this" onclick="akst_share('38266', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F29%2F38266%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Deleting+Records'); return false;" title="Post to del.icio.us, etc." id="akst_link_38266" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Deleting%20Records&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F29%2F38266%2F" id="akst_email_38266" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Search and Formatting</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/27/38243/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/27/38243/#comments</comments>
    <pubDate>Mon, 27 Apr 2009 12:44:54 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38243</guid>
    <description><![CDATA[This is the fourth post in a series on using jqGrid with ASP.NET MVC. Today, we&#8217;re going to examine search and formatting results. I will implement a search feature and fix the problem with formatting date columns which I observed in the last post. I&#8217;ve updated the demo solution with these new features, and also [...]]]></description>
      <content:encoded><![CDATA[<p>This is the fourth post in a series on using jqGrid with ASP.NET MVC. Today, we&#8217;re going to examine search and formatting results. I will implement a search feature and fix the problem with formatting date columns which I observed in <a title="Finally, A Solution" href="http://blogs.teamb.com/craigstuntz/2009/04/17/38229/">the last post</a>. I&#8217;ve updated the <strong><a href="/files/2009/04/griddemo_1256.zip">demo solution</a></strong> with these new features, and also fixed <a href="http://blogs.teamb.com/craigstuntz/2009/04/17/38229/#comment-5754">a bug reported by <span class="comment-author vcard"><span class="fn n">Andrey</span></span></a> last time. If you&#8217;re new to the series, you might want to start at <a title="Introduction" href="http://blogs.teamb.com/craigstuntz/2009/04/14/38200/">the beginning</a>.</p>
<p>First, let&#8217;s fix the date display. The reason the <a href="http://blogs.teamb.com/files/2009/04/jqgriddemoapp1_1192.png">date appeared so oddly</a> is that there is no official support for Date types in JSON, even though JavaScript has a date type. Microsoft, therefore, invented their own way of encoding dates for their JSON serializer, which jqGrid does not understand. There are two possible ways to fix the problem. The first is to keep sending the data to the grid in the Microsoft format, and write a <a href="http://www.secondpersonplural.ca/jqgriddocs/_2kn0mlo1p.htm">custom formatter for the grid</a> to parse that into a human-readable string. The second is to change the data we send to the grid. Both ways work, but I&#8217;m going to demonstrate the second method, mostly because I find C#&#8217;s date handling features superior to (<a title="date basics" href="http://blog.boyet.com/blog/javascriptlessons/javascript-for-c-developers-date-basics/">and less confusing than</a>) JavaScript&#8217;s.</p>
<p>In order to change the date "column" in the results of the query to a formatted string, we simply need to project into an anonymous type. However, this would break the sort, because a text sort on a formatted date will not be in the correct order. Hence, it is necessary to apply the sort before projecting. So I add an OrderBy to the query, and pass null as the <code>orderBy</code> argument to the <code>ToJqGridData</code> method.</p>
<blockquote>
<pre><code><strong>public </strong>ActionResult GridDemoData(<strong>int </strong>page, <strong>int </strong>rows, <strong>string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
{
    <strong>var </strong>repository = <strong>new </strong>Repository();
    <strong>var </strong>model = <strong>from </strong>entity <strong>in </strong>repository.SelectAll().OrderBy(sidx + " " + sord)
                <strong>select new</strong>
                {
                    Id = entity.Id,
                    IntProperty = entity.IntProperty,
                    StringProperty = entity.StringProperty,
                    DateProperty = entity.DateProperty.ToString(
                        System.Globalization.CultureInfo.CurrentUICulture)
                };
    <strong>return </strong>Json(model.ToJqGridData(page, rows, <strong>null</strong>, search,
        <strong>new</strong>[] { "IntProperty", "StringProperty", "DateProperty" }));
}</code></pre>
</blockquote>
<p>Note that in this revised solution I&#8217;ve updated the mock repository to return more sensible dates.</p>
<p><strong>Important update:</strong> This code works correctly with LINQ to Objects, as with my demo repository, but will not work with LINQ to SQL. <a title="Understanding LINQ Errors" href="http://blogs.teamb.com/craigstuntz/2009/05/05/38274/">I have addressed this issue in a subsequent post</a>.</p>
<p>Now let&#8217;s add a search feature. One of the problems in making a "demo" search is that search is a highly application-specific feature, both in terms of implementation and in terms of user experience. JqGrid&#8217;s search feature presumes that you want a search which looks something like this:</p>
<p><a href="/files/2009/04/jqgridsearchform_1250.png"><img src="/files/2009/04/jqgridsearchform_1250.png" alt="" width="411" height="61" /></a></p>
<p>Visually, there are lots of variations on this theme available, but in terms of the use case they all presume that the user will specify which fields she would like to search. However, I prefer a "Google-style" interface with just a search box and an implementation that can (hopefully) figure out what the user actually wants. So that&#8217;s what I&#8217;m going to demonstrate. The needs of your application may be different. The important thing to take away from this demonstration is that the jqGrid search feature can be co-opted to fit <em>your </em>design.</p>
<p>I want the search box to appear above the grid at all times, rather than requiring the user to press a toolbutton to see it. So first I need to add an empty div to the markup in order to indicate where the search box will be positioned, relative to the grid:</p>
<blockquote>
<pre><code>    &lt;h2&gt;GridDemo&lt;/h2&gt;
    &lt;div id="search"&gt;&lt;/div&gt;
    &lt;table id="grid" class="scroll" cellpadding="0" cellspacing="0"&gt;&lt;/table&gt;
    &lt;div id="pager" class="scroll" style="text-align:center;"&gt;&lt;/div&gt;</code></pre>
</blockquote>
<p>Next, I add a small bit of JavaScript to tell jqGrid to replace this div with a search control:</p>
<blockquote><p><code> </code></p>
<pre>    search.filterGrid("#" + grid.attr("id"), {
        gridModel: false,
        filterModel: [{
            label: 'Search',
            name: 'search',
            stype: 'text'
        }]
    });</pre>
</blockquote>
<p>The <code>filterModel </code>tells the grid to show a search control for one column, called "Search." Note that the entities I&#8217;m returning do not have a property called "search." That&#8217;s OK. When the user types something in the search box and presses enter, the grid will add a query string parameter to its request for the data of the form "<code>search=WhatTheUserTyped</code>". That&#8217;s what I want, and the fact that there is no "search" column in the data does not adversely affect the grid in any way.</p>
<p>The first argument to <code>filterGrid </code>is a little odd. I&#8217;m required to pass a jQuery selector as a string rather than being able to pass a jQuery object directly. Since this is all inside a method which accepts jQuery objects as arguments (rather than hard-coding the IDs of the DOM objects in the method, for unit-testability), I have to "decode" the jQuery object into a selector string. But note that I did not need to do that when setting up the pager or the grid itself. Like I said before, the grid&#8217;s API is consistently inconsistent.</p>
<p>As you can see in the code at the beginning of this post, the GridDemoData action just passes the search query string parameter through to the ToJqGridData method unchanged. Inside that method, I use Dynamic LINQ to alter the IQueryable to implement the search. I&#8217;ve cleaned up this method substantially since I first posted the code. Here&#8217;s the revised method:</p>
<blockquote><p><code> </code></p>
<pre><em>/// &lt;summary&gt;
/// Adds a Where to a Queryable list of entity instances.  In other words, filter the list
/// based on the search parameters passed.
/// &lt;/summary&gt;
/// &lt;typeparam name="T"&gt;Entity type contained within the list&lt;/typeparam&gt;
/// &lt;param name="baseList"&gt;Unfiltered list&lt;/param&gt;
/// &lt;param name="searchQuery"&gt;Whatever the user typed into the search box&lt;/param&gt;
/// &lt;param name="searchColumns"&gt;List of entity properties which should be included in the
/// search.  If any property in an entity instance begins with the search query, it will
/// be included in the result.&lt;/param&gt;
/// &lt;returns&gt;Filtered list.  Note that the query will not actually be executed until the
/// IQueryable is enumerated.&lt;/returns&gt;</em>
<strong>private static </strong>IQueryable&lt;T&gt; ListAddSearchQuery&lt;T&gt;(
    IQueryable&lt;T&gt; baseList,
    <strong>string </strong>searchQuery,
    IEnumerable&lt;<strong>string</strong>&gt; searchColumns)
{
    <strong>if </strong>((String.IsNullOrEmpty(searchQuery)) | (searchColumns == null)) <strong>return </strong>baseList;
    <strong>const string</strong> strpredicateFormat = "{0}.ToString().StartsWith(@0)";
    <strong>var </strong>searchExpression = <strong>new </strong>System.Text.StringBuilder();
    <strong>string </strong>orPart = String.Empty;
    <strong>foreach </strong>(<strong>string </strong>column <strong>in </strong>searchColumns)
    {
        searchExpression.Append(orPart);
        searchExpression.AppendFormat(strpredicateFormat, column, searchQuery);
        orPart = " OR ";
    }
    <strong>var </strong>filteredList = baseList.Where(searchExpression.ToString(), searchQuery);
    <strong>return </strong>filteredList;
}</pre>
</blockquote>
<p>Importantly, this method is simply adding to the expression represented by the IQueryable. It does not actually implement the search. So any search methodology which understands LINQ can deal with its results. At least, theoretically. In practice, LINQ providers vary greatly in terms of which LINQ features they support. So although this method works fine with LINQ to Objects (as used in the rest of the demo solution) I cannot guarantee that it will work with every LINQ provider in the world. You have to try, and revise it to fit the capabilities of the provider you&#8217;re using.</p>
<p>Putting all these pieces together, I now have a search feature which does what I want:</p>
<p><a href="/files/2009/04/jqgridwithsearch_1253.png"><img src="/files/2009/04/jqgridwithsearch_1253.png" alt="" width="457" height="132" /></a><br />
Be sure to <strong><a href="/files/2009/04/griddemo_1256.zip">download the updated solution</a></strong> in order to get the bug fixes and new features.</p>
<p>As a special, no-extra-charge bonus, the updated solution also includes a demonstration of using the grid&#8217;s tree view mode with client-side data from a JavaScript function. This has nothing to do with ASP.NET MVC; it&#8217;s just an example of how to use a grid feature which I wrote in response to <a href="http://www.trirand.com/blog/?page_id=18/treegrid/empty-treegrid-with-client-side-data/page-1/post-6175/#p6175">a request in the jqGrid support forums</a>.</p>
<p>That&#8217;s all for today. <a title="Deletes" href="http://blogs.teamb.com/craigstuntz/2009/04/29/38266/">In the next post in the series, I&#8217;ll begin to demonstrate the grid&#8217;s editing features</a>, and how to use them in an ASP.NET MVC application. But I will also take requests. If there&#8217;s a grid feature you&#8217;d like to see demonstrated query question regarding using the grid in ASP.NET MVC, please feel free to make a request in comments, and I will answer it as best I can.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38243&amp;akst_action=share-this" onclick="akst_share('38243', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F27%2F38243%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Search+and+Formatting'); return false;" title="Post to del.icio.us, etc." id="akst_link_38243" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Search%20and%20Formatting&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F27%2F38243%2F" id="akst_email_38243" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>A Crash Course In Failure</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/23/38241/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/23/38241/#comments</comments>
    <pubDate>Thu, 23 Apr 2009 10:37:39 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38241</guid>
    <description><![CDATA[My new article, A Crash Course In Failure, has just been published on the architecture site NPlus1. In it, I examine the surprisingly persuasive argument that unplugging entire racks of live, production servers is not only a good idea, but that shutting them down any other way is a mistake, and what this means for [...]]]></description>
      <content:encoded><![CDATA[<p>My new article, <a href="http://nplus1.org/articles/a-crash-course-in-failure/">A Crash Course In Failure</a>, has just been published on the architecture site NPlus1. In it, I examine the surprisingly persuasive argument that unplugging entire racks of live, production servers is not only a good idea, but that shutting them down any other way is a mistake, and what this means for how we design software.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38241&amp;akst_action=share-this" onclick="akst_share('38241', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F23%2F38241%2F', 'A+Crash+Course+In+Failure'); return false;" title="Post to del.icio.us, etc." id="akst_link_38241" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=A%20Crash%20Course%20In%20Failure&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F23%2F38241%2F" id="akst_email_38241" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Embarcadero Jobs and jqGrid Trees</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/20/38238/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/20/38238/#comments</comments>
    <pubDate>Mon, 20 Apr 2009 12:37:14 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38238</guid>
    <description><![CDATA[I have a couple of short updates on topics I&#8217;ve covered recently.
On The Podcast at Delphi.org, Nick Hodges confirms my earlier speculation about reorganization in the "CodeGear" group at Embarcadero. The whole show is worth listening to. Congratulations are due to Chris Pattinson, who was promoted to Director of Quality for all of Embarcadero. Time [...]]]></description>
      <content:encoded><![CDATA[<p>I have a couple of short updates on topics I&#8217;ve covered recently.</p>
<p>On The Podcast at Delphi.org, <a title="27 - Nick Hodges - R&amp;D Manager" href="http://www.delphi.org/2009/04/27-nick-hodges-rd-manager/">Nick Hodges confirms</a> my earlier <a title="Embarcadero Development Tools Reorganization?" href="http://blogs.teamb.com/craigstuntz/2009/04/16/38223/">speculation about reorganization in the "CodeGear" group at Embarcadero</a>. The whole show is worth listening to. Congratulations are due to <a href="http://blogs.embarcadero.com/chrispattinson/">Chris Pattinson</a>, who was promoted to Director of Quality for all of Embarcadero. Time to update the subtitle of your blog, Chris! (And maybe even write a post or two&#8230;) Sounds like good changes all around. You read it here first, folks!</p>
<p>I wrote <a href="http://www.trirand.com/blog/?page_id=18/treegrid/empty-treegrid-with-client-side-data/page-1/post-6175/#p6175">a short demo showing how to use jqGrid in tree grid node with client-side data</a> supplied by a JavaScript function.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38238&amp;akst_action=share-this" onclick="akst_share('38238', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F20%2F38238%2F', 'Embarcadero+Jobs+and+jqGrid+Trees'); return false;" title="Post to del.icio.us, etc." id="akst_link_38238" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Embarcadero%20Jobs%20and%20jqGrid%20Trees&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F20%2F38238%2F" id="akst_email_38238" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Finally, A Solution</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/17/38229/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/17/38229/#comments</comments>
    <pubDate>Fri, 17 Apr 2009 14:07:35 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38229</guid>
    <description><![CDATA[Having introduced jqGrid and written LINQ extension methods to make supplying data to the grid easy, we&#8217;re now ready to put together a demo application. The solution I&#8217;m going to build demonstrates sorting and paging. In a future post, I will enhance it to demonstrate search, formatting, and editing data. I&#8217;ve made the demo application [...]]]></description>
      <content:encoded><![CDATA[<p>Having <a href="http://blogs.teamb.com/craigstuntz/2009/04/14/38200/">introduced jqGrid</a> and written <a href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">LINQ extension methods</a> to make supplying data to the grid easy, we&#8217;re now ready to put together a demo application. The solution I&#8217;m going to build demonstrates sorting and paging. In a future post, I will enhance it to demonstrate search, formatting, and editing data. I&#8217;ve made the demo application available for download, but be advised that I intend to update it in the next few days; it&#8217;s currently a work in progress.</p>
<p>Rather than make you set up the Northwind database, I&#8217;ve written a quick, mock repository which supplies random data for the application. But the data persists for the lifetime of the app, so I&#8217;ll be able to demonstrate sorting, paging, etc. This way you can just run the application, without having to set up SQL Server.</p>
<p>So let&#8217;s write some code display a grid.</p>
<p>The data I&#8217;m going to display in the grid is a fairly useless type:</p>
<blockquote>
<pre><code>    <strong>public class </strong>SomeEntity
    {
        <strong>public int </strong>Id { <strong>get; set; </strong>}
        <strong>public int </strong>IntProperty { <strong>get; set; </strong>}
        <strong>public string </strong>StringProperty { <strong>get; set</strong>; }
        <strong>public </strong>DateTime DateProperty { <strong>get; set; </strong>}
    }</code></pre>
</blockquote>
<p>We need two actions. The first will display the page containing the grid. The second supplies data for one page of the grid. Remember, the grid can page through large datasets. It will only request one page of data at a time.</p>
<pre><code>        <strong>public </strong>ActionResult GridDemo()
        {
            <strong>return </strong>View();
        }

        <strong>public </strong>ActionResult GridDemoData(<strong>int </strong>page, <strong>int </strong>rows, <strong>string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
        {
            <strong>var </strong>repository = <strong>new </strong>Repository();
            <strong>var </strong>model = repository.SelectAll().ToJqGridData(page, rows, sidx + " " + sord, search,
                <strong>new</strong>[] { "IntProperty", "StringProperty", "DateProperty" });
            <strong>return </strong>Json(model);
        }</code></pre>
<p>The first action simply returns a view containing the HTML table which will eventually become the grid. It doesn&#8217;t need a model, because the grid will request its data asynchronously. The second action handles the data requested by the grid.</p>
<p>In order to make this work, we need HTML elements for the grid and its pager in the view, along with a reference to the JavaScript which will turn those elements into the grid.</p>
<blockquote>
<pre><code>&lt;asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"&gt;
    &lt;h2&gt;GridDemo&lt;/h2&gt;
    &lt;table id="grid" class="scroll" cellpadding="0" cellspacing="0"&gt;&lt;/table&gt;
    &lt;div id="pager" class="scroll" style="text-align:center;"&gt;&lt;/div&gt;
&lt;/asp:Content&gt;

&lt;asp:Content ID="Script" ContentPlaceHolderID="ScriptContent" runat="server"&gt;
    &lt;script language="javascript" type="text/javascript" src="&lt;%= Url.Content("~/Scripts/Home.GridDemo.js") %&gt;"&gt;&lt;/script&gt;
&lt;/asp:Content&gt;</code></pre>
</blockquote>
<p>The JavaScript file is where the grid itself is configured.</p>
<blockquote>
<pre><code>$(document).ready(<strong>function</strong>() {
    GridDemo.Home.GridDemo.setupGrid($("#grid"), $("#pager"));
});

GridDemo.Home.GridDemo = {
    setupGrid: <strong>function</strong>(grid, pager) {
        grid.jqGrid({
            colNames: ['Int', 'String', 'Date'],
            colModel: [
                        { name: 'IntProperty', index: 'IntProperty' },
                        { name: 'StringProperty', index: 'StringProperty' },
                        { name: 'DateProperty', index: 'DateProperty' },
                      ],
            pager: pager,
            sortname: 'IntProperty',
            rowNum: 10,
            rowList: [10, 20, 50],
            sortorder: "asc",
            url: "GridDemoData"
        }).navGrid(pager, { edit: <strong>false</strong>, add: <strong>false</strong>, del: <strong>false</strong>, search: <strong>false </strong>});
    }
};</code></pre>
</blockquote>
<p>Important to note here are:</p>
<ul>
<li><code>colNames</code>, the grid column captions the user sees.</li>
<li><code>colModel</code>,which includes the property <code>name</code>, which is the field name in the returned JSON data which supplies the data for that column, and <code>index</code>, which is the name which will be sent to the <code>GridDemoData </code>action as the <code>sidx </code>(field name to sort on) argument when you click on a grid header. There are a number of other properties you can set here which control editing, with, formatting, etc. See <a href="http://www.secondpersonplural.ca/jqgriddocs/_2eb0fihps.htm">the documentation</a> for full details. Importantly, <code>colNames </code>and <code>colModel </code>must have the same number of entries, and be in the same order.</li>
<li><code>url</code>, which tells the grid where to get its data. You&#8217;ll notice that the value I&#8217;ve passed is the name of the second action.</li>
</ul>
<p>As I mentioned in <a title="LINQ Extensions" href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">the last post</a>, I set a number of the grid options in a script referenced by the Site.Master, in order to prevent having to set them on every grid I create. The configuration idea for the grid on an individual page should be only the things that are unique to that page. So there is a fair bit of configuration for the grid which is not included here. In addition, the Site.Master contains references to the grid&#8217;s JavaScript and CSS files.</p>
<p>Finally, it&#8217;s worth mentioning that when you add jqGrid to a project you need to edit the jQuery.jqGrid.js file to tell the grid where to find the rest of the JS files it needs. Once you look at this file, it is obvious what you need to change.</p>
<p>At this point, I&#8217;m going to make the demo application available for download, so that you can experiment with it yourself. However, I&#8217;ll caution that I intend to update it when I write the next post in this series. In other words, the current download is a work in progress. It will change in the next few days.</p>
<p><a href="/files/2009/04/griddemo_1256.zip">Download the Solution (587 KB)</a></p>
<p>So let&#8217;s run the solution and see what we get:</p>
<p><a href="/files/2009/04/jqgriddemoapp1_1192.png"><img src="/files/2009/04/jqgriddemoapp1_1192.png" alt="jqGrid demo app version 1" width="500" height="464" /></a><br />
OK, the hideous and eyestrain-inducing clash between the default MVC theme and the jQuery UI "lightness" theme included with the grid download notwithstanding, this is actually not bad. Sorting and paging both work, and performance is very good.</p>
<p>But what&#8217;s the deal with the data in that date column? It turns out that there is no standard representation of a date in JSON, so Microsoft invented their own. The grid doesn&#8217;t know about this special format. <a title="Search and Formatting" href="http://blogs.teamb.com/craigstuntz/2009/04/27/38243/">We&#8217;ll clean that up in the next post in this series and also cover search. </a>Stay tuned!</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38229&amp;akst_action=share-this" onclick="akst_share('38229', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F17%2F38229%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Finally%2C+A+Solution'); return false;" title="Post to del.icio.us, etc." id="akst_link_38229" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Finally%2C%20A%20Solution&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F17%2F38229%2F" id="akst_email_38229" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Embarcadero Development Tools Reorganization?</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/16/38223/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/16/38223/#comments</comments>
    <pubDate>Thu, 16 Apr 2009 10:44:35 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38223</guid>
    <description><![CDATA[Item 1:
Nick Hodges has a new role/job title.
Item 2:
During his presentation to the Columbus Architecture Group a couple of weeks ago, Mike Rozlog handed out business cards which gave his title as "Senior Project Manager, Java Tools." He told us that in a couple of days he would have new business cards, because his role [...]]]></description>
      <content:encoded><![CDATA[<h5>Item 1:</h5>
<p><a href="http://blogs.embarcadero.com/nickhodges/2009/04/14/39230">Nick Hodges has a new role/job title.</a></p>
<h5>Item 2:</h5>
<p>During <a href="http://blogs.teamb.com/craigstuntz/2009/04/06/38188/">his presentation to the Columbus Architecture Group</a> a couple of weeks ago, Mike Rozlog handed out business cards which gave his title as "Senior Project Manager, Java Tools." He told us that in a couple of days he would have new business cards, because his role was changing. He didn&#8217;t tell us precisely what the new role would be, but I got the feeling that, like Nick, he was happy with the change.</p>
<p>Now, it is of course possible that these two changes happening so close together is merely a coincidence. But my <em><strong>personal speculation</strong></em> is that there are bigger plans afoot, and I&#8217;m glad to see that Mike and Nick, two people I trust, seem to be happy with them.</p>
<p>Repeat: <em>This is just my personal speculation</em>. It is based on the evidence above, not inside information. I could be wrong.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38223&amp;akst_action=share-this" onclick="akst_share('38223', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F16%2F38223%2F', 'Embarcadero+Development+Tools+Reorganization%3F'); return false;" title="Post to del.icio.us, etc." id="akst_link_38223" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Embarcadero%20Development%20Tools%20Reorganization%3F&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F16%2F38223%2F" id="akst_email_38223" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: LINQ Extensions</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/15/38212/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/15/38212/#comments</comments>
    <pubDate>Wed, 15 Apr 2009 11:25:36 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38212</guid>
    <description><![CDATA[Mere hours after I posted the first in a planned series of posts on using jqGrid in ASP.NET MVC applications, Phil Haack, a rather-more-widely-read-ASP.NET-MVC-blogger, wrote a long post on, er, exactly the same thing. Who, me, bitter? Naahhh…  
But it turns out that we&#8217;re using the grid in a different way, and I think [...]]]></description>
      <content:encoded><![CDATA[<p>Mere hours after I posted <a title="Introduction" href="http://blogs.teamb.com/craigstuntz/2009/04/14/38200/">the first in a planned series of posts on using jqGrid in ASP.NET MVC applications</a>, Phil Haack, a rather-more-widely-read-ASP.NET-MVC-blogger, wrote <a title="Using jQuery Grid With ASP.NET MVC" href="http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx">a long post on, er, exactly the same thing</a>. Who, me, bitter? Naahhh… <img src='http://blogs.teamb.com/feeds/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>But it turns out that we&#8217;re using the grid in a different way, and I think the difference is important. So rather than just referring you to Phil&#8217;s post and skipping the rest of the series, I think I still have some important information to contribute. In particular, I&#8217;m using the grid in a way which allows me to write an extension method for <code>IQueryable&lt;T&gt;</code> which returns data suitable for the grid, without having to know anything about the type <code>T</code>. If you look closely at the code in Phil&#8217;s post, you will see that populating the cell array requires custom code (or use of reflection) every time you want to return data to a grid.</p>
<p>It&#8217;s important to me that the method should work without knowing anything about the type of the data in the list because I don&#8217;t want to have to write repetitious code in every action method which supplies data to a grid to shape the data according to the grid&#8217;s needs, and because I generally use anonymous types for JSON serialization. JSON cannot handle object graphs with cycles (i.e., a "circle" of objects which all reference each other). The .NET JSON serializer will throw an exception if you pass it an object which contains a circular reference, or refers to another object which does. Since this is largely data-dependent and, worse, can be occasionally masked by lazy loading and the like, the safest way to serialize to JSON is to pass it data which provably can never contain a cycle. Anonymous types work really well for this. I&#8217;ll probably elaborate on this point in a future post. For the time being, the important thing is that I need to be able to take any IQueryable and turn it into data suitable for the grid, without having to think about what type that list might contain.</p>
<p><strong>In a nutshell, this is what I want to be able to do:</strong></p>
<blockquote>
<pre><code><strong>public </strong>JsonResult ListGridData(<strong>int </strong>page, <strong>int </strong>rows, <strong>string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
{
    <strong>var </strong>model = repository.SelectAll().ToJqGridData(page, rows, sidx + " " + sord, search,
      <strong>new</strong>[] { "Column1", "</code><code>Column2</code><code>", "</code><code>Column3</code><code>" })
    <strong>return </strong>Json(model);
}</code></pre>
</blockquote>
<p>In this example, <code>repository.SelectAll()</code> returns an <code>IQueryable&lt;TSomething&gt;</code>. I&#8217;ve written a method, <code>ToJqGridData</code>, which can transform that <code>IQueryable</code> into data suitable for the grid without having to know what <code>TSomething</code> is. (What the heck is that string array? Don&#8217;t worry about that just yet; I&#8217;ll cover it in a little bit.) The argument names aren&#8217;t what I would have picked, but they come from the grid. There is probably a way to change them, but I&#8217;ve never bothered to look.</p>
<p>The key to this is a grid property called <code>jsonReader.repeatitems</code>. I&#8217;m not sure why it&#8217;s called <code>repeatitems</code>, but here&#8217;s what it does. When <code>repeatitems </code>is true (the default), data is returned to the grid in a "cell array," like in Phil&#8217;s post. That is, an individual row of data in the JSON looks like this:</p>
<blockquote>
<pre>{id:<span class="codestring">"1"</span>, cell:[<span class="codestring">"cell11"</span>, <span class="codestring">"cell12"</span>, <span class="codestring">"cell13"</span>]}</pre>
</blockquote>
<p>When <code>repeatitems </code>is false, the data looks like a regular object in JSON format:</p>
<blockquote>
<pre>{id:<span class="codestring">"45678"</span>,name:<span class="codestring">"Speakers"</span>,note:<span class="codestring">"note"</span>,stock:<span class="codestring">"false"</span>,ship:<span class="codestring">"4"</span>}</pre>
</blockquote>
<p>Interestingly, it turns out that <em>this is the format the .NET JSON serializer already uses</em>. So I don&#8217;t have to write <em>any </em>code to get this portion of the data into the right shape. I just hand an object to the JSON serializer and let it do its thing. The only things I need to do to make the data work for the grid is to handle paging, sorting, search, and provide certain other bits of data, like the number of rows.</p>
<p>But, as you may have noticed, I&#8217;m lazy. Why write code when someone else has already done it? <a title="PagedList&lt;T&gt;" href="http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/">Rob Conery wrote a decent type for paging eons ago</a>, and <a title="PagedList Strikes Back" href="http://www.squaredroot.com/post/2008/07/08/PagedList-Strikes-Back.aspx">Troy Goode enhanced it</a>. So I&#8217;m going to use their work instead of re-writing paging. It turns out this type already computes most of what the grid needs to know. And Microsoft has this thing called Dynamic LINQ which can deal with ordering and filtering by property names, mostly. All I have to do is tie this stuff together.</p>
<p>I wrote a type to hold the data which the grid needs. You can actually use an anonymous type for this; the JavaScript grid obviously doesn&#8217;t care if the data it receives comes from an anonymous type or not, but because I am writing extension methods to IQueryable, it was convenient for me to have a non-anonymous type so that the extension methods could build on each other. This type represents one page of data requested by the grid:</p>
<blockquote>
<pre><code><strong>namespace </strong>GridDemo.Models
{
<em>    /// &lt;summary&gt;
    /// This type is designed to conform to the structure required by the JqGrid JavaScript component.
    /// It has all of the properties required by the grid. When this type is serialized to JSON, the resulting
    /// JSON will be in the structure expected by the grid when it fetches pages of data via AJAX calls.
    /// &lt;/summary&gt;</em>
    [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Jq",
        Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Jq",
        Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
    <strong>public class</strong> JqGridData
    {
<em>        /// &lt;summary&gt;
        /// The number of pages which should be displayed in the paging controls at the bottom of the grid.
        /// &lt;/summary&gt;</em>
        <strong>public int </strong>Total {<strong> get; set;</strong> }
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// The current page number which should be highlighted in the paging controls at the bottom of the grid.
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public int </strong>Page { <strong>get; set;</strong> }
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// The total number of records in the entire data set, not just the portion returned in Rows.
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public int </strong>Records { <strong>get; set; </strong>}</code><code>
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// The data that will actually be displayed in the grid.
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public </strong>IEnumerable Rows { <strong>get; set; </strong>}
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// Arbitrary data to be returned to the grid along with the row data. Leave null if not using. Must be serializable to JSON!
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public object </strong>UserData { <strong>get; set; </strong>}</code><code>
</code><code>    }
}</code></pre>
</blockquote>
<p>Note that I&#8217;ve used C# capitalization for the property names. This is not what the grid expects. But I have to tell the grid that I&#8217;m using a non-default value for <code>repeatitems </code>anyway, so it&#8217;s nice to follow C# conventions.</p>
<p>We have lots of grids in our application, so rather than configuring each grid individually, we set defaults for the grid in one place. In a JavaScript file referenced by the Site.Master, this method is called in the jQuery ready event:</p>
<blockquote>
<pre><code>    setDefaults: <strong>function</strong>() {
        $.jgrid.defaults = $.extend($.jgrid.defaults, {
            datatype: 'json',
            height: 'auto',
            imgpath: '/Content/jqGrid/themes/basic/images',
            jsonReader: {
                root: "Rows",
                page: "Page",
                total: "Total",
                records: "Records",
                repeatitems: <strong>false</strong>,
                userdata: "UserData",
                id: "Id"
            },
            loadui: "block",
            mtype: 'GET',
            multiboxonly: <strong>true</strong>,
            rowNum: 20,
            rowList: [10, 20, 50],
            url: "ListGridData.json",
            viewrecords: <strong>true</strong>
        });
    }</code></pre>
</blockquote>
<p>In addition to setting <code>repeatitems</code>, telling the grid to expect the capitalization I mentioned above, this code also sets the grid theme and other options we want to be consistent throughout the application. One important property set in the <code>jsonReader </code>property is <code>id</code>. The value supplied is the name of a column in the returned data which contains a unique ID for the row. You can supply any name you want to, and the type of the property can be just about anything serializable, but it is important that the data you return to the grid contains some unique ID. All of the types in our Entity Framework model contain a unique ID called "<code>Id</code>", so we set this in our defaults for the grid. If you don&#8217;t have a single operating name for any data you might supply to the grid, you will have to set this value on the individual grids, when you write the JavaScript for the view.</p>
<p>Now I can write a method which takes a PagedList and transforms it into jqGrid data:</p>
<blockquote>
<pre><code>        /// &lt;summary&gt;
        /// Converts a paged list into a format suitable for the JqGrid component, when
        /// serialized to JSON. Use this method when returning data that the JqGrid component will
        /// fetch via AJAX. Take the result of this method, and then serialize to JSON. This method
        /// will also apply paging to the data.
        /// &lt;/summary&gt;
        /// &lt;typeparam name="T"&gt;The type of the element in baseList. Note that this type should be
        /// an anonymous type or a simple, named type with no possibility of a cycle in the object
        /// graph. The default JSON serializer will throw an exception if the object graph it is
        /// serializing contains cycles.&lt;/typeparam&gt;
        /// &lt;param name="list"&gt;The list of records to display in the grid.&lt;/param&gt;
        /// &lt;param name="userData"&gt;Arbitrary data to be returned to the grid along with the row data.
        /// Leave null if not using. Must be serializable to JSON!&lt;/param&gt;
        /// &lt;returns&gt;A structure containing all of the fields required by the JqGrid. You can then call
        /// a JSON serializer, passing this result.&lt;/returns&gt;
        [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the grid component we use.")]
        <strong>public static </strong>JqGridData ToJqGridData&lt;T&gt;(<strong>this </strong>PagedList&lt;T&gt; list, <strong>object </strong>userData)
        {
            <strong>return new </strong>JqGridData()
            {
                Page = list.PageIndex,
                Records = list.TotalItemCount,
                Rows = from record in list
                       select record,
                Total = list.PageCount,
                UserData = userData
            };
        }</code></pre>
</blockquote>
<p>That&#8217;s getting somewhere, but it&#8217;s not yet enough to let me write the action method I showed above. For that, I need to wrap up the PagedList inside the action so that I can pass the arguments from the grid directly, without having to construct a new PagedList inside of every action method which supplies data to a grid. So I build on the method above:</p>
<pre><code>        /// &lt;summary&gt;
        /// Converts a queryable expression into a format suitable for the JqGrid component, when
        /// serialized to JSON. Use this method when returning data that the JqGrid component will
        /// fetch via AJAX. Take the result of this method, and then serialize to JSON. This method
        /// will also apply paging to the data.
        /// &lt;/summary&gt;
        /// &lt;typeparam name="T"&gt;The type of the element in baseList. Note that this type should be
        /// an anonymous type or a simple, named type with no possibility of a cycle in the object
        /// graph. The default JSON serializer will throw an exception if the object graph it is
        /// serializing contains cycles.&lt;/typeparam&gt;
        /// &lt;param name="baseList"&gt;The list of records to display in the grid.&lt;/param&gt;
        /// &lt;param name="currentPage"&gt;A 1-based index indicating which page the grid is about to display.&lt;/param&gt;
        /// &lt;param name="rowsPerPage"&gt;The maximum number of rows which the grid can display at the moment.&lt;/param&gt;
        /// &lt;param name="orderBy"&gt;A string expression containing a column name and an optional ASC or
        /// DESC. You can, separate multiple column names as with SQL.&lt;/param&gt;
        /// &lt;param name="searchQuery"&gt;The value which the user typed into the search box, if any. Can be
        /// null/empty.&lt;/param&gt;
        /// &lt;param name="searchColumns"&gt;An array of strings containing the names of properties in the
        /// element type of baseList which should be considered when searching the data for searchQuery.&lt;/param&gt;
        /// &lt;param name="userData"&gt;Arbitrary data to be returned to the grid along with the row data. Leave
        /// null if not using. Must be serializable to JSON!&lt;/param&gt;
        /// &lt;returns&gt;A structure containing all of the fields required by the JqGrid. You can then call
        /// a JSON serializer, passing this result.&lt;/returns&gt;
        [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the grid component we use.")]
        <strong>public static </strong>JqGridData ToJqGridData&lt;T&gt;(<strong>this </strong>IQueryable&lt;T&gt; baseList,
            <strong>int </strong>currentPage,
            <strong>int </strong>rowsPerPage,
            <strong>string </strong>orderBy,
            <strong>string </strong>searchQuery,
            IEnumerable&lt;<strong>string</strong>&gt; searchColumns,
            <strong>object </strong>userData)
        {
            <strong>var </strong>filteredList = ListAddSearchQuery(baseList, searchQuery, searchColumns);
            <strong>var </strong>pagedModel = <strong>new </strong>PagedList&lt;T&gt;(filteredList.OrderBy(orderBy), currentPage, rowsPerPage);
            <strong>return </strong>pagedModel.ToJqGridData(userData);
        }</code></pre>
<p>Now you see that string array (IEnumerable, actually) again. JqGrid supports sorting and searching, and so do I. Like Phil, I suggest using Microsoft Dynamic LINQ in order to take the field names that jqGrid passes and turn them into a sorted, filtered, result set. ListAddSearchQuery is a (longish) method which takes a search string and a list of columns to search and turns them into a Dynamic LINQ expression and applies it to the base list. Unfortunately, search is kind of application-specific. In some applications you might want to search different columns in different ways. Some applications might want "Google-style" searching. It kind of depends upon what you&#8217;re doing. So although I will supply the source code for this method when I make the demo project available, I cannot promise that it will be useful for <em>your </em>application. Feel free to substitute your own method here.</p>
<p>It turns out both methods (the one which takes a <code>PagedList </code>and the one which takes an <code>IQueryable</code>) are useful. Generally, I use the method which takes an <code>IQueryable</code>. But every once in a while I want to do something to the data I&#8217;m about to supply to the grid before the grid sees it, but after paging, like transform a single page of results in some way. In this case, the action builds up a <code>PagedList</code>, uses that to reduce to one page of data, modifies the results in whatever way is appropriate, and then calls the <code>PagedList </code>extension. I&#8217;ve also written additional overloads to both methods which do not have a <code>userData </code>argument, since it is very seldomly used. <code>userData</code>, as the name suggests, is an additional bit of data you can return to the grid with your result set for use in grid event handlers when loading a fresh page of data. Since it&#8217;s of type object, you can put as much data in there as you need to, so long as it&#8217;s serializable to JSON. In practice, though, we rarely use this feature of the grid.</p>
<p>With these methods, it is easy to write actions as concise as the code I showed at the beginning of this post. Just get a list from somewhere and call ToJqGridData, passing information about which page to display, how to sort, etc.</p>
<p>In a future post, I will tie this all together into a demo application.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38212&amp;akst_action=share-this" onclick="akst_share('38212', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F15%2F38212%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+LINQ+Extensions'); return false;" title="Post to del.icio.us, etc." id="akst_link_38212" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20LINQ%20Extensions&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F15%2F38212%2F" id="akst_email_38212" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Introduction</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/14/38200/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/14/38200/#comments</comments>
    <pubDate>Tue, 14 Apr 2009 11:28:03 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38200</guid>
    <description><![CDATA[This is the first post in a short series on using the jqGrid jQuery plug-in with ASP.NET MVC. In this short introduction I will describe the plug-in, list some of its strengths and weaknesses, and explain why we selected it for our MVC applications. In the next few days, I will give detailed information about [...]]]></description>
      <content:encoded><![CDATA[<p>This is the first post in a short series on using the <a href="http://www.trirand.com/blog/">jqGrid</a> jQuery plug-in with ASP.NET MVC. In this short introduction I will describe the plug-in, list some of its strengths and weaknesses, and explain why we selected it for our MVC applications. In the next few days, I will give detailed information about how to use the grid in your own applications.</p>
<p>jqGrid provides a nice-looking grid with built-in features such as sorting, editing, search, drill-down, tree lists, and more. It is based upon jQuery and integrates well with ASP.NET MVC. <a href="http://www.trirand.com/blog/?page_id=154">The grid is dual-licensed under both the GPL and MIT licenses</a> (just like jQuery), so it can fit well into both commercial and open-source projects.</p>
<p><a href="/files/2009/04/jqgrid_1166.png"><img src="/files/2009/04/jqgrid_1166.png" alt="jqGrid with sub-grid" width="660" height="277" /></a></p>
<p>If you want to display tabular (grid) data with paging in an ASP.NET MVC application, there are essentially three choices:</p>
<ol>
<li>You can write your own grid components using HTML tables, links, manually-implemented paging, etc. This is actually less work than it might seem at first, and the first release of our ASP.NET MVC software did just this. But our own implementation lacked some of the visual flair of some of the third-party components, and avoided solving some of the harder problems, like in-line editing. Still, it was much easier than I expected, and worked well enough for our initial release.</li>
<li>You can use a commercial component designed for ASP.NET. However, many commercial grid components don&#8217;t work well with MVC. Telerik has MVC demos available for their grid, and Developer Express has said that they intend to support MVC to some degree in the future. Even when the commercial components do support MVC at all, they don&#8217;t tend to make all of their features available in MVC applications, owing to the fundamental difference between the way ASP.NET MVC and "plain" ASP.NET work. If you are building a Web application on ASP.NET MVC, I would never recommend buying an ASP.NET component unless the vendor for that component is fully committed to supporting MVC. <em>You cannot presume that any given ASP.NET component will work at all with MVC unless the vendor explicitly supports this.</em></li>
<li>You can use a grid component which has no knowledge of ASP.NET at all. There are quite a number of these, generally built within the framework of one of the popular JavaScript libraries, and it is, ironically, easier to use one of them within ASP.NET MVC application than it is to use a grid component designed for ASP.NET (but not necessarily MVC).</li>
</ol>
<p>As I said, we ended up choosing jqGrid. We were strongly influenced by the fact that we already use jQuery extensively in our application. There are several grid plug-ins available for jQuery. jqGrid has a number of advantages over the others I&#8217;ve seen, however:</p>
<ul>
<li>Supports three different models for editing data within the grid: Single-cell editing, in-line row editing, and editing within a pop-up form.</li>
<li>Unlike some of the other jQuery grid plug-ins, jqGrid has <a href="http://www.secondpersonplural.ca/jqgriddocs/index.htm">decent documentation</a> and <a href="http://trirand.com/jqgrid/jqgrid.html">a large number of demos with source code</a>.</li>
<li>You can display a simple grid, a "sub grid" (drill down), or a treeview.</li>
<li>AJAX paging is supported in a number of different formats, including JSON, XML, or JavaScript objects via a custom function.</li>
<li>The grid is updated very regularly, and <a href="http://www.trirand.com/jqgrid35/jqgrid.html">a new version, with support for the jQuery UI theming library</a> is under active development right now.</li>
<li>Tracing through the grid source code is quite easy to do with Firebug, which is useful for figuring out things which aren&#8217;t quite covered by the documentation.</li>
</ul>
<p>The grid also has a few downsides:</p>
<ul>
<li>The API is a bit of a mess. Capitalization (significant, in JavaScript) is so varied that it seems almost random. Portions of the code were clearly written by different people with limited collaboration with the original author of the grid. There is no consistent naming convention, and similar functionality is sometimes invoked in wildly different ways. For example, you set the grid height with a custom method, <code>setGridHeight</code>, instead of the jQuery method <code>height</code>. But you reload the grid&#8217;s data with a jQuery method, <code>trigger</code>, passing the string <code>"reloadGrid"</code> as an argument. It&#8217;s a good thing the grid has decent documentation and includes source code, because you&#8217;re going to need them. The API is just not discoverable.</li>
<li>Although the grid has quite a number of options for editing, it doesn&#8217;t necessarily play well with some of the other tools you may want to use in the context of editing, such as <a title="http://blogs.teamb.com/craigstuntz/2009/01/15/37923/" href="http://blogs.teamb.com/craigstuntz/2009/01/15/37923/">jQuery validation</a>. (For starters, the in-line row editing doesn&#8217;t actually use an HTML form.) The three different editing modes (single-cell, in-line row editing, and editing in a form) use different source modules, different configuration options, and work differently. Doing editing in a way not explicitly supported by the grid can be challenging.</li>
<li>Variable names in the source code use a lot of single letter and two letter abbreviations. This is quite common in JavaScript libraries, but it does make the source code a bit challenging to read.</li>
<li>Although <a href="http://www.trirand.com/blog/?page_id=154">there is both free and paid support available</a>, there is not a commercial company standing behind the grid. So don&#8217;t expect round-the-clock support, a toll-free phone number, etc.</li>
</ul>
<p>After a good deal of experimentation with several grids, we decided to use jqGrid because it has considerably more features than every other grid we examined (when used in MVC application), and because we didn&#8217;t find any of its limitations to be show stoppers.</p>
<p>The next post in this series is <a href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">LINQ Extensions</a>. There, I show an extension method for <code>IQueryable&lt;T&gt;</code> which returns data suitable for the grid, without having to know anything about the type <code>T.</code></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38200&amp;akst_action=share-this" onclick="akst_share('38200', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F14%2F38200%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Introduction'); return false;" title="Post to del.icio.us, etc." id="akst_link_38200" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Introduction&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F14%2F38200%2F" id="akst_email_38200" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Do You Recognize Math When You See It?</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/07/38190/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/07/38190/#comments</comments>
    <pubDate>Tue, 07 Apr 2009 10:34:14 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38190</guid>
    <description><![CDATA[Jeff Atwood says:
On the other hand, I have not found in practice that programmers need to be mathematically inclined to become great software developers.  Quite the opposite, in fact. This does depend heavily on what kind of code you&#8217;re writing, but the vast bulk of code that I&#8217;ve seen consists mostly of the "balancing [...]]]></description>
      <content:encoded><![CDATA[<p><a title="Should Competent Programmers be &quot;Mathematically Inclined&quot;?" href="http://www.codinghorror.com/blog/archives/001249.html">Jeff Atwood says</a>:</p>
<blockquote><p>On the other hand, <strong>I have not found <em>in practice</em> that programmers need to be mathematically inclined to become great software developers</strong>.  Quite the opposite, in fact. This does depend heavily on what kind of code you&#8217;re writing, but the vast bulk of code that <em>I&#8217;ve</em> seen consists mostly of the "balancing your checkbook" sort of math, nothing remotely like what you&#8217;d find in the average college calculus textbook, even.</p>
<pre>{
  i = j++ / (x + v);
}</pre>
<p>Not exactly the stuff mathletes are made of.</p></blockquote>
<p>Arithmetic is one kind of math. It is relatively common in elementary math classes, and <em>relatively </em>uncommon in programming. Does Jeff&#8217;s example look like the "vast bulk of code <em>you&#8217;ve </em>seen?" It certainly doesn&#8217;t look like the vast bulk of code <em>I&#8217;ve </em>seen.</p>
<p>On the other hand, I do see a good bit of:</p>
<ul>
<li>Relational database queries (<a href="http://www.vocw.edu.vn/content/m10536/latest/">relational algebra</a>)</li>
<li>LINQ (<a href="http://mathworld.wolfram.com/Functor.html">functors</a>)</li>
<li>Composition of lambda expressions (<a href="http://mathworld.wolfram.com/LambdaCalculus.html">lambda calculus</a>, of course)</li>
<li>Set operations and logical operators (<a href="http://mathworld.wolfram.com/SetTheory.html">set theory</a>)</li>
<li>Etc.</li>
</ul>
<p>That&#8217;s by no means a comprehensive list. For example, every general-purpose programming language I&#8217;ve ever used would not exist without the <a href="http://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis">Church-Turing thesis</a>. But I didn&#8217;t include that, since most people don&#8217;t do programming language design.</p>
<p>All programmers work with mathematical systems day in and day out, whether we recognize them or not. Perhaps the ability to recognize math when we see it will help us better evaluate the importance of understanding it.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38190&amp;akst_action=share-this" onclick="akst_share('38190', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F07%2F38190%2F', 'Do+You+Recognize+Math+When+You+See+It%3F'); return false;" title="Post to del.icio.us, etc." id="akst_link_38190" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Do%20You%20Recognize%20Math%20When%20You%20See%20It%3F&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F07%2F38190%2F" id="akst_email_38190" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Reminder: Mike Rozlog to Speak to Columbus Architecture Group</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/06/38188/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/06/38188/#comments</comments>
    <pubDate>Mon, 06 Apr 2009 15:28:29 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38188</guid>
    <description><![CDATA[Mike Rozlog, the product manager for the JBuilder and 3rdRail products for Embarcadero, will be speaking to the Columbus Architecture Group tonight at 6:00 p.m., on the subject of software archaeology. For more information on the topic, here is a slide deck for one of his previous presentations on the subject, and here&#8217;s a video [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://blogs.embarcadero.com/michaelrozlog/">Mike Rozlog</a>, the product manager for the JBuilder and 3rdRail products for <a href="http://www.embarcadero.com/">Embarcadero</a>, will be speaking to the <a href="http://www.colarc.org/2009/03/guest-speaker-at-april-6th-meeting.html">Columbus Architecture Group <em>tonight </em>at 6:00 p.m.</a>, on the subject of <a href="http://www.embarcadero.com/solutions/software_archeology.php">software archaeology</a>. For more information on the topic, here is <a href="http://blogs.embarcadero.com/files/2007/12/radstudiowebinar_192.pdf">a slide deck for one of his previous presentations on the subject</a>, and <a href="http://cc.embarcadero.com/Item/26427">here&#8217;s a video replay</a>.</p>
<p><strong>Update:</strong> Attendee Bill Melvin wrote <a title="COLARC Meeting - April 2009" href="http://www.bluecog.com/blog/2009/04/07/colarc-meeting-april-2009/">a short summary of the presentation</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38188&amp;akst_action=share-this" onclick="akst_share('38188', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F06%2F38188%2F', 'Reminder%3A+Mike+Rozlog+to+Speak+to+Columbus+Architecture+Group'); return false;" title="Post to del.icio.us, etc." id="akst_link_38188" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Reminder%3A%20Mike%20Rozlog%20to%20Speak%20to%20Columbus%20Architecture%20Group&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F06%2F38188%2F" id="akst_email_38188" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Designed as Designer</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/31/38153/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/31/38153/#comments</comments>
    <pubDate>Tue, 31 Mar 2009 13:04:52 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38153</guid>
    <description><![CDATA[Have you ever ridden a horse? When you drive the car, the process goes something like this:

Decide where you want to go.
Aim the car in that direction.
Get there.

It&#8217;s different when you ride a horse. In that case the process is more like:

Decide where you want to go.
Communicate your intention to the horse.
Arrive at some hybrid [...]]]></description>
      <content:encoded><![CDATA[<p>Have you ever ridden a horse? When you drive the car, the process goes something like this:</p>
<ol>
<li>Decide where you want to go.</li>
<li>Aim the car in that direction.</li>
<li>Get there.</li>
</ol>
<p>It&#8217;s different when you ride a horse. In that case the process is more like:</p>
<ol>
<li>Decide where you want to go.</li>
<li>Communicate your intention to the horse.</li>
<li>Arrive at some hybrid of where you want to go and where the horse wants to go.</li>
<li>Return to step (1). Repeat.</li>
</ol>
<p>Now, which of those two would you find more analogous to software architecture? Does that sound like a silly question? The reason that I ask is that I read a paper last night which argues in a persuasive but decidedly unconventional manner that <em>the things you design </em>have, for lack of a better word, intention. In other words, building a cathedral, or a software application is more like riding a horse than driving a car.</p>
<p>The paper is called <a href="http://dreamsongs.org/DesignedAsDesigner.html">Designed as Designer</a>, by <a href="http://en.wikipedia.org/wiki/Richard_Gabriel">Richard P. Gabriel</a>. As technical papers go, this one is unusual to say the least. It was written as a response to <a href="http://www.oopsla.org/oopsla2007/index.php?page=podcasts/">an address by Fred Brooks at OOPSLA 2007</a>, during his keynote. In the address, Brooks stated:</p>
<blockquote><p>If we look back then at the 19th century and the things that happened—the cartwright and the textile machinery, Stephenson (the train), Brunel&#8217;s bridges and railway, Edison, Ford, the Wright brothers, etc.—these were very largely the designs of single designers or, in the case of the Wright brothers, pairs.</p></blockquote>
<p>Gabriel disputes this idea, and chooses an unexpected way of making his case. <a href="http://dreamsongs.org/Books.html">Gabriel is a published author </a>both in the fields of computer science and writing/poetry. The paper draws as much from his experience in the latter field as the former—there is considerably more poetry quoted in the paper than source code. He also manages to weave in, <em>with some relevance, no less</em>, baseball statistics.</p>
<p>The general outline of the paper is as follows: First, there is a running, fictional narrative about a child named Pippo who observes the construction of the <a href="http://www.duomofirenze.it/storia/storia_eng.htm">cathedral of Firenze</a>. Next, Gabriel addresses Brooks&#8217;s point directly. He discusses the relationship between poets T.S. Eliot and Ezra Pound in the evolution of Eliot&#8217;s masterpiece <a href="http://www.bartleby.com/201/1.html"><em>The Waste Land</em></a>. The middle, and longest, section of the paper is an explanation and example of a theory of poetry he has developed based around an almost algorithmic approach to classifying a given text as either poetry or ordinary writing. Contrasting an early version of a published column with a later revision to same, he asserts that the structure of the earlier version leads the poet into the later revision. I should add here that even though I really like poetry, I find his analysis a bit academic for my taste. Returning to the Cathedral of Firenze, Gabriel shows that many people were involved in its design and construction, and that the Cathedral form itself had a bigger impact on the final design than the architect. Then he uses statistical analysis of the career of Roger Maris to show that luck, as much as skill, played a role in Maris&#8217;s exceeding Babe Ruth&#8217;s home run record.</p>
<p>The final section of the paper includes, almost shockingly at this point, discussion of computer science and one small example of (Lisp) source code. He relates the story of how Gerry Sussman and Guy Steele discovered how two mechanisms they were studying turned out to be exactly the same thing by implementing both of them separately and noticing later that the source code was identical.</p>
<p>If all this sounds a bit, well, crazy, it isn&#8217;t. <a href="http://www.oopsla.org/oopsla2008/program-overview/essays.html">The paper was presented at OOPSLA 2008</a>. I&#8217;m not above a bit of <em>schadenfreude</em>, but this is definitely a "laugh with him" rather than "laugh at him" paper. If you have ever had the experience of designing a system, and then uncovering necessary changes in the system when you try to use your design, then you have some idea of what he&#8217;s getting at.</p>
<p>I am also reminded, more than a little bit, of Michael Pollan&#8217;s book, <a href="http://www.amazon.com/gp/product/0375760393?ie=UTF8&amp;tag=learningtowhi-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0375760393">The Botany of Desire</a><img style="border:none !important;margin:0px !important" src="http://www.assoc-amazon.com/e/ir?t=learningtowhi-20&amp;l=as2&amp;o=1&amp;a=0375760393" border="0" alt="" width="1" height="1" />, which calls the evolution of the humans and plants "co-evolutionary," and questions who has domesticated whom. Again, we don&#8217;t tend to think of plants as having "intention," but maybe the question should be, "just what is intention, really?" So all in all, it&#8217;s a fascinating read.</p>
<p>That said, it seems to me that, to some extent, Brooks and Gabriel may be talking past each other. Surely, Brooks can&#8217;t be under the delusion that the Wright brothers invented the airplane in a vacuum? Surely, Gabriel wouldn&#8217;t presume that he is? Much of Brooks&#8217;s writing focuses on organizational support for creativity. Indeed, Brooks, to me, seems almost to take creativity as a given, more so than examining what it is and what makes it tick. Gabriel seems to be on the other side of this coin, examining the nature of creativity, rather than how to make it work in a large organization.</p>
<p>Both points of view are worth reading, I think.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38153&amp;akst_action=share-this" onclick="akst_share('38153', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F31%2F38153%2F', 'Designed+as+Designer'); return false;" title="Post to del.icio.us, etc." id="akst_link_38153" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Designed%20as%20Designer&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F31%2F38153%2F" id="akst_email_38153" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>URIs Should Be Persistent</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/30/38145/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/30/38145/#comments</comments>
    <pubDate>Mon, 30 Mar 2009 12:02:54 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38145</guid>
    <description><![CDATA[When you are creating a new URI for a site you are building, give it a lot of thought. You should aim to design a URI which can last forever. Of course, this is not news. Jakob Nielsen said it 10 years ago. But in the intervening 10 years, we&#8217;ve gone from URIs which typically [...]]]></description>
      <content:encoded><![CDATA[<p>When you are creating a new URI for a site you are building, give it a lot of thought. You should aim to design a URI which can last forever. Of course, this is not news. <a title="URL as UI" href="http://www.useit.com/alertbox/990321.html">Jakob Nielsen said it 10 years ago</a>. But in the intervening 10 years, we&#8217;ve gone from URIs which typically used to look something like this:</p>
<blockquote><p><code>http://www.example.com/foo.html</code></p></blockquote>
<p>&#8230;which is fine, because if you go to such a link, you probably really will get HTML back, to URIs which (often) look something like this:</p>
<blockquote><p><code>http://www.example.com/foo.php</code></p></blockquote>
<p>&#8230;which, <a title="The Web Is Just Text" href="http://blogs.teamb.com/craigstuntz/2009/02/16/38024/">as I noted in a previous post</a>, is a lie. Actually, it&#8217;s worse than a lie; it&#8217;s poor encapsulation. What happens when you come to your senses and stop using PHP? Now you URIs have to change, which means you get to either create redirects for that abomination or break every link to your site. One of the things we&#8217;ve learned from the success of Google is that the information encoded in the links between sites is nearly as important as the information on the sites itself.</p>
<p><em>The web is dynamic. It has to be, because it is too big to compile. </em>And so the same concerns we have when writing code and dynamic languages often apply to creating a web site, whether you use a dynamic language or not. You need to choose very good names, because if you ever need to change them you will either break stuff or have a substantial job on your hands correcting every reference to the name you&#8217;ve changed, including references you don&#8217;t personally control.</p>
<p>So I&#8217;m going to propose a general rule, which states, "<strong>Any URI which allows an informed developer to discern the technology used to serve the result is probably broken.</strong>" The resources you are serving, if they are at all valuable to the user, will probably last longer than the implementation you use to serve them.</p>
<p>Of course, choosing good names is hard. <a title="Naming is Hard" href="http://blog.stackoverflow.com/2009/03/it-stack-overflow-update-naming-is-hard/">I read a great quote the other day</a>:</p>
<blockquote><p>There are only two hard things in Computer Science: cache invalidation and naming things. -Phil Karlton</p></blockquote>
<p>Also, even after you&#8217;ve chosen a good URI, you may have to do extra work to make it functional. If routing is not built into the technology stack you&#8217;re using, you may have to implement a URL rewriter to make your persistent URIs functional. It&#8217;s worth the effort to do so.</p>
<p><strong>Late update</strong>: Thank you to commentor <a href="http://www.stecki.de/">Stecki</a> for <a href="http://blogs.teamb.com/craigstuntz/2009/03/30/38145/#comment-5058">the link to</a> the following article: <a href="http://www.w3.org/Provider/Style/URI">Cool URIs don&#8217;t change</a>, by Tim Berners-Lee. Well said.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38145&amp;akst_action=share-this" onclick="akst_share('38145', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F30%2F38145%2F', 'URIs+Should+Be+Persistent'); return false;" title="Post to del.icio.us, etc." id="akst_link_38145" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=URIs%20Should%20Be%20Persistent&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F30%2F38145%2F" id="akst_email_38145" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Why Has the Size of TObject Doubled In Delphi 2009?</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/25/38138/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/25/38138/#comments</comments>
    <pubDate>Wed, 25 Mar 2009 11:23:00 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38138</guid>
    <description><![CDATA[Because it has a new feature.
Mason Wheeler noticed that TObject.InstanceSize returns 8 (bytes). It turns out that this is new in Delphi 2009; in previous releases, TObject.InstanceSize returned 4. But when you look at the definition of TObject in System.pas, you don&#8217;t see any fields declared at all.
Four out of the eight bytes are consumed [...]]]></description>
      <content:encoded><![CDATA[<p>Because it has a new feature.</p>
<p><a title="TURBU" href="http://turbu-rpg.com/">Mason Wheeler</a> noticed that <a title="What data does a TObject contain?" href="http://stackoverflow.com/questions/679022/what-data-does-a-tobject-contain">TObject.InstanceSize returns 8</a> (bytes). It turns out that this is new in Delphi 2009; in previous releases, TObject.InstanceSize returned 4. But when you look at the definition of TObject in System.pas, you don&#8217;t see any fields declared at all.</p>
<p>Four out of the eight bytes are consumed by the <acronym title="Virtual Method Table">VMT</acronym>; this has been true since the first version of Delphi. You can read more about that in <a title="The Delphi Object Model" href="http://oreilly.com/catalog/delphi/chapter/ch02.html">this chapter from <em>Delphi In A Nutshell</em></a>, which is old, but still accurate insofar as the VMT is concerned.</p>
<p>But what about the remaining four bytes? I didn&#8217;t remember the answer, but I enjoy a good puzzle, so I took a closer look at the source code for TObject. While poking around in System.pas, I happened to notice the following constants:</p>
<blockquote>
<pre><code><span style="color: #008000"><em>{ Hidden TObject field info }</em></span>
hfFieldSize          = <span style="color: #0000ff">4</span>;
hfMonitorOffset      = <span style="color: #0000ff">0</span>;</code></pre>
</blockquote>
<p>OK, that explains the four bytes, but what is this used for? Searching for <code>hfFieldSize</code> yielded the answer:</p>
<blockquote>
<pre><code><strong>class function</strong> TMonitor.GetFieldAddress(AObject: TObject): PPMonitor;
<strong>begin</strong>
  Result := PPMonitor(Integer(AObject) + AObject.InstanceSize - hfFieldSize + hfMonitorOffset);
<strong>end</strong>;</code></pre>
</blockquote>
<p>So any object <em>can </em>have a reference to a TMonitor instance, and that reference is as big as a pointer on the target CPU. That reminded me of <a title="Lock my Object… Please!" href="http://blogs.embarcadero.com/abauer/2008/02/19/38856">Allen Bauer&#8217;s long series of blog posts last year on the "Delphi Parallel Library,"</a> which discuss the TMonitor class in detail. He notes:</p>
<blockquote><p>The TMonitor class<em> [...] </em>is now tied directly to any TObject instance or derivative (which means <em>any</em> instance of a Delphi <strong>class</strong>).  <em>[...] </em>For Tiburón <em>[a.k.a. Delphi 2009]</em>, you merely need to call System.TMonitor.Enter(&lt;obj&gt;); or System.TMonitor.Exit(&lt;obj&gt;); among the other related methods.</p></blockquote>
<p>The ability to lock any object is a good feature to have, especially in a multi-CPU, multi-core world. So I&#8217;m happy to spend the extra four bytes to get this feature. But I do find the implementation a bit mysterious. Why not just declare an actual field in TObject? I guess one reason would be to reduce the chance of a conflict with existing code. Another possible reason would be to enforce TMonitor&#8217;s contract; by obfuscating access to the field, you reduce the chances that an uninformed programmer performs actions on the field which break the contract. But these are just guesses. I don&#8217;t know why the Delphi team settled on this implementation. I presume they have some good reason.</p>
<p><strong>Update:</strong> In comments, <a href="http://blogs.codegear.com/abauer">Allen Bauer</a> explains <a href="http://blogs.teamb.com/craigstuntz/2009/03/25/38138/#comment-4937">the reasons for this implementation</a>:</p>
<blockquote><p>The reason for always placing the monitor reference field at the end of the object instance is mainly for backward compatibility. I didn’t want to alter the layout of objects in case there was some code out there that depended upon it. Also, by hiding the implementation the chance of inadvertent mucking with the monitor data was reduced and therefore it increased the overall safety of using it.</p>
<p>If you look closely at what happens on descendant instances, the monitor field is <strong>always </strong>the last field of the instance. This happens because the compilers (Delphi &amp; C++) ensure that the field is allocated as the last step in the process of laying out the class instance. By doing this, an object laid out in pre-Delphi 2009 will be laid out exactly the same in Delphi 2009 except there is now an extra trailing pointer-sized field.</p></blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38138&amp;akst_action=share-this" onclick="akst_share('38138', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F25%2F38138%2F', 'Why+Has+the+Size+of+TObject+Doubled+In+Delphi+2009%3F'); return false;" title="Post to del.icio.us, etc." id="akst_link_38138" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Why%20Has%20the%20Size%20of%20TObject%20Doubled%20In%20Delphi%202009%3F&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F25%2F38138%2F" id="akst_email_38138" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>InterBase 2009 Hotfix Update 2</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/23/38135/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/23/38135/#comments</comments>
    <pubDate>Mon, 23 Mar 2009 23:49:31 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38135</guid>
    <description><![CDATA[IB 2009 Hotfix Update 2 is available for download, and includes many bug fixes.
]]></description>
      <content:encoded><![CDATA[<p>IB 2009 Hotfix Update 2 is <a title="InterBase Registered User Downloads" href="http://cc.embarcadero.com/reg/interbase">available for download</a>, and includes <a title="InterBase 2009 Hotfix Update 2 Readme (version 9.0.2.369)" href="http://edn.embarcadero.com/article/39435#6ResolvedDefects">many bug fixes</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38135&amp;akst_action=share-this" onclick="akst_share('38135', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38135%2F', 'InterBase+2009+Hotfix+Update+2'); return false;" title="Post to del.icio.us, etc." id="akst_link_38135" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=InterBase%202009%20Hotfix%20Update%202&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38135%2F" id="akst_email_38135" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>What ASP.NET MVC Did Learn from Rails</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/23/38130/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/23/38130/#comments</comments>
    <pubDate>Mon, 23 Mar 2009 19:30:27 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38130</guid>
    <description><![CDATA[This morning, I saw two different posts from Rails developers who were newly learning ASP.NET MVC, both bemoaning the fact that ASP.NET MVC does not supply/force upon you one particular ORM. The dependency on ActiveRecord is, to my way of thinking, a shortcoming of Rails, which the Rails community is presently doing an exceptional job [...]]]></description>
      <content:encoded><![CDATA[<p>This morning, I saw two different posts from <a title=".NET MVC vs Ruby on Rails" href="http://www.tokumine.com/2009/03/21/net-mvc-vs-ruby-on-rails/">Rails developers who were newly learning ASP.NET MVC</a>, both <a title="What ASP.NET MVC Can Learn From Ruby on Rails" href="http://www.kevinwilliampang.com/post/What-ASPNET-MVC-Can-Learn-From-Ruby-on-Rails.aspx">bemoaning the fact that ASP.NET MVC does not supply</a>/force upon you one particular ORM. The <a title="Rails without ActiveRecord" href="http://blog.lathi.net/articles/2007/08/08/rails-without-activerecord">dependency on ActiveRecord</a> is, to my way of thinking, a shortcoming of Rails, <a title="Lightweight Frameworks, Again" href="http://blogs.teamb.com/craigstuntz/2008/12/26/37874/">which the Rails community is presently doing <em>an exceptional job of fixing</em></a>. The best way to learn from that mistake is to not repeat it.</p>
<p>Yes, it is true that ASP.NET MVC does not force you to use one particular ORM. Yes, that means that you&#8217;re going to have to expend some thought, and quite possibly even effort, deciding which one is appropriate for you. It will not be sufficient to read a blog post about the Entity Framework from somebody who tried it once and another blog post about NHibernate from somebody who saw a screencast about it and then conclude that there are no workable solutions in the world.</p>
<p>But it&#8217;s worth the effort, because you have a big reward in store: Whatever choice you make will work just fine with ASP.NET MVC. Because the framework has no dependencies whatsoever on any ORM, all ORMs work equally well. You get to choose the best tool for your data access needs without worrying that your web framework will reject it.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38130&amp;akst_action=share-this" onclick="akst_share('38130', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38130%2F', 'What+ASP.NET+MVC+Did+Learn+from+Rails'); return false;" title="Post to del.icio.us, etc." id="akst_link_38130" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=What%20ASP.NET%20MVC%20Did%20Learn%20from%20Rails&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38130%2F" id="akst_email_38130" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Mike Rozlog to Speak to Columbus Architecture Group</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/20/38126/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/20/38126/#comments</comments>
    <pubDate>Fri, 20 Mar 2009 19:41:03 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[CodeRage]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38126</guid>
    <description><![CDATA[Mike Rozlog, the product manager for the JBuilder and 3rdRail products for Embarcadero, will be speaking to the Columbus Architecture Group on Monday, April 6, at 6:00 p.m., on the subject of software archaeology. For more information on the topic, here is a slide deck for one of his previous presentations on the subject, and [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://blogs.embarcadero.com/michaelrozlog/">Mike Rozlog</a>, the product manager for the JBuilder and 3rdRail products for <a href="http://www.embarcadero.com/">Embarcadero</a>, will be speaking to the <a href="http://www.colarc.org/2009/03/guest-speaker-at-april-6th-meeting.html">Columbus Architecture Group on Monday, April 6, at 6:00 p.m.</a>, on the subject of <a href="http://www.embarcadero.com/solutions/software_archeology.php">software archaeology</a>. For more information on the topic, here is <a href="http://blogs.embarcadero.com/files/2007/12/radstudiowebinar_192.pdf">a slide deck for one of his previous presentations on the subject</a>, and <a href="http://cc.embarcadero.com/Item/26427">here&#8217;s a video replay</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38126&amp;akst_action=share-this" onclick="akst_share('38126', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F20%2F38126%2F', 'Mike+Rozlog+to+Speak+to+Columbus+Architecture+Group'); return false;" title="Post to del.icio.us, etc." id="akst_link_38126" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Mike%20Rozlog%20to%20Speak%20to%20Columbus%20Architecture%20Group&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F20%2F38126%2F" id="akst_email_38126" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>ASP.NET Routing and ASP.NET MVC</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/18/38085/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/18/38085/#comments</comments>
    <pubDate>Wed, 18 Mar 2009 13:02:58 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38085</guid>
    <description><![CDATA[.NET 3.5 SP1 introduced ASP.NET Routing. This feature is primarily used by ASP.NET MVC and Dynamic Data. Routing is actually a very simple feature; here is what it does:

Stores a list of routes.
Translates an incoming URI into lists of values and tokens, and passes those lists to the handler specified on the route. In the [...]]]></description>
      <content:encoded><![CDATA[<p>.NET 3.5 SP1 introduced ASP.NET Routing. This feature is primarily used by ASP.NET MVC and Dynamic Data. Routing is actually a very simple feature; here is what it does:</p>
<ul>
<li>Stores a list of routes.</li>
<li>Translates an incoming URI into lists of values and tokens, and passes those lists to the handler specified on the route. In the MVC framework, this feature is used to call the appropriate Controller/Action.</li>
<li>Translates a list of values into a URI suitable for inclusion within an HTML page. In the MVC framework, this feature is most commonly used in the <code>Html.RouteLink/ActionLink</code> methods you call to generate a link in your Views.</li>
</ul>
<p>Let&#8217;s examine in more detail how MVC uses Routing, and distinguish between the features of Routing and the MVC framework.</p>
<h2>Components of a URI</h2>
<p>Consider this sample URI:</p>
<p><code>http://www.example.com:80/SiteRoot/Controller/Action?foo=A&amp;bar=B#anchor</code></p>
<p>The individual parts of the URI are:</p>
<ul>
<li>The <strong>scheme </strong>(protocol), <strong>authority </strong>(host), and <strong>port </strong>("<code>http://www.example.com:80</code>" in this sample URI). I will mostly ignore this part in the rest of the post, since Routing doesn&#8217;t deal with it, except to pass it along when necessary.</li>
<li>The <strong>path </strong>("<code>/SiteRoot/</code><code>Controller/Action</code>" in this example). Per the <a title="Generic Syntax" href="http://www.ietf.org/rfc/rfc3986.txt">URI RFC</a>, this part "serves to identify a resource&#8230;" I&#8217;ll talk about what that means in a second.</li>
<li>The <strong>query </strong>("<code>?foo=A&amp;bar=B</code>" in this example). My example uses name/value pairs is the query, because that seems to be the most common case. However, the RFC says that the query can be almost anything, and the purpose of the query is to provide a non-hierarchical means of identifying the resource requested by the user.</li>
<li>The <strong>fragment </strong>("<code>#anchor</code>" in this example). I&#8217;m going to ignore this, since Routing doesn&#8217;t deal with it.</li>
<li>I&#8217;ve omitted some stuff like username/password which is almost never used today.</li>
</ul>
<h2>MapRoute</h2>
<p>Now lets examine a simple case of adding a route to the routing system. This is from the default MVC application template:</p>
<blockquote>
<pre><code>routes.MapRoute(
    <span style="color: #ff0000">"Default"</span>,                                              <span style="color: #339966">// Route name</span>
    <span style="color: #ff0000">"{controller}/{action}/{id}"</span>,                           <span style="color: #339966">// URL with parameters</span>
    <strong>new </strong>{ controller = <span style="color: #ff0000">"Home"</span>, action = <span style="color: #ff0000">"Index"</span>, id = <span style="color: #ff0000">""</span> }  <span style="color: #339966">// Parameter defaults</span>
);</code></pre>
</blockquote>
<p>Note that <code>MapRoute </code>is actually not part of the routing system; it&#8217;s an extension method added to <code>RouteCollection </code>by ASP.NET MVC. Calling <code>MapRoute </code>will add a single route to the <code>RouteCollection</code>. Most web applications will have only one <code>RouteCollection</code>, stored in <code>System.Web.Routing.RouteTable.Routes</code>. The most important thing that <code>MapRoute </code>does is to create and pass an <code>MvcRouteHandler </code>instance when adding the route to the <code>RouteCollection</code>. This ensures that when ASP.NET handles an incoming URI which matches this route, control will be passed to the MVC framework for handling the request.</p>
<p>The second argument to <code>MapRoute </code>is named "<code>url</code>", but it&#8217;s not really a complete URL. Instead, it is a template for a fragment of a URL containing <em>a portion of</em> the path component of a URI. I say "a portion of the path" because it omits the site root, which I&#8217;ve called "<code><code>/SiteRoot</code></code>" in the example above. The site root is often empty, but it doesn&#8217;t have to be. The URIs produced by the routing system include quite a bit more than the path, however. They also include the scheme/authority (in other words, the protocol and host) and, sometimes, a query.</p>
<p>There are a number of overloads to MapRoute. In addition to the values passed in this simple example, you can also pass constraints (which I&#8217;ll discuss in a moment) and namespaces. The namespaces argument is for MVC only (it&#8217;s not used by routing) and is useful when you want to put a Controller in a place where MVC wouldn&#8217;t otherwise find it.</p>
<p>A route can also contain <code>DataTokens</code>, which are not used by the routing system, but are passed to the route handler. <code>MapRoute </code>doesn&#8217;t have an overload which includes these as an argument, and I&#8217;m not going to discuss them in this post. ASP.NET MVC uses them only to store the <code>namespaces </code>argument, discussed above.</p>
<h2>Parsing a URI</h2>
<p>Let&#8217;s examine what happens when the routing system is asked to interpret a URI submitted by the user. Importantly, the RouteCollection is ordered. So the routing system will attempt to match the routes in the collection in the order you added them. The first matching route "wins" even if a later route is a "better" match. The incoming URI is compared with the url portion of the route. If it matches, the entire URI, including the query, is tokenized. If there are any constraints on the route, these are considered.</p>
<p><em>In practice, this means that if you have a lot of routes, then you are almost guaranteed to encounter a bug, sooner or later, where the wrong route is matched to an incoming URI. The only good way to prevent this that I know of is to write unit tests for your routes.</em> Unfortunately, the name of the route is not actually part of the route itself. It is stored in a private, internal dictionary in the RouteCollection. So there is no way to write a unit test which examines the name of the route returned.</p>
<p>Let&#8217;s use the sample URI and route from earlier in this post as an example. Out of the entire URI, <code>http://www.example.com:80/SiteRoot/</code><code>Controller/Action</code><code>?foo=A&amp;bar=B#anchor</code>, the routing system is only going to examine this bit when processing an incoming URI:</p>
<p><code>/</code><code>Controller/Action</code><code>?foo=A&amp;bar=B#anchor</code></p>
<p>Does this match the url portion of the route defined above? Recall that it is defined as:</p>
<pre><code><span><span style="color: #ff0000">"{controller}/{action}/{id}"
</span></span></code></pre>
<p>Yes, it matches, because "<code>Controller</code>" can be interpreted as the "<code>{controller}</code>" portion of the <code>url</code>, "<code>Action</code>" for the "<code>{action}</code>" part, and a default value exists for the "<code>{id}</code>" portions (empty string). Note that this means that having default values in a route makes that route much more likely to "match" an incoming URI. If there are defaults for every token in a URL pattern and there are no constraints, then that route will match every incoming URI. The route shown in this post is created by the MVC framework as a "catch all" route for a new application, which contains only that route. That is why it has defaults for all of its values and no constraints; it is intended to match every incoming URI. If, on the other hand, you write a special-purpose route intended only for one particular controller or action, and you provide default values for all of the tokens, then you need to implement constraints to prevent this route for matching other controllers or actions.</p>
<p>Because the url matches, we have five values, so far, to pass as the route data. "controller" will have the value Controller, and "action" will have the value "Action". "id" will have the default value. Also, from the query, "foo" will have the value "A", and "bar" will have the value "B". Now the routing system considers any constraints on the route, but in this case, there aren&#8217;t any. Therefore, this list of values is handed to the MvcRouteHandler which was created by MapRoute.</p>
<p><em>Importantly</em>, note that all of these values are strings. The routing system only deals with URIs, which are always strings. Now, your actions on your controllers can have arguments which are not strings, and the MVC framework will attempt to coerce the strings supplied by the routing system into whatever type is specified in the method signature. But that&#8217;s a feature of the MVC framework, not of the routing system. (Yes, the <code>Values</code> property returns type <code>object</code>, but, when matching an incoming URI, the segments are always added as strings.)</p>
<p>Not all URI patterns are as simple as the default route from the standard MVC application template. You can use delimiters other than /, for example. If you have hyphens, parentheses, etc. in your <code>url </code>template, these will be matched against the incoming URI to determine if the route is a match. The following route, for example, would not match the sample URI at the top of the post, even though it contains all of the necessary tokens and has no constraints:</p>
<blockquote>
<pre><code>routes.MapRoute(
    <span style="color: #ff0000">"Parenthesized"</span>,                                        <span style="color: #339966">// Route name</span>
    <span style="color: #ff0000">"{controller}({action})({id})"</span>,                         <span style="color: #339966">// URL with parameters</span>
    <strong>new </strong>{ id = <span style="color: #ff0000">""</span> }                    <span style="color: #339966">                     // Parameter defaults</span>
);</code></pre>
</blockquote>
<p>The incoming URI contains no parentheses, so this route can&#8217;t match, because the parentheses are needed to to delimit the values for <code>controller</code> and <code>action</code>, and there are no defaults for this values.</p>
<h2>Matching a Route With an Action</h2>
<p>After a route is matched to an incoming URI, and a list of route values is created, control goes to the <code>MvcRouteHandler</code>. Now the MVC framework can invoke the action on the controller specified by the "action" and "controller" route values. Note that there is nothing special about these names/values to the routing system; they&#8217;re just two more values in the list from the routing system&#8217;s point of view. But these two names, "action" and "controller" are very important to the MVC framework, for obvious reasons.</p>
<p><code>MvcRouteHandler </code>(indirectly) calls <code>MvcHandler.ProcessRequest</code>, which constructs the controller using the <code>ControllerFactory</code>, and then calls <code>Controller.Execute</code>, which, in turn, invokes the action using the <code>ControllerActionInvoker</code>. It is at this point that the values in the route are matched against the arguments for the action. In other words, tokenizing the URI and matching those values with action arguments are two entirely separate operations. The tokenizing is done by the routing system, and the matching route values with controller action arguments is done by the MVC framework.</p>
<p>In order to invoke the action, the MVC framework needs to look at the individual arguments to the action, and match them with route values. This is performed by the model binding system.</p>
<p>Note that the name of the argument does not have to correspond to a name in the route values if the model binding system can instantiate an instance of the type of the argument from the values which do exist. For example, if the type of the argument is FormCollection, then this argument can always be passed, no matter what names are present in the route values, and no matter what the name of the argument. The model binding system knows that it can always create a FormCollection by rolling up any values in the form in the incoming POST, if there are any. If there are not, it will simply return an empty FormCollection.</p>
<p>If the action takes an argument which cannot be instantiated based on the data in the route values, that is fine, so long as the argument is nullable. If the action requires a non-nullable argument which is not in the route values, or if the route values contain a value for an argument which cannot be bound into the type of that argument, the MVC framework will throw an exception. Otherwise, the action will be invoked.</p>
<h2>Creating a URI With RouteLink</h2>
<p>Creating an "<strong>a href=</strong>" tag with <code>Html.RouteLink</code> is trivial. The routing system looks up the route by name, and populates the URI with values from the <code>RouteCollection </code>you passed. Any values in the <code>RouteCollection </code>not included in the string in the <code>url </code>argument to <code>MapRoute </code>will be added to the resulting link as query string parameters. In my view, you should always prefer <code>RouteLink </code>over <code>ActionLink</code>, whenever there is any ambiguity as to which route will be returned.</p>
<p>Again, let&#8217;s consider an example, with the route defined in the MapRoute call earlier in this post:</p>
<blockquote>
<pre><code>&lt;%= Html.RouteLink(<span style="color: #ff0000">"Link text to display on page"</span>, <span style="color: #ff0000">"Default"</span>,
    <strong>new </strong><span style="color: #339966">RouteValueDictionary</span>(<strong>new </strong>{controller = <span style="color: #ff0000">"Foo"</span>, action = <span style="color: #ff0000">"Bar"</span>, foo = <span style="color: #ff0000">"A"</span>, bar = <span style="color: #ff0000">"B"</span> })) %&gt;</code></pre>
</blockquote>
<p>With this example, the order of the routes in the <code>RouteCollection</code>, the constraints, etc., are not needed to find the matching route, because we have specified ("<code>Default</code>") directly. Since there are no tokens called "foo" and "bar" in the <code>url</code> argument we passed to <code>MapRoute</code>, these will be appended to the generated URI as query string parameters. So we end up with the sample URI at the top of this post, less the anchor, provided that the site is configured to live in /SiteRoot.</p>
<h2>Creating a URI With ActionLink</h2>
<p><code>ActionLink </code>is more complicated, because the routing system must first <em>find </em>an appropriate route, and then use that route to generate the URI. In a way, the method of finding the route is similar to the method used when parsing a URI, insofar as the first matching route "wins." But in another way, it is very different, because there is no incoming URI to use as a pattern for matching the partial template passed as the <code>url</code> argument to <code>MapRoute</code>. The only thing that the <code>url</code> argument is used for in this scenario is determining which tokens must be included, either directly, or via defaults, in order for a route to match. Let&#8217;s re-examine the same scenario considered in the RouteLink section, above, only this time using <code>ActionLink</code>. The call looks like this:</p>
<blockquote>
<pre><code>&lt;%= Html.ActionLink(<span style="color: #ff0000">"Link text to display on page"</span>, <span style="color: #ff0000">"Bar"</span>, <span style="color: #ff0000">"Foo"</span>,
    <strong>new </strong><span style="color: #339966">RouteValueDictionary</span>(<strong>new </strong>{foo = <span style="color: #ff0000">"A"</span>, bar = <span style="color: #ff0000">"B"</span> })) %&gt;</code></pre>
</blockquote>
<p>Does this match the route defined at the top of this post? Yes it does, and here&#8217;s why: That route contains three tokens in its <code>url </code>argument. They are <code>controller</code>, <code>action</code>, and <code>id</code>. I have supplied values for two of these tokens in the call to <code>ActionLink</code>, namely <code>controller </code>and <code>action</code>, via the <code>controller </code>and <code>action </code>arguments in the overload of <code>ActionLink </code>I am using here. The remaining required token, <code>id</code>, is not supplied in the <code>ActionLink </code>call at all. However, there was a default for it (empty string) in the original call to <code>MapRoute</code>, so the route matches even without an explicit value for <code>id</code>. Because <code>foo </code>and <code>bar </code>are present in the <code>RouteValueDictionary</code>, but the <code>url </code>template in the route does not contain <code>{foo}</code> or <code>{bar}</code>, these will be added to the generated URI as query string parameters. Again, the generated URI will be the sample URI at the top of this post, less the anchor, provided that the site is configured to live in /SiteRoot.</p>
<h2>Conclusions</h2>
<p>I hope this long explanation has taken some of the mystery out of what routing does. Since there&#8217;s a lot of detail above, I&#8217;m going to summarize some of the information which is important for day-to-day work.</p>
<ul>
<li>Routing and the MVC framework are distinct features. MVC knows about Routing, but Routing does not know about MVC. Routing produces a list of values, but does not assign special meaning to them. MVC signs special meaning to the controller and action values.</li>
<li>Routes include information about a portion of the path in the URI and also the query, since any token not in the path is treated as part of the query.</li>
<li>The order of routes is very important, both for parsing incoming URIs and for generating URIs with ActionLink.</li>
<li>Default values in a route will cause the route to match more incoming URIs or sets of values in a <code>RouteValueDictionary</code>. Constraints in a route will cause the route to match fewer incoming URI this or sets of values in a <code>RouteValueDictionary</code>. If there are defaults for every token in a URL pattern and there are no constraints, then that route will match every incoming URI or sets of values in a <code>RouteValueDictionary</code>. For a "catch all" route like the one in the default MVC application, it is fine for all of the tokens to have default values in for there to be no constraints. If you write a special-purpose route for a particular controller or action, however, then you should probably use constraints to prevent it from ever matching any other controller or action.</li>
<li>If you have more than one route, then you simply <em>must </em>write unit tests to ensure that the correct route is selected for all incoming URIs or values used in your calls to ActionLink.</li>
</ul>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38085&amp;akst_action=share-this" onclick="akst_share('38085', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F18%2F38085%2F', 'ASP.NET+Routing+and+ASP.NET+MVC'); return false;" title="Post to del.icio.us, etc." id="akst_link_38085" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=ASP.NET%20Routing%20and%20ASP.NET%20MVC&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F18%2F38085%2F" id="akst_email_38085" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>A Not-So-Secret Sale</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/17/38109/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/17/38109/#comments</comments>
    <pubDate>Tue, 17 Mar 2009 11:02:09 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38109</guid>
    <description><![CDATA[Upscene Productions is offering their Database Workbench Pro product for 75% off, through 28 March 2009 only. They call this the "Super Secret Sale," but since Martijn asked me to post it here, I&#8217;m not sure how much of a secret it is. Anyway, 75% off is about as cheap as you&#8217;ll ever find it, [...]]]></description>
      <content:encoded><![CDATA[<p>Upscene Productions is <a href="http://www.upscene.com/dbw_secretsupersale.php">offering their Database Workbench Pro product for 75% off</a>, through 28 March 2009 only. They call this the "Super Secret Sale," but since Martijn asked me to post it here, I&#8217;m not sure how much of a secret it is. Anyway, 75% off is about as cheap as you&#8217;ll ever find it, so if you&#8217;ve been considering buying the tool, now is a good time.</p>
<p><a href="http://www.upscene.com/products.dbw.index.php">Database Workbench</a> supports InterBase and many other DB servers. You can buy the module for one (or more) DB server only if you don&#8217;t need all of them.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38109&amp;akst_action=share-this" onclick="akst_share('38109', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F17%2F38109%2F', 'A+Not-So-Secret+Sale'); return false;" title="Post to del.icio.us, etc." id="akst_link_38109" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=A%20Not-So-Secret%20Sale&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F17%2F38109%2F" id="akst_email_38109" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>SQL Performance Tuning Book Includes InterBase</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/16/38097/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/16/38097/#comments</comments>
    <pubDate>Mon, 16 Mar 2009 19:21:22 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38097</guid>
    <description><![CDATA[SQL Performance Tuning, by Peter Gulutzan and Trudy Pelzer, "is a guide for users and programmers who want to improve SQL performance no matter what brand of SQL they use. &#8230; All the ideas have been tested against the eight leading DBMS applications."
I haven&#8217;t read this book, but someone in the newsgroups mentioned that it [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.pearsoned.co.uk/Bookshop/detail.asp?item=302416">SQL Performance Tuning, by Peter Gulutzan and Trudy Pelzer</a>, "is a guide for users and programmers who want to improve SQL performance no matter what brand of SQL they use. &#8230; All the ideas have been tested against the eight leading DBMS applications."</p>
<p>I haven&#8217;t read this book, but <a href="https://forums.codegear.com/thread.jspa?threadID=13638&amp;tstart=0#91911">someone in the newsgroups mentioned that it included InterBase</a>. He writes:</p>
<p style="padding-left: 30px">"Note that they tested on IB6 — but I have still found most of their advice to be valid."</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38097&amp;akst_action=share-this" onclick="akst_share('38097', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F16%2F38097%2F', 'SQL+Performance+Tuning+Book+Includes+InterBase'); return false;" title="Post to del.icio.us, etc." id="akst_link_38097" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=SQL%20Performance%20Tuning%20Book%20Includes%20InterBase&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F16%2F38097%2F" id="akst_email_38097" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>A Functional View of A Web Server</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/05/38072/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/05/38072/#comments</comments>
    <pubDate>Thu, 05 Mar 2009 14:31:35 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38072</guid>
    <description><![CDATA[A few days ago, I opined that, "Web applications, as a class, are extremely easy to debug." I&#8217;m going to further explain why I think that is true by introducing a useful abstraction which you can employ when you are debugging a web application which doesn&#8217;t seem to do what is is intended to do.
When [...]]]></description>
      <content:encoded><![CDATA[<p>A few days ago, I opined that, "<a title="The Web Is Just Text" href="http://blogs.teamb.com/craigstuntz/2009/02/16/38024/">Web applications, as a class, are extremely easy to debug.</a>" I&#8217;m going to further explain why I think that is true by introducing a useful abstraction which you can employ when you are debugging a web application which doesn&#8217;t seem to do what is is intended to do.</p>
<p>When a web application misbehaves, one of the first things you&#8217;ll need to do is determine if the problem is in the browser/client (e.g., buggy JavaScript, attempting to use CSS on IE 6, etc.) or in the server application (e.g., returns incorrect HTML, inserts wrong data into database, etc.). In order to make this distinction, it is helpful to use a very simple conception of what a web application does. HTTP is a stateless protocol. Therefore, a web server is expected to always return the same results in response to a certain request, without regard to what has happened beforehand. So we can consider the server as a single function:</p>
<div id="attachment_38073" class="wp-caption alignnone" style="width: 510px"><a href="/files/2009/03/web-server-function_1054.png"><img src="/files/2009/03/web-server-function_1054.png" alt="(Browser request, state) -&gt; web server -&gt; result (usually HTML)" width="500" height="194" /></a><p class="wp-caption-text"> </p></div>
<p>The illustration above may appear a bit strange, because of the close proximity of the browser and the database server. In reality, we know that the database server is likely closer to the web server than to the browser. But remember, I am attempting to treat the web server as a pure function here (I&#8217;ll explain why in a minute). The state of the database, if there is one, will certainly affect the page returned by the web server. Therefore, it is an input to the function. Similarly, authentication, which can also change the page returned by the web application is most often stored in a cookie. So cookies are also inputs to the server function.</p>
<p>Using this abstraction, it is now very easy to diagnose where the bug exists, by looking at the inputs to the function and its result:</p>
<ul>
<li>If the inputs are correct and the result is wrong, then the bug is in the server. But remember that "result" means the HTML returned by the server, not the manner in which the browser renders it. It is possible for correct HTML to be rendered incorrectly, especially if JavaScript or <a title="IE is teh 3v1l" href="http://weblog.jamisbuck.org/2005/6/3/ie-is-teh-3v1l">IE 6</a> are involved.</li>
<li>If the inputs are incorrect, then the bug is obvious. But remember, inputs can include things like form data which, for some reason, people don&#8217;t always tend to examine.</li>
<li>If the inputs and the result are both correct, but the page still looks wrong in the browser, then the bug is in the browser/client side.</li>
</ul>
<p>The only circumstance in which this abstraction doesn&#8217;t really work is when you&#8217;re maintaining state on the client. An example would be when using frames. If you click a link which targets a frame, the result that you see in the browser will be different depending upon what you have done before, because you might have other pages open in other frames. This is an example of why I think that frames are not a good architectural fit with the rest of the web.</p>
<p>Once you&#8217;ve determined eactly where the bug lives, you are well on your way to fixing it. You can also describe the bug with more precision. For example, you will say things like "the server returns incorrect HTML (incorrect style on the div with ID &#8216;foo&#8217;) when&#8230;" instead of "the panel is on the wrong place in the page when&#8230;".</p>
<h3>Colophon</h3>
<p>It&#8217;s not really relevant to the rest of the post, but here is how I made the illustration above. I decided the post would be easier to understand if I included a diagram of the function. So I followed my standard process for using Microsoft Visio, which is something along the lines of the following:</p>
<ol>
<li>Decide that I need a very simple block diagram, and remember that this is something which Visio is supposed to be good at.</li>
<li>Attempt to use Visio to produce the diagram.</li>
<li>"WTF, I&#8217;m not allowed to resize this? I thought that Visio was supposed to be for <em>simple </em>drawings."</li>
<li>Decide, "Wow, I&#8217;d forgotten how much I really despise Visio."</li>
<li>Produce diagram in some other piece of software.</li>
<li>Repeat, 6 months later. Some day I&#8217;ll learn.</li>
</ol>
<p>I ended up using <a href="http://www.inkscape.org/">Inkscape</a>, which has more than a few rough edges, but which was good enough to produce a simple diagram, which is more than I can personally say for Visio. The drawing includes an MPLed globe image, so I&#8217;m releasing the whole drawing under the terms of the MPL.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38072&amp;akst_action=share-this" onclick="akst_share('38072', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F05%2F38072%2F', 'A+Functional+View+of+A+Web+Server'); return false;" title="Post to del.icio.us, etc." id="akst_link_38072" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=A%20Functional%20View%20of%20A%20Web%20Server&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F05%2F38072%2F" id="akst_email_38072" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Columbus Architecture Group Lightning Talks</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/02/38063/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/02/38063/#comments</comments>
    <pubDate>Mon, 02 Mar 2009 15:58:26 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38063</guid>
    <description><![CDATA[The Columbus Architecture Group, a special interest group for software architects, is hosting "lightning talks" (a series of short, 10-20 minute presentations) tonight, at 6:00 p.m. in the Quick Solutions offices. I will be presenting a talk on "The Structure and Interpretation of URIs." See the list of other topics at the link.
Share This &#124; [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.colarc.org/2009/02/march-lightening-talks.html">The Columbus Architecture Group, a special interest group for software architects, is hosting "lightning talks"</a> (a series of short, 10-20 minute presentations) tonight, at 6:00 p.m. in the <a href="http://www.quicksolutions.com">Quick Solutions offices</a>. I will be presenting a talk on "The Structure and Interpretation of URIs." See the list of other topics at the link.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38063&amp;akst_action=share-this" onclick="akst_share('38063', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F02%2F38063%2F', 'Columbus+Architecture+Group+Lightning+Talks'); return false;" title="Post to del.icio.us, etc." id="akst_link_38063" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Columbus%20Architecture%20Group%20Lightning%20Talks&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F02%2F38063%2F" id="akst_email_38063" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Sampling Profiler</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/25/38058/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/25/38058/#comments</comments>
    <pubDate>Wed, 25 Feb 2009 14:26:26 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38058</guid>
    <description><![CDATA[Eric Grange&#8217;s free, sampling profiler for Delphi finally has a site to call its home.
]]></description>
      <content:encoded><![CDATA[<p><a href="http://delphitools.info/">Eric Grange&#8217;s free, sampling profiler</a> for Delphi finally has a site to call its home.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38058&amp;akst_action=share-this" onclick="akst_share('38058', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F25%2F38058%2F', 'Sampling+Profiler'); return false;" title="Post to del.icio.us, etc." id="akst_link_38058" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Sampling%20Profiler&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F25%2F38058%2F" id="akst_email_38058" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>All Access</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/20/38045/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/20/38045/#comments</comments>
    <pubDate>Fri, 20 Feb 2009 20:01:08 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38045</guid>
    <description><![CDATA[Embarcadero&#8217;s DavidI and Mike Rozlog stopped by the Vertex Systems office on Wednesday to chat with us about Embarcadero&#8217;s plans for the near future and David&#8217;s personal developer wish list.
They told us about the All Access product, which had been officially released that day. One of the most interesting things about this product is that [...]]]></description>
      <content:encoded><![CDATA[<p>Embarcadero&#8217;s <a href="http://blogs.codegear.com/davidi/">DavidI</a> and <a href="http://blogs.embarcadero.com/michaelrozlog/">Mike Rozlog</a> stopped by the <a href="http://www.vertexsystems.com/">Vertex Systems</a> office on Wednesday to chat with us about Embarcadero&#8217;s plans for the near future and David&#8217;s personal developer wish list.</p>
<p>They told us about the <a href="http://embarcadero.com/products/all_access/">All Access</a> product, which had been officially released that day. One of the most interesting things about this product is that it is installation-free, or so Embarcadero claims. It uses a virtualized registry, etc., so that you can just start the application directly. I&#8217;m thinking that this might be useful even outside of the context of All Access. Especially for something like a build machine, where you might want to run it in various different configurations. Sort of like a "lite" VM. It will be interesting to see if Embarcadero uses this technology outside of All Access.</p>
<p>One thing I wonder about right now: Perhaps the biggest differentiator between Delphi Enterprise and Delphi Architect is that with Architect you get Embarcadero <a href="http://embarcadero.com/products/er_studio/index.php">ER/Studio</a>. So with the way the SKUs are differentiated right now, All Access is sort of an alternative to Architect. That&#8217;s how it seems to me, anyway. I suspect that we will see a different feature mix in Architect in the future.</p>
<p>David expressed a lot of relief at not being part of Borland anymore. He said that since Embarcadero is private, they can talk about upcoming features more freely than when they were part of a publicly held corporation.</p>
<p>David also talked about how Delphi developers who do database work could really benefit from the Embarcadero database tools. He wants to bring the integration much closer. For example, he wants you to be able to step into the Rapid SQL <a href="http://embarcadero.com/products/debugger/">stored procedure debugger</a> directly when debugging through a Delphi application which called a stored procedure in the database. Embarcadero has profilers for Java applications and for database servers; you can see the potential for interaction there, too.</p>
<p>We are looking for a good solution for doing heterogeneous, bidirectional replication between InterBase and SQL Server. We have a working solution already using a SQL Server job and linked servers, but I would prefer a solution that we do not have to develop and maintain. I am aware of <a href="http://www.microtec.fr/copycat/ct/">CopyTiger</a>, which claims to support both, but doesn&#8217;t really seem flexible enough to do what we need. There are a lot of replicators which doesn&#8217;t explicitly support InterBase, that support JDBC or ODBC connections, and they could possibly be a solution. David suggested that Embarcadero&#8217;s <a href="http://embarcadero.com/products/change_manager/">Change Manager</a> product would be a potential solution for us, so we&#8217;re going to look into that.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38045&amp;akst_action=share-this" onclick="akst_share('38045', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F20%2F38045%2F', 'All+Access'); return false;" title="Post to del.icio.us, etc." id="akst_link_38045" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=All%20Access&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F20%2F38045%2F" id="akst_email_38045" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>jQuery 1.3.1 Selector Bug and Workaround</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/17/38038/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/17/38038/#comments</comments>
    <pubDate>Tue, 17 Feb 2009 11:36:56 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38038</guid>
    <description><![CDATA[In jQuery 1.2.6, if you wanted to select all inputs with empty values, you could do this:
var emptyInput = $("form input[value='']");
That&#8217;s a little hard to read, so note that the quotes around the entire selector are double quotes, but the quotes inside the square brackets are two single quotes. This says, "Give me any input [...]]]></description>
      <content:encoded><![CDATA[<p>In jQuery 1.2.6, if you wanted to select all inputs with empty values, you could do this:</p>
<blockquote><p><code><strong>var </strong>emptyInput = $("form input[value='']");</code></p></blockquote>
<p>That&#8217;s a little hard to read, so note that the quotes around the entire selector are double quotes, but the quotes inside the square brackets are two single quotes. This says, "Give me any input where the value is equal to empty string."</p>
<p><a title="1.3.1 selector bug - $('input[value=&quot;&quot;]')" href="http://dev.jquery.com/ticket/3990">This is broken in jQuery 1.3.1</a>. Try it, and you will see (if you have a debugger attached):</p>
<blockquote><p>Syntax error, unrecognized expression: value=""]</p></blockquote>
<p><a title="Changeset 6181" href="http://dev.jquery.com/changeset/6181">A fix for the bug has been checked in</a>, so you can get a corrected version in the nightly build. If you prefer to stick with 1.3.1, I&#8217;ve found a workaround; do this instead:</p>
<blockquote><p><code><strong>var </strong>emptyInput = $("form input:not([value])");</code></p></blockquote>
<p>This works because empty string is implicitly converted to false in JavaScript.</p>
<p><strong>Update: </strong>The bug is fixed in jQuery 1.3.2.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38038&amp;akst_action=share-this" onclick="akst_share('38038', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F17%2F38038%2F', 'jQuery+1.3.1+Selector+Bug+and+Workaround'); return false;" title="Post to del.icio.us, etc." id="akst_link_38038" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=jQuery%201.3.1%20Selector%20Bug%20and%20Workaround&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F17%2F38038%2F" id="akst_email_38038" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>The Web Is Just Text</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/16/38024/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/16/38024/#comments</comments>
    <pubDate>Mon, 16 Feb 2009 14:18:26 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38024</guid>
    <description><![CDATA[In the beginning (around 1990 or so), the World Wide Web was composed of three parts:

HTML, a markup language for displaying rich documents
HTTP, a stateless protocol for communicating with a web server
The URI, a short, standardized reference to a network resource

Almost 20 years later, very little has changed, especially from the point of view of [...]]]></description>
      <content:encoded><![CDATA[<p>In the beginning (around 1990 or so), the World Wide Web was composed of three parts:</p>
<ul>
<li><a href="http://www.w3.org/TR/1999/REC-html401-19991224/">HTML</a>, a markup language for displaying rich documents</li>
<li><a href="http://tools.ietf.org/html/rfc2616">HTTP</a>, a stateless protocol for communicating with a web server</li>
<li>The <a href="http://tools.ietf.org/html/rfc3986">URI</a>, a short, standardized reference to a network resource</li>
</ul>
<p>Almost 20 years later, very little has changed, especially from the point of view of the server. To the list above, we have added client-side stuff like JavaScript and CSS, and HTML is now at version 4. But HTTP and the URI are close to unchanged.</p>
<p>And <em>all three</em> of the items in the list above <em>are just text</em>. Not just any text, mind you, but text which is formatted in such a way as to be mostly easy for humans to read.</p>
<p><strong>This means that what web servers do is very simple.</strong> They accept text over a text-based protocol and return more text.</p>
<p>Despite this, people occasionally seem to find web servers confusing, in part because we like to lie about what they do. For example, you might see a URI which looks like this:</p>
<blockquote><p><code>http://www.example.com/foo.php</code></p></blockquote>
<p><strong>This is a lie.</strong> If you point a web browser at this URI, you will almost certainly not receive a PHP source file; instead, you will probably get HTML. That the HTML was generated with PHP source code is an implementation detail unsuitable for inclusion in a Uniform <strong>Resource </strong>Identifier.</p>
<p>Some people might think I&#8217;m being pedantic here. How many end users actually care what the extension in the URI is? These are probably the same people who post questions on Stack Overflow wondering why their web application doesn&#8217;t work, but not including in the question <em>the only things that the server really cares about</em>, which you can find in the list at the beginning of this post. It doesn&#8217;t matter if you generated your HTML using aspx, rhtml, or PHP. It&#8217;s still just plain HTML to the browser. When you submit a form, you&#8217;re submitting name/value pairs of strings, not "integers" and "dates" and "classes."</p>
<p>That&#8217;s why this matters to a programmer: <strong>Web applications, as a class, are <em>extremely </em>easy to debug.</strong> Tools like <a href="http://getfirebug.com/">Firebug</a> and <a href="http://www.fiddlertool.com/">Fiddler</a> allow you to see the text that is exchanged between the browser and the server, and even pretty it up a little to make it more readable than it already is. But already built-in to your web browser is the single most important tool that you need for debugging a web application; namely, the "View Source" command. Chances are very good that if you look at the HTML, the HTTP, and the URI, you can solve whatever issue you&#8217;re having with your web application. But if you can&#8217;t, including whichever of these three is relevant to the problem at hand will dramatically increase the chances of getting a solution when you ask someone else to help you out.</p>
<p>Perhaps it&#8217;s the fact that we&#8217;re used to debugging within an IDE which causes people to look at, for example, aspx source code instead of HTML when a web page doesn&#8217;t render the way we&#8217;d like, or to debug through model binders instead of looking at a form submission when the input to a controller action is not what we expect. But remember, the browser doesn&#8217;t see your aspx or PHP. The browser just sees the HTML you generate.</p>
<p>Perhaps another reason why this tends to confuse people is that certain web frameworks, such as ASP.NET, introduce fictions such as "event handlers" and "postbacks." <em>No such concepts exist within HTTP.</em> Instead, they are (extraordinarily leaky) abstractions built on top of HTTP within a certain framework. But under the hood, there is still just HTTP. If you want to understand the communication between your web application and a browser, look at the HTTP and the HTML.</p>
<p>I&#8217;m going to close this post with a recommendation: If you&#8217;ve never <a href="http://tonycode.com/wiki/index.php?title=Making_HTTP_requests_via_telnet">visited a web site via telnet</a>, go do it right now. It only takes a second, and <a href="http://www.dgate.org/~brg/bvtelnet80/">you&#8217;ll learn a lot in the process</a>. This is an easy way to understand at a very fundamental level how web browsers and web servers talk to each other. If you need to debug your web application at a client site and can&#8217;t install Fiddler, you can probably use Telnet instead.</p>
<p>This is the first article in a series on <a href="http://blogs.teamb.com/craigstuntz/tag/the-dynamic-web/">the dynamic web.</a></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38024&amp;akst_action=share-this" onclick="akst_share('38024', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F16%2F38024%2F', 'The+Web+Is+Just+Text'); return false;" title="Post to del.icio.us, etc." id="akst_link_38024" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=The%20Web%20Is%20Just%20Text&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F16%2F38024%2F" id="akst_email_38024" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>jQuery and ASP.NET MVC Model Binding to a List</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/11/38013/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/11/38013/#comments</comments>
    <pubDate>Wed, 11 Feb 2009 20:08:33 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38013</guid>
    <description><![CDATA[In ASP.NET MVC, when you want to submit a page with many instances of a certain type (e.g., a form with a list of phone numbers), the framework will recognize the form elements as a list if you use a specific format for the name attribute of the inputs. This allows you to have an [...]]]></description>
      <content:encoded><![CDATA[<p>In ASP.NET MVC, when you want to submit a page with many instances of a certain type (e.g., a form with a list of phone numbers), the framework will recognize the form elements as a list if you <a title=" ASP.NET MVC RC1 - Binding a List" href="http://www.distribucon.com/blog/ASPNETMVCRC1BindingAList.aspx">use a specific format for the name attribute of the inputs</a>. This allows you to have an action <a title="Model Binding To A List" href="http://haacked.com/archive/0001/01/01/model-binding-to-a-list.aspx">like this</a>:</p>
<blockquote>
<pre><code><strong>public </strong>ActionResult UpdateInts(IList&lt;<strong>int</strong>&gt; ints) {
</code></pre>
</blockquote>
<p>The MVC framework, in this case, will look at all the inputs on your form, figure out which inputs correspond to which records on the form, find each record individually, and pass the whole list to your action as an IList&lt;T&gt;. Pretty convenient, that.</p>
<p>Note that the format for the name element requires square brackets and a period.<code> </code></p>
<blockquote>
<pre><code><span class="kwrd">&lt;<strong>input </strong>type="text" name="products[0].Name" value="Beer" /&gt;</span>
</code></pre>
</blockquote>
<p>There is no way around this required formatting; it is hard-coded into the framework source code. (See DefaultModelBinder.cs.)</p>
<p>Unfortunately, these are special characters in jQuery selectors. As a result, some plug-ins can become unhappy when you use them in an input name. For example, the <a href="http://plugins.jquery.com/project/ClockPick">ClockPick plugin</a> has <a href="http://www.oakcitygraphics.com/jquery/clockpick/trunk/ClockPick.cfm">an option</a> which is useful when you want an image that the user can click on in order to pop up the clock picker instead of clicking on the input itself:</p>
<blockquote>
<pre><code><span class="kwrd">$(".clockpick").clockpick({
    valuefield : 'myfieldname'
});</span></code></pre>
</blockquote>
<p>If the name attribute of your input happens to be <code>myfieldname</code>, this works fine. If, on the other hand, it is <code><span class="kwrd">products[0].Name</span></code>, it doesn&#8217;t work at all.</p>
<p>The solution is to include an extra set of quotes around the name with the brackets and the dot:</p>
<blockquote>
<pre><code><span class="kwrd">$(".clockpick").clockpick({
    valuefield : "'</span></code><code><span class="kwrd">products[0].Name</span></code><code><span class="kwrd">'"
});
</span></code></pre>
</blockquote>
<p>With only one set of quotes, we just have a string containing <code>products[0].Name</code>. With two sets of quotes, the string contains the same thing, except surrounded by quotes. This causes jQuery to not treat the square brackets and the dots as special characters. As <a title="API/1.3/Selectors" href="http://docs.jquery.com/Selectors">the jQuery documentation notes</a>:</p>
<blockquote><p>Quotes are optional in most cases, but should be used to avoid conflicts when the value contains characters like "]".</p></blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38013&amp;akst_action=share-this" onclick="akst_share('38013', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F11%2F38013%2F', 'jQuery+and+ASP.NET+MVC+Model+Binding+to+a+List'); return false;" title="Post to del.icio.us, etc." id="akst_link_38013" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=jQuery%20and%20ASP.NET%20MVC%20Model%20Binding%20to%20a%20List&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F11%2F38013%2F" id="akst_email_38013" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Generics, Commas, and Semicolons</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/09/38000/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/09/38000/#comments</comments>
    <pubDate>Mon, 09 Feb 2009 18:19:10 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38000</guid>
    <description><![CDATA[In Delphi 2009, you declare a generic type with multiple type parameters by separating the type parameters with a semicolon. If the type parameters have a constraint, you separate the constraint using a colon. Like this:

type
  TFoo&#60;TypeParam1; TypeParam2: ISomething&#62; = class

This means that TypeParam2 must support ISomething. In C#, you would use where instead [...]]]></description>
      <content:encoded><![CDATA[<p>In Delphi 2009, you <em>declare </em>a generic type with multiple type parameters by separating the type parameters with a semicolon. If the type parameters have a constraint, you separate the constraint using a colon. Like this:</p>
<blockquote>
<pre><code><strong>type</strong>
  TFoo&lt;TypeParam1; TypeParam2: ISomething&gt; = <strong>class</strong></code></pre>
</blockquote>
<p>This means that TypeParam2 must support ISomething. In C#, you would use <a title="Constraints on Type Parameters (C# Programming Guide)" href="http://msdn.microsoft.com/en-us/library/d5x73970(VS.80).aspx"><code>where</code></a> instead of the colon syntax.</p>
<p>To use (as opposed to declare) a generic type, however, you separate the type parameters with commas, like this:</p>
<blockquote>
<pre><code>  Foo := TFoo&lt;integer, TBar&gt;.Create;
</code></pre>
</blockquote>
<p>Does that seem a little odd? It might to a C# programmer, I guess. But it should look very familiar to a Delphi programmer, because it exactly mirrors the syntax for procedure arguments:</p>
<blockquote>
<pre><code>  <em>// declare:</em>
  <strong>procedure </strong>Foo(ArgA: integer; ArgB: boolean);
  <em>// invoke:</em>
  Foo(A, B);
</code></pre>
</blockquote>
<p>Indeed, the only reason this is really worth mentioning at all is that if you forget and you use a comma instead of a semicolon when declaring a list of type parameters in a generic type declaration, the message you get from the compiler is not especially helpful.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38000&amp;akst_action=share-this" onclick="akst_share('38000', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F09%2F38000%2F', 'Generics%2C+Commas%2C+and+Semicolons'); return false;" title="Post to del.icio.us, etc." id="akst_link_38000" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Generics%2C%20Commas%2C%20and%20Semicolons&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F09%2F38000%2F" id="akst_email_38000" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>The Hidden Dangers of TRadioButton.TabStop</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/02/37987/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/02/37987/#comments</comments>
    <pubDate>Mon, 02 Feb 2009 20:12:28 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37987</guid>
    <description><![CDATA[TRadioButton has a TabStop property. It looks harmless enough. Why not set it? You&#8217;d like the user to be able to set radio button controls with the keyboard, right?
Trust me, just leave that little bastard alone.
To understand why, we should review the Windows standards for interacting with radio buttons using the keyboard. If you drop [...]]]></description>
      <content:encoded><![CDATA[<p>TRadioButton has a TabStop property. It looks harmless enough. Why not set it? You&#8217;d like the user to be able to set radio button controls with the keyboard, right?</p>
<p>Trust me, just leave that little bastard alone.</p>
<p>To understand why, we should review the Windows standards for interacting with radio buttons using the keyboard. If you drop several TRadioButtons onto a group box, then these buttons are treated as a group; although they aren&#8217;t quite the same thing as a TRadioGroup, they behave similarly. Namely, if you tab into the group box, then the checked radio button will receive input focus. If you press tab again, you will tab out of the group box. When the checked radio button has focus, pressing the arrow keys will check a different radio button in the group (and un-check all other radio buttons in the group box).</p>
<p>The VCL does not rely on Windows for this behavior; instead, it is implemented in the VCL source code, and you can trace through it.</p>
<p>The reason that this is on my mind is because of a curious bug report I received the other day. A tester reported that tabbing into a radio group on a certain form caused the selection to change (in other words, a different radio button was checked simply by tabbing into the group box). Based upon the explanation above, you can probably see where this is headed, but it took me a long time to figure out. The behavior was easy to reproduce, and I could even see a CN_COMMAND message of BN_CLICKED in the debugger, but it was near the top of the call stack, and I could not figure out where it was coming from.</p>
<p>It seems that if you tab to this particular radio button, and only this particular radio button, and only when you first enter the form, <em>Windows </em>will send BN_CLICKED. But why was I able to tab to a non-selected radio button at all? Shouldn&#8217;t focus go to the selected button?</p>
<p>No, not really. Again, Windows doesn&#8217;t choose which control is focused when you press tab; the Delphi VCL does. Glossing over a few details, it essentially looks for the next enabled control where TabStop is true. When you click a radio button, in addition to un-checking all of the other radio buttons in the group, the VCL sets their TabStop properties to False.</p>
<p><em>But only if they weren&#8217;t checked in the first place. </em>If a radio button is not already checked, then its TabStop property will not be set false when another radio button in the radio group has its Checked property set true.</p>
<p>So here is what actually happened:</p>
<ol>
<li>A few months ago, a well-meaning developer had done some tab order maintenance on the form in question. He changed the TabStop and TabIndex properties of a number of controls. The changes looked quite innocuous, and even passed code review.</li>
<li>Unfortunately, he had set TabStop true on a TRadioButton which was not Checked.</li>
<li>Some code in the form configured the radio group by setting the Checked property of a different radio button True. This caused the Checked and TabStop properties of the other radio buttons in the group to be set False, <em>but only if their Checked properties were not true to begin with.</em></li>
<li>Now the tester tabbed into the group box. The first radio button in the tab order was not checked, so a BN_CLICKED message is sent. The tester is surprised that the "wrong" radio button is focused, and, worse, it is checked, as well.</li>
</ol>
<p>The moral of the story? Just don&#8217;t touch the TRadioButton.TabStop property. The VCL is going to manipulate it in code. Leave it at its default value. If you want to change whether or not the user can tab into a group of radio buttons on a TGroupBox, then change the property of the container, instead.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37987&amp;akst_action=share-this" onclick="akst_share('37987', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F02%2F37987%2F', 'The+Hidden+Dangers+of+TRadioButton.TabStop'); return false;" title="Post to del.icio.us, etc." id="akst_link_37987" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=The%20Hidden%20Dangers%20of%20TRadioButton.TabStop&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F02%2F37987%2F" id="akst_email_37987" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Data Structures for Time Records</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/29/37964/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/29/37964/#comments</comments>
    <pubDate>Thu, 29 Jan 2009 14:17:10 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[InterBase]]></category>

		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37964</guid>
    <description><![CDATA[Over the years, I&#8217;ve had a number of occasions to need to store information about when somebody worked on a certain job. Sometimes people will want to store the date the work was done and the number of hours the employee worked, where as other people will need to store the start time and the [...]]]></description>
      <content:encoded><![CDATA[<p>Over the years, I&#8217;ve had a number of occasions to need to store information about when somebody worked on a certain job. Sometimes people will want to store the date the work was done and the number of hours the employee worked, where as other people will need to store the start time and the stop time (in other words, when the employee "punched in," and when the employee "punched out"). Often, the same customer will need to use both methods of recording time, depending upon the nature of the work recorded.</p>
<h2>A first try</h2>
<p>So here is a naïve attempt at creating metadata for this sort of data. I&#8217;m going to demonstrate this as a database table, but the issues involved are nearly identical when you create similar structures in code.</p>
<blockquote>
<pre><code><strong>CREATE TABLE </strong>TimeRecords (
  Id <strong>INTEGER NOT NULL PRIMARY KEY</strong>,
  PersonId <strong>INTEGER </strong>[...],
  WorkDate <strong>DATE</strong>,
  StartTime <strong>TIME</strong>,
  StopTime <strong>TIME</strong>,
  TotalHours <strong>NUMERIC</strong>(18, 4));</code></pre>
</blockquote>
<p>This might look OK at first glance, <em>but it turns out to be fairly badly broken</em>. Before I discuss why, I should clarify the data types involved. <strong></strong></p>
<h2>What isn&#8217;t broken</h2>
<p>One thing you might notice when looking at this metadata is that I&#8217;ve made most of the columns nullable. In my experience, it is very important to allow users to save work in progress, and to only do validations (such as requiring that the Person is filled in) when you actually try to do something important that the time record, such as submit it for payroll. For example, an employee could begin a time record when they "punch in" at the beginning of a shift, and finish the time record when they "punch out" at the end of a shift.</p>
<p><strong>DATE </strong>and <strong>TIME </strong>in this DDL refer to the SQL Standard data types which contain, respectively, a date and a time only. The SQL Standard data type for a date and time in a single column is <strong>TIMESTAMP</strong>. Not all databases (or programming languages/environments) support such types. In many cases, you will have to do with only <strong>TIMESTAMP</strong>, or its equivalent, such as TDateTime in Delphi.</p>
<p>Note that TotalHours is <strong>NUMERIC</strong>, not <strong>TIME</strong>. It is important not to confuse a time span with a time of day; they are different units. In .NET, there is a <a href="http://msdn.microsoft.com/en-us/library/system.timespan.aspx">TimeSpan type</a> which is appropriate for this.</p>
<h2>Problems with the naïve approach</h2>
<p>Presuming that the user has filled in all of the required information for a time record, what would we expect to see in a typical row?</p>
<p>If the user is recording only the date and the number of hours worked, it seems pretty obvious: both the WorkDate and the TotalHours fields will be non-NULL, and the StartTime and StopTime columns will be NULL.</p>
<p>What if the user needs to record the start and stop times? Well, the WorkDate, StartTime and StopTime fields almost be non-NULL. But what about TotalHours? We could fill that in, but wouldn&#8217;t it be redundant with the information in StartTime and StopTime? Or, worse, could we even be sure that all three fields are kept "in sync?" So we might be tempted to leave that NULL, but then, what if we want to do a SUM in SQL? By filling in TotalHours, we can compute an employee&#8217;s total work time, even if some of the records are filled in with start times and stop times, but others were filled in with only the total hours worked.</p>
<table border="1">
<thead>
<th>Id</th>
<th>PersonId</th>
<th>WorkDate</th>
<th>StartTime</th>
<th>StopTime</th>
<th>TotalHours</th>
</thead>
<tbody>
<tr>
<td>0</td>
<td>100</td>
<td>2009-01-29</td>
<td>1:00 PM</td>
<td>1:30 PM</td>
<td>0.5</td>
</tr>
<tr>
<td>1</td>
<td>101</td>
<td>2009-01-29</td>
<td><em>NULL</em></td>
<td><em>NULL</em></td>
<td>1.5</td>
</tr>
</tbody>
</table>
<p>To compute the total hours on a record that has start and stop times, we might be tempted to subtract the start time from the stop time. But that doesn&#8217;t work. An employee could work a shift from 8 PM to 2 AM, yielding a negative result for this calculation.</p>
<p>We could make a rule that we add a day to the stop time before subtracting if it is less than the start time, but this presumes that the employee&#8217;s shift was less than 24 hours. Greater than 24 hour shifts may be uncommon, but they do happen; I once worked a 31 hour shift, fresh out of college.</p>
<p>What this means is that <em>recording only the start and stop times without the start and stop <strong>dates </strong>does not give us sufficient information to compute the total hours worked in all cases, and makes it more difficult in many cases</em>.</p>
<h2>Some useful redundancy</h2>
<p>Here&#8217;s another way to store this data. This is what I generally do. But I&#8217;ll forgive you if you&#8217;re skeptical when you see it. I&#8217;ll discuss some alternatives later.</p>
<blockquote>
<pre><code><strong>CREATE TABLE </strong>TimeRecords (
  Id <strong>INTEGER NOT NULL PRIMARY KEY</strong>,
  PersonId <strong>INTEGER </strong>[...],
  WorkDate <strong>DATE</strong>,
  StartTime <strong>TIMESTAMP</strong>,
  StopTime </code><code><strong>TIMESTAMP</strong></code><code>,
  TotalHours <strong>NUMERIC</strong>(18, 4));</code></pre>
</blockquote>
<p>First, it is no longer a problem to compute TotalHours from the StopTime and StartTime, if they&#8217;re filled in. StopTime minus StartTime will always equal the correct total hours worked, when they are non-NULL. Also, it is no longer a problem to record a greater than 24 hour shift.</p>
<p>But isn&#8217;t there some redundancy here? WorkDate is always going to equal the date portion of StartTime, when StartTime is non-NULL. Somebody once suggested to me that it would be possible to just use the date portion of the StartTime <strong>TIMESTAMP </strong>for a "TotalHours-only"time record (and drop the WorkDate column altogether). The problem with this idea is that a <strong>TIMESTAMP </strong>always contains time information, whether or not you bother to fill in. If you assign only a date, then the time portion is presumed to be midnight. So there is no way to distinguish between a record where the user intended to fill in only total hours and one where the user intentionally filled in midnight as the StartTime but forgot to fill in the StopTime. That will be a problem when you validate the record prior to submitting it for payroll.</p>
<h2>Another way</h2>
<p>I found that the approach above works well for me, but those who find the duplication of one date completely untenable might be tempted to do something along the lines of this metadata:</p>
<blockquote>
<pre><code><strong>CREATE TABLE </strong>TimeRecords (
  Id <strong>INTEGER NOT NULL PRIMARY KEY</strong>,
  PersonId <strong>INTEGER </strong>[...],
  WorkDate <strong>DATE</strong>,
  StartTime <strong>TIME</strong>,
  StopTime </code><code><strong>TIMESTAMP</strong></code><code>,
  TotalHours <strong>NUMERIC</strong>(18, 4));</code></pre>
</blockquote>
<p>There&#8217;s no redundancy in this version. You can store both time records with start times and stop times or time records with just elapsed times, and it&#8217;s easy to distinguish the two. Unfortunately, certain queries become more difficult. With the version which uses <strong>TIMESTAMP </strong>for the StartTime column, I can write a query like this to determine who was in the building at a particular point in time:</p>
<blockquote>
<pre><code><strong>SELECT</strong>
  PersonId
<strong>FROM</strong>
  TimeRecords
<strong>WHERE</strong>
  :SomeParameter <strong>BETWEEN </strong>StartTime and StopTime</code></pre>
</blockquote>
<p>Records without start and stop times will be ignored by this query, since they do not contain enough information to answer the question. With a <strong>TIME </strong>instead of a <strong>TIMESTAMP </strong>data type for the StartTime column, I would have to use an expression in the where clause to write this query:</p>
<blockquote>
<pre><code><strong>SELECT</strong>
  PersonId
<strong>FROM</strong>
  TimeRecords
<strong>WHERE</strong>
  :SomeParameter <strong>BETWEEN </strong>(</code><code>WorkDate + </code><code>StartTime) and StopTime</code></pre>
</blockquote>
<p>That might well mean that my query can no longer be indexed.</p>
<h2>Conclusion</h2>
<p>Although my preferred schema has a small bit of redundancy, I find it significantly more usable.It is considerably less work to handle copying the date between the WorkDate and StartTime fields, and computing the TotalHours from the StartTime and StopTime, than it is to not have the date in either column.And not having dates in the StartTime and StopTime columns at all is just unusable.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37964&amp;akst_action=share-this" onclick="akst_share('37964', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F29%2F37964%2F', 'Data+Structures+for+Time+Records'); return false;" title="Post to del.icio.us, etc." id="akst_link_37964" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Data%20Structures%20for%20Time%20Records&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F29%2F37964%2F" id="akst_email_37964" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>ASP.NET MVC TempData Is Really RedirectData</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/23/37947/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/23/37947/#comments</comments>
    <pubDate>Fri, 23 Jan 2009 16:30:38 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37947</guid>
    <description><![CDATA[Many people seem to be confused about the TempData feature in ASP.NET MVC. TempData behaves like the ViewData dictionary, except that it persists until the next request from the same browser.
Because of this, TempData should only be used when you know exactly what the next request is going to be. If you set TempData and [...]]]></description>
      <content:encoded><![CDATA[<p><a title="Questions containing tempdata" href="http://stackoverflow.com/search?q=tempdata">Many people seem to be confused about the TempData feature in ASP.NET MVC</a>. TempData behaves like the ViewData dictionary, <em>except </em>that it persists until the next request from the same browser.</p>
<p>Because of this, TempData should only be used when you know exactly what the next request is going to be. If you set TempData and your action then returns a ViewResult, then the next request, whatever it happens to be (an AJAX request, another page the user opened in a different tab, etc.), is going to see the TempData value you set, and no other request will see it. I&#8217;m guessing that this is never the behavior you want.</p>
<p><strong>Realistically, this means that you should only use TempData immediately before you redirect</strong> (in other words, immediately before you return a RedirectResult), because this is the only time when you are sure what the next request from that browser is going to be. I actually think that RedirectData would be a better name for this property. Someone, perhaps Steve McConnell, once noted that you should never include "temp" in a variable name, since variables are, by definition, temporary. "Temp data," to me, is synonymous with "variable." The (functionally similar) "flash" feature in Rails is even more badly named.</p>
<p>If your controller action returns a ViewResult, and you are tempted to put data into TempData, <strong>don&#8217;t</strong>. Use ViewData, instead, in this case.</p>
<p>This may lead to a situation where you might need to have a view look into both ViewData and TempData for a key. One example would be if you have an area in your Site.Master to display error messages on the page. It is likely that one controller action will need to send a message to the view via ViewData (because that action returns a ViewResult), while another action will need to send a message to the view via TempData (because that action returns a RedirectResult, as part of a <a href="http://blog.eworldui.net/post/2008/05/ASPNET-MVC---Using-Post2c-Redirect2c-Get-Pattern.aspx">POST/redirect/GET</a> cycle). In this case, you can use code like this in the Site.Master:</p>
<blockquote>
<pre><code>&lt;%= ViewData["Message"] ?? TempData["Message"] %&gt;</code></pre>
</blockquote>
<p>Under the hood, TempData works by using server-side Session state, so a distributed session cache like Velocity can be used if your application runs on a server farm. Since the lifetime of data put into TempData is limited to the next request, it is fairly easy to use without worrying about growing the session very large, especially since the most common use for TempData is to store a short error string. But the usual rules on what you can put into a Session apply. If you set the <a href="http://msdn.microsoft.com/en-us/library/ms178586.aspx">Session state mode</a> to out of process, then the data you put in it must be serializable.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37947&amp;akst_action=share-this" onclick="akst_share('37947', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F23%2F37947%2F', 'ASP.NET+MVC+TempData+Is+Really+RedirectData'); return false;" title="Post to del.icio.us, etc." id="akst_link_37947" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=ASP.NET%20MVC%20TempData%20Is%20Really%20RedirectData&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F23%2F37947%2F" id="akst_email_37947" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>SQLDA missing or incorrect version, or incorrect number/type of variables</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/22/37934/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/22/37934/#comments</comments>
    <pubDate>Thu, 22 Jan 2009 05:23:10 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37934</guid>
    <description><![CDATA[The error in the title comes from InterBase. Actually, the full error is:
[DataDirect][ODBC InterBase driver][InterBase]Dynamic SQL Error, SQL error code = -804, SQLDA missing or incorrect version, or incorrect number/type of variables.
I&#8217;ve seen this error before when the wrong InterBase client (gds32.dll) version was loaded by the application, or when the wrong number of variables [...]]]></description>
      <content:encoded><![CDATA[<p>The error in the title comes from InterBase. Actually, the full error is:</p>
<p><code>[DataDirect][ODBC InterBase driver][InterBase]Dynamic SQL Error, SQL error code = -804, SQLDA missing or incorrect version, or incorrect number/type of variables.</code></p>
<p>I&#8217;ve seen this error before when the wrong InterBase client (gds32.dll) version was loaded by the application, or when the wrong number of variables is passed to a stored procedure. But yesterday I found a new way to get the error. It took me quite a while to debug this, so I&#8217;m putting the information out in case other people encounter it.</p>
<p>It seems that certain versions of InterBase server don&#8217;t respond well to passing a parameter of type ShortInt to a parameterized query that calls a stored procedure with that param as an integer argument. In particular, I found that doing this will fail on InterBase server version 7.5.1.162, but works fine on 7.5.1.80. Changing the type of the parameter to integer fixes the problem. I was doing this via ODBC; I don&#8217;t know if it makes a difference or not.</p>
<p>(Why was I using a parameter of type ShortInt in the first place? I wasn&#8217;t, exactly. But the value that I assigned to the Param.Value, a variant, was the constant 0. Delphi will treat the constant value 0 as a ShortInt.)</p>
<p>This is a good example of why unit testing can never be sufficient to completely test an application. Since this is a server error, a unit test can&#8217;t find it. Since it only happens on certain versions of the server, even basic integration testing might miss it. The only way to have a hope of finding such an error is to do automated testing on multiple environments. In this case, the error prevented a Crystal report from executing at all. We have a testing tool built into our applications that executes all of the reports and saves timing information to a log file. We run this with every QA releasewe do, and compare the timing information with previous releases. Sometimes we catch reports which won&#8217;t executed all, as with this case. In other cases, we find that the report has become much faster or much slower, due to a database metadata change.</p>
<p>The report profiler is part of a "debug console" which is built into the applications and provides testing and diagnostic information at runtime. I said before that <a href="http://blogs.teamb.com/craigstuntz/2009/01/12/37919/">testing is a valid use case</a>, and this is one example. Another, report-related example is that whenever our applications modified the SQL in a report (to customize the result set for an end user), we have a way to display the final SQL before it is executed by the report. The reason is that a particular customer might make a particular selection that either performs badly or does not execute at all. (End users don&#8217;t directly edit SQL; instead they choose the data they want to see graphically, and we build SQL from their choices.) In order to reproduce their problem in a debug environment we need to know precisely what kind of choices they have made, and how the software handle those choices. Displaying the SQL before it is executed answer six questions.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37934&amp;akst_action=share-this" onclick="akst_share('37934', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F22%2F37934%2F', 'SQLDA+missing+or+incorrect+version%2C+or+incorrect+number%2Ftype+of+variables'); return false;" title="Post to del.icio.us, etc." id="akst_link_37934" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=SQLDA%20missing%20or%20incorrect%20version%2C%20or%20incorrect%20number%2Ftype%20of%20variables&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F22%2F37934%2F" id="akst_email_37934" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Customizing jQuery Validation</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/15/37923/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/15/37923/#comments</comments>
    <pubDate>Thu, 15 Jan 2009 14:28:52 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37923</guid>
    <description><![CDATA[While doing some bug fixing and cleanup in a web application, I had the chance to go a little deeper into the jQuery user input validation framework. There are many tutorials available about implementing custom validations. But what I wanted to do was to extend the default validations with my own code, while preserving the [...]]]></description>
      <content:encoded><![CDATA[<p>While doing some bug fixing and cleanup in a web application, I had the chance to go a little deeper into the <a href="http://docs.jquery.com/Plugins/Validation">jQuery user input validation framework</a>. There are many tutorials available about <a href="http://randomactsofcoding.blogspot.com/2008/10/starting-with-jquery-how-to-write.html">implementing custom validations</a>. But what I wanted to do was to extend the default validations with my own code, while preserving the existing functionality, and to do it site-wide.</p>
<p>So let&#8217;s pretend that I&#8217;d like to extend the default "required" validation in such a way that you are not allowed to enter "foo" in any form field with the "required" class. First, I need to write a function to test this:</p>
<blockquote>
<pre><code><strong>function </strong>notFoo(value) {
    <strong>return </strong>value !== "foo";
}</code></pre>
</blockquote>
<p>Putting the custom code in a separate function makes it very easy to unit test.</p>
<p>Now, I&#8217;d like to replace <a href="http://docs.jquery.com/Plugins/Validation/Methods/required">the default "required" validation</a> with one which first calls my custom method, and then does the regular, default validation, if it passes the custom validation. I can call jQuery.validator.<a href="http://docs.jquery.com/Plugins/Validation/Validator/addMethod#namemethodmessage">addMethod</a>, and pass "required" as the name argument. Even though this is a standard validator, supplied by the jQuery validation framework, I&#8217;m allowed to replace it with my own custom method:</p>
<blockquote>
<pre><code>jQuery.validator.addMethod("required", <strong>function</strong>(value, element, param) {
        <strong>return </strong>notFoo(value);
        },
    jQuery.validator.messages.required // use default message
    );</code></pre>
</blockquote>
<p>So far, I&#8217;ve only replaced the standard "required" validator. This is useful by itself; there may be times when you want to write code to completely replace the standard validator. If you put this code in your site master template, you will have accomplished that goal.</p>
<p>But my goal was to extend the default validation, not replace it. So I need to store a reference to the default "required" validator, and then call it, after calling my custom code:</p>
<blockquote>
<pre><code>jQuery.validator.methods.oldRequired = jQuery.validator.methods.required;

jQuery.validator.addMethod("required", <strong>function</strong>(value, element, param) {
        <strong>if </strong>(!notFoo(value)) {
            return <strong>false</strong>;
        }
        <strong>return </strong>jQuery.validator.methods.oldRequired.call(<strong>this</strong>, value, element, param);
    },
    jQuery.validator.messages.required // use default message
    );</code></pre>
</blockquote>
<p>I can&#8217;t call the oldRequired method directly, because it uses "<a href="http://www.quirksmode.org/js/this.html">this</a>", which will point at the wrong thing if I just invoke it without <a href="http://blog.metawrap.com/blog/TheVeryUsefulJavaScriptCallAndApplyFunctionsForOverridingThisForAGivenFunction.aspx">call</a>.</p>
<p>Before I wrap up this post, I would like to extend thanks to the folks at Stack Overflow who <a href="http://stackoverflow.com/questions/447658/can-i-copy-clone-a-function-in-javascript">helped me fix a some issues in my first attempt at doing this</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37923&amp;akst_action=share-this" onclick="akst_share('37923', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F15%2F37923%2F', 'Customizing+jQuery+Validation'); return false;" title="Post to del.icio.us, etc." id="akst_link_37923" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Customizing%20jQuery%20Validation&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F15%2F37923%2F" id="akst_email_37923" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Testing Is a Legitimate Use Case</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/12/37919/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/12/37919/#comments</comments>
    <pubDate>Mon, 12 Jan 2009 20:46:30 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37919</guid>
    <description><![CDATA[How should you unit test private methods? It depends. Some say you shouldn&#8217;t do it at all. Others say you should test everything. Who is right?
The problem that I have with a statement like, "Don&#8217;t test private methods," is that it is a circular argument. That a method is private implies that you don&#8217;t want [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://stackoverflow.com/questions/422379/dunit-testing-in-delphi-how-to-test-private-methods">How should you unit test private methods</a>? It depends. <a title="Don’t test your privates!" href="http://delphixtreme.com/wordpress/?p=19">Some say you shouldn&#8217;t do it at all</a>. Others say you should test everything. Who is right?</p>
<p>The problem that I have with a statement like, "Don&#8217;t test private methods," is that it is a circular argument. That a method is private implies that you don&#8217;t want to test it (or haven&#8217;t thought about testing it). So it&#8217;s like saying, "Don&#8217;t test stuff that you don&#8217;t want to test." That&#8217;s not very helpful.</p>
<p>Similarly, when people say "test everything," I think they&#8217;re being a little vague. I can go along with "(unit) test everything that can practically be tested," but I&#8217;m not going to pretend that unit testing will take the place of integration testing, that it is possible to test every condition in a complex software system, etc.</p>
<p>Last year, I asked the question, "<a href="http://blogs.teamb.com/craigstuntz/2007/10/26/37763/">Why hide information?</a>" Without needing a definitive answer for that question, let&#8217;s agree that, given a certain use case and the code which addresses it, there is some portion which must be public in order to be useful. Internally, however, there is probably some additional code which does not need to be public in order to solve the problem at hand. One popular school of thought says that code which is not needed in the public interface should never be public. (And similarly for protected, etc.)</p>
<p>At this point, I would like to point out that testing code is a legitimate use case. I commonly refactor functioning code to make it more testable. This is code which appears to work just fine, and requires no changes in functionality to the end user. Despite the aphorism, "if it ain&#8217;t broke, don&#8217;t fix it," I&#8217;m willing to make these changes, because I think that the ability to run more tests is a good feature to add to the software.</p>
<p>Some would argue that testing the public interface of a piece of code is sufficient, because any internal bugs which are not reflected in the public behavior are not relevant to how the code is actually used. This is true insofar as it goes, but it turns out that exhaustively testing the public behavior of a complex collection of code is <em>extremely </em>difficult, especially if that code has state.</p>
<p>Let&#8217;s imagine a function called Foo which accepts an integer argument and returns some value, but doesn&#8217;t use any kind of state. There are, therefore, 2^32 possible test cases for this function. Imagine another function, Bar, with the same characteristics. Again, 2^32 possible test cases. That&#8217;s a lot, and perhaps we would not want to test every possible case, but even if we did, it&#8217;s nothing that a computer can&#8217;t handle. Now imagine a type with a public function called Baz which uses both Foo and Bar internally, passing some internal state of the type. Because Foo and Bar are not needed for the end user&#8217;s use case, we decide to make them private. The list of possible test cases for the type now probably exceeds what can be performed with a fast computer in your lifetime. Typically, we try to work around such excessively large numbers of test cases by <a title="Pex - Automated White box Testing for .NET" href="http://research.microsoft.com/en-us/projects/Pex/">probing boundary conditions</a>. But if private state is involved, this turns out to be very difficult to do. Given that making a field private implies that the implementation may change, probing the behavior of Baz by trying to make it hit the extremes of Foo and Bar is both difficult and likely to be a maintenance nightmare in the future.</p>
<p>In such a situation, I would argue that the need to test the behavior of Baz is by itself reason enough to make Foo and Bar public. If we are positive that both Foo and Bar work correctly (e.g., because we have exhausted the unit tests), then testing the behavior of Baz is either easy or so trivial as to be unnecessary. Because we don&#8217;t want to pollute the namespace of the type containing Baz, and because neither Foo nor Bar use any internal state, it would probably make sense to make them public members of a separate type, probably a static type. The point is that even if they are never used anywhere else in the system, it is worth making them publicly visible for the sole purpose of improving the coverage and efficiency of our testing.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37919&amp;akst_action=share-this" onclick="akst_share('37919', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F12%2F37919%2F', 'Testing+Is+a+Legitimate+Use+Case'); return false;" title="Post to del.icio.us, etc." id="akst_link_37919" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Testing%20Is%20a%20Legitimate%20Use%20Case&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F12%2F37919%2F" id="akst_email_37919" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>How to Unit Test a Data Module</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/09/37912/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/09/37912/#comments</comments>
    <pubDate>Fri, 09 Jan 2009 17:04:02 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37912</guid>
    <description><![CDATA[Data modules are unit tested in exactly the same way that you would unit test any other piece of code. That is, by refactoring the code to be tested in such a way as to separate it from code not relevant to the test. But since people occasionally seem to find this confusing, perhaps a practical example is in order.]]></description>
      <content:encoded><![CDATA[<p>Data modules are unit tested in exactly the same way that you would unit test any other piece of code. That is, by refactoring the code to be tested in such a way as to separate it from code not relevant to the test. But <a title="DUnit Testing in a Midas/DataSnap project" href="http://stackoverflow.com/questions/247978/dunit-testing-in-a-midas-datasnap-project">since people occasionally seem to find this confusing</a>, perhaps a practical example is in order.</p>
<p>Imagine that you have been given the task of fixing a bug in the following code. Before you fix the bug, you would like to write a unit test which shows the bug, in order to prevent regressions after you fix it.</p>
<blockquote>
<pre><code><strong>procedure </strong>TMyDM.qryFooCalcFields(DataSet: TDataSet);
<strong>var</strong>
  Minimum, PieceRate: Double;
<strong>begin</strong>
  Minimum := qryFooHOURS.Value / qryFooMINIMUM_WAGE.Value; <em>// </em></code><em><code>oops; should be *</code></em><code>
  PieceRate := qryFooPIECE_RATE.Value * qryFooPIECES.Value;
  qryFooEarnings.Value := Max(Minimum, PieceRate);
<strong>end</strong>;
</code></pre>
</blockquote>
<p>Now, tests which access a database are, generally speaking, integration tests rather than unit tests. But the code you&#8217;ve been asked to fix seems to be pretty wound up in database access. It doesn&#8217;t have to be, though. Let&#8217;s refactor:</p>
<blockquote>
<pre><code><strong>function </strong>TMyDM.CalcEarnings(AHours, AMinimumWage, APieceRate, APieces: Double): double;
<strong>var</strong>
  Minimum, PieceRate: Double;
<strong>begin</strong>
  Minimum := AHours / AMinimumWage; <em>// oops; should be *</em>
  PieceRate := APieceRate * APieces;
  Result := Max(Minimum, PieceRate);
<strong>end</strong>;

<strong>procedure </strong>TMyDM.qryFooCalcFields(DataSet: TDataSet);
<strong></strong><strong>begin</strong>
  qryFooEarnings.Value := CalcEarnings(qryFooHOURS.Value,
    qryFooMINIMUM_WAGE.Value, qryFooPIECE_RATE.Value, qryFooPIECES.Value);
<strong>end</strong>;</code></pre>
</blockquote>
<p>Resist any temptation to actually fix the bug at the moment; we went to write a unit test which fails before making it pass by fixing the bug. Note that you can make CalcEarnings static, meaning you won&#8217;t even need an instance of the data module in order to unit test the function:</p>
<blockquote>
<pre><code><strong>procedure </strong>TestMyDM.CalcEarnings;
<strong>var</strong>
  Actual, Delta, Expected, Hours, Minimum, PieceRate, Pieces: Double;
<strong>begin</strong>
  Hours := 1;
  Minimum := 7;
  PieceRate := 1;
  Pieces := 1;
  Expected := 7;

  Actual := TMyDM.CalcEarnings(Hours, MinimumWage, PieceRate, Pieces);

  Delta := 0.0001;
  CheckEquals(Expected, Actual, Delta);
<strong>end</strong>;
</code></pre>
</blockquote>
<p>There are aspects of this code which will be hard to unit test. I could, for example, pass the wrong field value into the refactored function. I can fix that by abstracting the data access layer, but it&#8217;s not a complete fix, since I might have the wrong data in the database. The fact is that unit testing can only catch so much, and integration testing will always be necessary, as well. The important point is that I have isolated the bug which I was asked to fix, and future regressions in <em>that code</em> will now be caught.</p>
<p>I wonder if some Delphi users are confused by the term "unit test." The word "unit" means something very different in Delphi than it does in the term "unit test." In "unit testing," the word "unit" refers to a single piece of functionality. In Delphi, a unit (reserved word) is a source code file. When you write unit tests, you do not have to test an entire unit at a time. Unit tests are for specific cases of using a specific function.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37912&amp;akst_action=share-this" onclick="akst_share('37912', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F09%2F37912%2F', 'How+to+Unit+Test+a+Data+Module'); return false;" title="Post to del.icio.us, etc." id="akst_link_37912" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=How%20to%20Unit%20Test%20a%20Data%20Module&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F09%2F37912%2F" id="akst_email_37912" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Functional Programming in Delphi 2009 Video</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/08/37908/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/08/37908/#comments</comments>
    <pubDate>Thu, 08 Jan 2009 07:18:59 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[CodeRage]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37908</guid>
    <description><![CDATA[The video of my CodeRage III presentation on Functional Programming in Delphi 2009 is available for download. ]]></description>
      <content:encoded><![CDATA[<p>The <a title="Functional Programming in Delphi 2009" href="http://cc.codegear.com/Item/26395">video</a> of my CodeRage III presentation on Functional Programming in Delphi 2009 is available for download. You&#8217;ll want to grab <a title="Functional Programming in Delphi 2009 CodeRage Source Code Only" href="http://cc.codegear.com/Item/26324">the source code</a> first, so that you can follow along during the presentation.</p>
<blockquote><p>Delphi 2009 includes several new features well suited to a functional style of programming. We&#8217;ll explore the use of generics, anonymous methods, and new RTL types while introducing concepts from functional programming.</p></blockquote>
<p>By the way, comments on this blog should be fixed now; the spam filter had been overly aggressive.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37908&amp;akst_action=share-this" onclick="akst_share('37908', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F08%2F37908%2F', 'Functional+Programming+in+Delphi+2009+Video'); return false;" title="Post to del.icio.us, etc." id="akst_link_37908" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Functional%20Programming%20in%20Delphi%202009%20Video&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F08%2F37908%2F" id="akst_email_37908" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Architectural Hedges</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/06/37897/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/06/37897/#comments</comments>
    <pubDate>Tue, 06 Jan 2009 09:00:07 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37897</guid>
    <description><![CDATA[In gardening, a hedge is a line of shrubs which forms a barrier between two areas. In finance, a hedge is a risk management strategy based on making investments or business plans in such a way that a loss in one area of the portfolio will be balanced by a gain in another area of [...]]]></description>
      <content:encoded><![CDATA[<p>In gardening, a <strong>hedge</strong> is a line of shrubs which forms a barrier between two areas. In finance, a hedge is a risk management strategy based on making investments or business plans in such a way that a loss in one area of the portfolio will be balanced by a gain in another area of the portfolio. For example, Southwest Airlines correctly predicted, a few years ago, that the price of jet fuel was going to rise dramatically. Normally, this would hurt their business. <a title="Hedging Their Costs" href="http://www.time.com/time/magazine/article/0,9171,1074147,00.html">However, they used this prediction to lock in long-term contracts </a>at a rate which may have seemed high when they were signed, but which quickly turned into a bargain when other airlines had to pay twice as much for their fuel. Hence, the rising cost of jet fuel became a business advantage for Southwest, rather than a liability.</p>
<p>Last night, <a href="http://www.colarc.org/2008/12/next-meeting-monday-january-5th.html">the Columbus Architecture Group met</a> to discuss the effects of the economic recession on software vendors, IT departments, and other projects. One area of discussion which I found particularly interesting was the notion of how to build hedges into enterprise or software architecture. In other words, can we examine areas of business risk, and design teams and systems in such a way that they, at least partially, offset this risk?</p>
<p>I&#8217;m writing this post more as a question than as a statement of advice, but I will give some examples here in order to clarify what I am asking.</p>
<ul>
<li>Last year, my company recognized a need to be in a certain area of the market which we had not previously served. But exactly how to enter this area of the market would depend upon sales needs which were not yet clear. There were two routes we could take, both of which had significant advantages. Taking Fred Brooks&#8217;s dictum of "<a href="http://www.cs.usfca.edu/~parrt/course/601/lectures/man.month.html">Plan to throw one away; you will anyway</a>" to heart, we started working on both projects, with full knowledge that we would be unlikely to complete both. As anticipated, one of the two projects was eventually left behind. But the other one was better for having undertaken it, and we had mitigated the risk of choosing incorrectly.</li>
<li>Another participant noted that he had a programmer working on a project which would eventually require to write code to accomplish a certain task. He noticed that another team was working on a similar functional area, although they were not close to completing this work. He asked the first programmer to put off work in this area for another month, which she could easily do, due to the amount of work required in other parts of the project. At the end of the month, they would assess whether the second team had completed enough work to make integration of that team&#8217;s code a better idea than writing new code. As it happened, the second team&#8217;s project was not far enough along to help the first programmer. However, the cost of rearranging her schedule had been very low, so even though it didn&#8217;t provide any actual benefits in the long run, it was still, in hindsight, worth doing.</li>
<li>Economic conditions which are destructive to one area of a market can be beneficial to another. For example, as companies consolidate due to shrinking markets, there may be an increasing need for software systems integration.</li>
</ul>
<p><a href="http://blogs.teamb.com/craigstuntz/2009/01/06/37897/#respond">Now I&#8217;d like to turn the question over to you</a>: How should architects and developers build hedges into our products and process?</p>
<p><a href="http://delphixtreme.com/wordpress/?p=165">Here&#8217;s one response from Jody Dawkins.</a> If you&#8217;ve tried to comment in the past couple of days, please forgive the overly aggressive spam filter on this server; it should be fixed now.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37897&amp;akst_action=share-this" onclick="akst_share('37897', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F06%2F37897%2F', 'Architectural+Hedges'); return false;" title="Post to del.icio.us, etc." id="akst_link_37897" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Architectural%20Hedges&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F06%2F37897%2F" id="akst_email_37897" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>The Strange Story of Erlang&#8217;s Success</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/12/29/37887/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/12/29/37887/#comments</comments>
    <pubDate>Mon, 29 Dec 2008 21:26:22 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Erlang]]></category>

		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37887</guid>
    <description><![CDATA[Back in May, I wrote a post on "Let It Crash" programming in Erlang, based on Joe Armstrong&#8217;s paper on the history of the language, and intended to return to other interesting discussions from the paper in a future post. Well, better late than never.
Today I&#8217;d like to discuss the "success" of Erlang, how it [...]]]></description>
      <content:encoded><![CDATA[<p>Back in May, I wrote a post on <a href="http://blogs.teamb.com/craigstuntz/2008/05/19/37819/">"Let It Crash" programming</a> in Erlang, based on Joe Armstrong&#8217;s paper on the history of the language, and intended to return to other interesting discussions from the paper in a future post. Well, better late than never.</p>
<p>Today I&#8217;d like to discuss the "success" of Erlang, how it got there, and what it means.</p>
<p>Is Erlang successful at all? It&#8217;s not particularly widely used, there are few books on the subject, and its influence on other languages is debatable. It doesn&#8217;t do very well in <a href="http://www.langpop.com/">search-engine-based "metrics,"</a> either. On the other hand, one could say that it is "successful" in certain, domain-specific ways. It&#8217;s the first example anyone uses of the lightweight-processes-with-message-passing approach to concurrency. It&#8217;s proving itself in real-world applications, such as <a href="http://www.satine.org/archives/2007/12/13/amazon-simpledb/">Amazon&#8217;s SimpleDB</a> and Ericsson&#8217;s phone switches. (If your reaction to that last sentence is, "Of course Ericsson uses it in their phone switches; they invented it," then read the paper, or at least the rest of this post.) The Ericsson AXD301 <a href="http://www.pragprog.com/articles/erlang">claims nine nines reliability (99.9999999%)</a>. I think that would be a success even if nobody else ever used it.</p>
<p>So the question I&#8217;m going to address here is how did Erlang went from a research project to a "successful" tool (in certain domains) with essentially no backing whatsoever, least of all from Ericsson.</p>
<p>Joe Armstrong credits two primary factors for Erlang&#8217;s success, <em>neither of which have anything whatsoever to do with Erlang as a language:</em></p>
<ul>
<li>A hardware and software project which Ericsson was developing using C++ collapsed.</li>
<li>A division at Ericsson banned using Erlang altogether, effectively driving it out of the company.</li>
</ul>
<p>Although Erlang had proven itself moderately successful in the lab, commercial use of the tool required documentation, libraries, and testing, which, in turn, required more effort to produce than the R&amp;D team could provide. Here&#8217;s how Armstrong explains it:</p>
<blockquote><p>Without the collapse of AXE-N, Erlang would have still remained a Lab experiment and the effort to turn it into a commercial quality product would not have happened. The difference is the many thousands of hours of work that must be done to produce high-quality documentation and to produce and test extensive libraries. AXE-N was a project aimed at developing a new generation of switching products ultimately to replace the AXE10 system. The AXE-N project had developed a new hardware platform and system software that was developed in C++.</p>
<p>Following a series of crisis meetings the project was reorganised and re-started. This time the programming language would be Erlang and hardware from the AXE-N project was salvaged to start the production of a new ATM16 switch, to be called the AXD. This new project was to be the largest-ever Erlang project so far, with over 60 Erlang programmers. At the start of the AXD project, the entire Erlang system was the responsibility of half a dozen people in the Lab. This number was viewed as inadequate to support the needs of a large development project and so plans were immediately enacted to build a product unit, called OTP, to officially support the Erlang system.</p></blockquote>
<p>This is a really important point, which people have been missing at least since the era when Fred Brooks was writing <em><a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FMythical-Man-Month-Software-Engineering-Anniversary%2Fdp%2F0201835959%2F&amp;tag=learningtowhi-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325">The Mythical Man Month</a><img style="border:none !important;margin:0px !important" src="http://www.assoc-amazon.com/e/ir?t=learningtowhi-20&amp;l=ur2&amp;o=1" border="0" alt="" width="1" height="1" /></em>. Brooks noted that most programmers have had a moment when they write something really cool, and think, "Wow, if I can produce this thing in one week of hard work, why does it take [insert large software company here] two years to produce the functionality I need?" <a href="http://www.fabtime.com/man-month.shtml">Brooks explained that turning the "really cool" functionality into, say, a piece of an operating system takes many times the effort of writing the functionality in the first place.</a> Adding the library support needed to make the "cool" functionality generally useful (i.e., useful to someone other than the person who wrote it) at least doubles the effort. Sufficiently documenting both the original functionality in the library support you just added doubles it again. Anyone tempted to say, "Just ship the functionality and document later," should consider the reception that greeted the Delphi 2005 and 2006 help systems.</p>
<p>Perhaps you&#8217;ve heard about a really cool open source project, and then discovered, when you try to use it, that it was buggy, didn&#8217;t have the features required for your application, and had no documentation whatsoever. That&#8217;s exactly the same problem at work.</p>
<p>How could an Ericsson division banning Erlang lead to its success? That&#8217;s a surprising claim, and the answer is interesting. For some time, the R&amp;D team which developed Erlang had been interested in marketing it to other companies. But they were limited, at first, by the secrecy typical of the era, and later by increasing competition from a more open marketplace:</p>
<blockquote><p>By 1998, about 40 evaluation systems had been distributed to external users and by now the idea of releasing Erlang subject to an open source license was formed. Recall that at the start of the Erlang era, in 1986, “open source” was unheard of, so in 1986 everything we did was secret. By the end of the era, a significant proportion of the software industry was freely distributing what they would have tried to sell ten years earlier—as was the case with Erlang.</p></blockquote>
<p>In the end, the ban led to the ability to promote Erlang outside the constraints of Ericsson&#8217;s telephone business:</p>
<blockquote><p>Shortly after the open source release, the majority of the original Erlang development team resigned from Ericsson and started a new company called Bluetail AB with Jane [Walerud] as the chief executive. In retrospect the Erlang ban had the opposite effect and stimulated the long-term growth of Erlang. The ban led indirectly to Open Source Erlang and to the formation of Bluetail. Bluetail led in its turn to the introduction of Erlang into Nortel Networks and to the formation of a small number of Erlang companies in the Stockholm region.</p></blockquote>
<p>That Armstrong credits these two factors for Erlang&#8217;s success is interesting, but can we tie them together into a coherent method for promoting a programming language? Perhaps. Armstrong doesn&#8217;t exactly spell it out, but elsewhere in the paper he makes a point which, I think, is the missing link between them:</p>
<blockquote><p><strong>People are not convinced by theory, only by practice</strong></p></blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37887&amp;akst_action=share-this" onclick="akst_share('37887', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F29%2F37887%2F', 'The+Strange+Story+of+Erlang%26%238217%3Bs+Success'); return false;" title="Post to del.icio.us, etc." id="akst_link_37887" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=The%20Strange%20Story%20of%20Erlang%26%238217%3Bs%20Success&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F29%2F37887%2F" id="akst_email_37887" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Lightweight Frameworks, Again</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/12/26/37874/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/12/26/37874/#comments</comments>
    <pubDate>Fri, 26 Dec 2008 21:54:01 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37874</guid>
    <description><![CDATA[A couple weeks ago, I wrote a post noting that I liked the lightweight nature of the Ruby web framework Merb. Today comes the news that Merb and Rails will be merging in Rails 3. People who see Merb as the "anti-Rails" seem to find this surprising. But people who see Merb as "Rails done [...]]]></description>
      <content:encoded><![CDATA[<p>A couple weeks ago, I wrote a post <a title="Lightweight Frameworks" href="http://blogs.teamb.com/craigstuntz/2008/12/12/37872/">noting that I liked the lightweight nature of the Ruby web framework Merb</a>. Today comes the news that <a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/">Merb and Rails will be merging in Rails 3</a>. People who see Merb as the "anti-Rails" seem to find this surprising. But people who see Merb as "Rails done right/better" are enthusiastic about it. It&#8217;s hard to blame the developers for being more interested in pleasing the latter group. When you read through the list of <a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/">"What Does That Mean, Exactly?" at this link</a>, I don&#8217;t see a downside to this. Rails is going to pick up many — or maybe all — of Merb&#8217;s best design attributes, and folks who want to use Merb won&#8217;t have to justify why they decided against Rails.</p>
<p>I&#8217;m going to tell another story which might not seem related at first. But I have a point, I promise.</p>
<p>In the middle of last year, we started a new project based on the ASP.NET MVC framework and the Entity Framework, both of which were essentially beta projects at the time. Despite some (entirely expected) pain from the shifting nature of data frameworks, the project progressed remarkably quickly, and we have begun shipping it to paying customers.</p>
<p>We had planned on using ASP.NET Dynamic Data, but we had to drop that very early in the project. The first thing that you have to do when using Dynamic Data is to <a href="http://msdn.microsoft.com/en-us/library/cc668159.aspx#WebSiteConfiguration">call RegisterContext, passing your model</a>, which can be an Entity Framework or LINQ to SQL model. Why only these two frameworks, when both return materialized .NET objects with rich metadata? Good question. What if I don&#8217;t want to surface Entity Framework instances in my web application, but prefer to use lightweight data transfer objects instead? What if I don&#8217;t want to use the Entity Framework at all?</p>
<p>Worse, the initial release of Dynamic Data cannot handle Entity Framework models containing many-to-many relationships, even though support for these is one of the more significant features that the Entity Framework has over LINQ to SQL. Worse still, Dynamic Data provides no way to <a href="http://en.wikipedia.org/wiki/Scaffold_(programming)">scaffold</a> only a subset of your model. I would have been perfectly happy if Dynamic Data just couldn&#8217;t provide scaffolding for tables with many-to-many relationships, but could handle other things. Unfortunately, any one thing which Dynamic Data cannot handle in RegisterContext means that you cannot use Dynamic Data at all. So we didn&#8217;t.</p>
<p>The non-support for many-to-many relationships <a title="ASP.NET Dynamic Data 4.0 Preview 2" href="http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=20628">will be fixed in a forthcoming version of Dynamic Data</a>, and you can get a preview version now. I expect we&#8217;ll give it a try, because the framework has a lot of promise, and portions of it are very nicely done. But part of me wonders which other, entirely legal, things might be lurking in our Entity Framework model which might make Dynamic Data die a speedy death. I don&#8217;t see any mention of removing the restriction that Dynamic Data must understand your entire model before it can do anything at all. Even if it does understand our model, I wonder what will happen if I hand it a type which doesn&#8217;t happen to be in that model?</p>
<p>This is an area where laziness could be a virtue. Obviously, Dynamic Data needs some sort of metadata model from which to produce its scaffolding. But if it waited to generate this model for types until they were actually needed, it would not die because it didn&#8217;t handle something which the application didn&#8217;t ever have a need to have scaffolded. Moreover, I think it&#8217;s the desire to create a metadata model for every type you might possibly want Dynamic Data support for during the entire lifetime of the application upfront which led to the design decision to support only the Entity Framework and LINQ to SQL. If you create the metadata models on an as-needed basis, using Entity Framework or LINQ to SQL knowledge where possible to enrich the models, then you don&#8217;t need a single model in a "known" framework as a starting point.</p>
<p>So the lesson here is that, even within a single-vendor ecosystem such as the standard portions of the Microsoft .NET Framework, dependencies on other projects can be lethal.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37874&amp;akst_action=share-this" onclick="akst_share('37874', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F26%2F37874%2F', 'Lightweight+Frameworks%2C+Again'); return false;" title="Post to del.icio.us, etc." id="akst_link_37874" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Lightweight%20Frameworks%2C%20Again&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F26%2F37874%2F" id="akst_email_37874" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Lightweight Frameworks</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/12/12/37872/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/12/12/37872/#comments</comments>
    <pubDate>Fri, 12 Dec 2008 22:08:43 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37872</guid>
    <description><![CDATA[Big frameworks with strong coupling are prisons. Once you go into them, you're stuck, and it can be incredibly difficult to get out.]]></description>
      <content:encoded><![CDATA[<p>I came across this <a href="http://www.infoq.com/interviews/katz-merb">interview with Yehuda Katz</a> about <a href="http://merbivore.com/">Merb</a>, an interesting web framework for <a href="http://www.ruby-lang.org/en/">Ruby</a>.  Although I have less actual experience with Merb than with Rails, I&#8217;ve always liked the general design philosophy of Merb. Whereas Rails appears to be designed as a complete MVC framework (and a nice one, too; I&#8217;m not writing this post to critique Rails), Merb allows you to build your own framework by combining existing tools. It doesn&#8217;t try and reinvent a new ORM or package manager, for example. Like <a href="http://jquery.com/">jQuery</a>, less commonly needed items are available as <a href="http://github.com/wycats/merb-plugins/tree/master">plug-ins</a>, rather than being part of the core framework. As Katz puts it:</p>
<blockquote><p>We also try to keep our code relatively small and modular, so a few just install Merb core, which is the core of framework - there are only 6.000 lines of code in there. Just starting up Merb and having it run it&#8217;s going automatically takes up less RAM, the critical path will be smaller, we don&#8217;t do alias_method_chain, which means that the number of method calls for a regular request is going to be smaller out of Merb.</p></blockquote>
<p>Now, that&#8217;s nice, but it&#8217;s even nicer if your preferred ORM doesn&#8217;t happen to be <a href="http://wiki.rubyonrails.org/rails/pages/ActiveRecord">ActiveRecord</a>.</p>
<p>I like the <a href="http://www.asp.net/mvc/">ASP.NET MVC</a> framework for the same reason.  It doesn&#8217;t supply an ORM because you might not need one, and if you do, there are plenty of existing tools from which to choose.  It doesn&#8217;t invent a new templating language.  Though <a href="http://msdn.microsoft.com/en-us/library/cc668201.aspx">ASP.NET routing</a> was created to support it, routing is no longer part of the ASP.NET MVC framework; it&#8217;s now an entirely separate project which other tools can and do use.</p>
<p>By contrast, I have pretty much sworn off / am not even tempted to try certain other frameworks which attempt to do everything required to build an entire application, with strong coupling between the various parts.  Indeed, even though I use the Entity Framework in my ASP.NET MVC applications, these two parts of the application have no knowledge of each other. I&#8217;m also incredibly wary of commercial web "components" which don&#8217;t play well in ASP.NET MVC, due to dependencies on <a href="http://msdn.microsoft.com/en-us/library/ms972976.aspx">View State</a> (or worse).  These aren&#8217;t web "components;" they are extensions of the WebForms framework, and I&#8217;m building web sites, not WebForms sites.</p>
<p>Big frameworks with strong coupling are prisons. Once you go into them, you&#8217;re stuck, and it can be incredibly difficult to get out.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37872&amp;akst_action=share-this" onclick="akst_share('37872', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F12%2F37872%2F', 'Lightweight+Frameworks'); return false;" title="Post to del.icio.us, etc." id="akst_link_37872" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Lightweight%20Frameworks&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F12%2F37872%2F" id="akst_email_37872" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>nPlus1</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/12/11/37859/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/12/11/37859/#comments</comments>
    <pubDate>Thu, 11 Dec 2008 20:05:56 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37859</guid>
    <description><![CDATA[nPlus1 is a new site with articles and links on application architecture. They&#8217;re also looking for writers.
]]></description>
      <content:encoded><![CDATA[<p><a href="http://nplus1.org/">nPlus1</a> is a new site with <a href="http://nplus1.org/articles/">articles</a> and <a href="http://nplus1.org/tidbits/">links</a> on application architecture. They&#8217;re also <a href="http://nplus1.org/articles/look-for-writers/">looking for writers</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37859&amp;akst_action=share-this" onclick="akst_share('37859', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F11%2F37859%2F', 'nPlus1'); return false;" title="Post to del.icio.us, etc." id="akst_link_37859" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=nPlus1&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F11%2F37859%2F" id="akst_email_37859" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Job Security</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/12/01/37856/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/12/01/37856/#comments</comments>
    <pubDate>Mon, 01 Dec 2008 14:24:50 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37856</guid>
    <description><![CDATA[From News of the Weird:
Facing a state budget crisis in July, California Gov. Arnold Schwarzenegger fired about 10,000 temporary and part-time workers and ordered the 200,000 permanent employees to be paid only the minimum wage of $6.55 an hour until the legislature passed a crisis-solving budget. However, a week later the State Controller John Chiang [...]]]></description>
      <content:encoded><![CDATA[<p>From <a href="http://www.newsoftheweird.com/archive/nw081130.html">News of the Weird</a>:</p>
<blockquote><p>Facing a state budget crisis in July, California Gov. Arnold Schwarzenegger fired about 10,000 temporary and part-time workers and ordered the 200,000 permanent employees to be paid only the minimum wage of $6.55 an hour until the legislature passed a crisis-solving budget. However, a week later the <a title="California state computers can't handle pay cut, controller says" href="http://www.sacbee.com/capitolandcalifornia/story/1132588.html">State Controller John Chiang pointed out that state payroll records could not be changed</a> to accommodate the cut because they were written in the antiquated <a title="COBOL just keeps going, say advocates" href="http://www.sacbee.com/capitolandcalifornia/story/1164867.html">COBOL</a> computer language, and virtually the only state employees who knew the code were some of the part-timers Schwarzenegger had just fired.</p></blockquote>
<p>It turns out <a title="Some question if computer is to blame in California minimum wage standoff" href="http://www.sacbee.com/140/story/1164723.html">the whole system is fragile</a>, not just the computers.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37856&amp;akst_action=share-this" onclick="akst_share('37856', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F01%2F37856%2F', 'Job+Security'); return false;" title="Post to del.icio.us, etc." id="akst_link_37856" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Job%20Security&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F12%2F01%2F37856%2F" id="akst_email_37856" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>A Proof of the Undecidability of the Halting Problem, In Verse</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/11/21/37850/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/11/21/37850/#comments</comments>
    <pubDate>Fri, 21 Nov 2008 22:01:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37850</guid>
    <description><![CDATA[Well, the title of this post pretty much tells the story; Geoffrey K. Pullum has published a proof that the Halting Problem is undecidable, in verse.  Here&#8217;s an excerpt:
Here’s the trick that I’ll use – and it’s simple to do.
I’ll define a procedure, which I will call Q,
that will use P’s predictions of halting success
to [...]]]></description>
      <content:encoded><![CDATA[<p>Well, the title of this post pretty much tells the story; Geoffrey K. Pullum has published a proof that the Halting Problem is undecidable, in verse.  Here&#8217;s an excerpt:</p>
<blockquote><p>Here’s the trick that I’ll use – and it’s simple to do.<br />
I’ll define a procedure, which I will call <em>Q</em>,<br />
that will use <em>P</em>’s predictions of halting success<br />
to stir up a terrible logical mess.</p></blockquote>
<p>Do read <a href="http://ling.ed.ac.uk/~gpullum/loopsnoop.pdf">the whole thing</a>, as it actually does contain a peer-reviewed proof.</p>
<p>Personally, I find rhyme and meter to be underused tools in the fields of mathematics and computer science. I suspect that most programmers don&#8217;t read technical journals at all; making the research more entertaining can only help the field. Then again, <a href="http://blogs.msdn.com/oldnewthing/archive/2007/11/13/6157507.aspx#6178257">I&#8217;ve been known to cancel spam in verse</a>, so my opinion may be outside of the mainstream.</p>
<p>So anyway, I&#8217;m off to adapt Beowulf into a proof in epic verse of the <a href="http://mathworld.wolfram.com/Taniyama-ShimuraConjecture.html">Taniyama–Shimura conjecture</a>.  I&#8217;m still dithering over whether to base my adaptation on <a href="http://www.wwnorton.com/college/english/nael/beowulf/introbeowulf.htm">Seamus Heaney&#8217;s translation</a>, or <a href="http://beowulf.engl.uky.edu/~kiernan/ENG619/eBeowulf-ed/ed/ed.htm">the original, Old English</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37850&amp;akst_action=share-this" onclick="akst_share('37850', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F11%2F21%2F37850%2F', 'A+Proof+of+the+Undecidability+of+the+Halting+Problem%2C+In+Verse'); return false;" title="Post to del.icio.us, etc." id="akst_link_37850" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=A%20Proof%20of%20the%20Undecidability%20of%20the%20Halting%20Problem%2C%20In%20Verse&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F11%2F21%2F37850%2F" id="akst_email_37850" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>My CodeRage Presentation: Functional Programming in Delphi 2009</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/11/04/37845/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/11/04/37845/#comments</comments>
    <pubDate>Tue, 04 Nov 2008 20:22:56 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[CodeRage]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37845</guid>
    <description><![CDATA[
I&#8217;ll be speaking at the CodeRage III virtual conference, on the subject of functional programming in Delphi 2009.  Here&#8217;s the (rather bland) abstract:
Delphi 2009 includes several new features well-suited to a functional style of programming.  We&#8217;ll explore the use of generics, anonymous methods, and new RTL types while introducing concepts from functional programming.
If you&#8217;ve been [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://conferences.codegear.com/coderage08"><img src="http://conferences.codegear.com/coderage08/article/38867/images/38867/03000001.png" alt="CodeRage 2008 logo" /></a></p>
<p>I&#8217;ll be speaking at the CodeRage III virtual conference, on the subject of functional programming in Delphi 2009.  Here&#8217;s the (rather bland) abstract:</p>
<blockquote><p>Delphi 2009 includes several new features well-suited to a functional style of programming.  We&#8217;ll explore the use of generics, anonymous methods, and new RTL types while introducing concepts from functional programming.</p></blockquote>
<p>If you&#8217;ve been following my blog over the past few months, you might have <a title="Implementing Memoize in Delphi 2009" href="http://blogs.teamb.com/craigstuntz/2008/10/01/37839">a fair idea of what to expect</a>.  As you can tell from the somewhat vague abstract, I&#8217;m still rounding out the details of the presentation.  If there&#8217;s anything you&#8217;d like to see me cover, please make your suggestion in comments.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37845&amp;akst_action=share-this" onclick="akst_share('37845', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F11%2F04%2F37845%2F', 'My+CodeRage+Presentation%3A+Functional+Programming+in+Delphi+2009'); return false;" title="Post to del.icio.us, etc." id="akst_link_37845" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=My%20CodeRage%20Presentation%3A%20Functional%20Programming%20in%20Delphi%202009&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F11%2F04%2F37845%2F" id="akst_email_37845" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>LINQ to SQL : Entity Framework :: WinForms : WPF</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/11/03/37844/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/11/03/37844/#comments</comments>
    <pubDate>Mon, 03 Nov 2008 16:29:21 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/11/03/37844</guid>
    <description><![CDATA[Microsoft has announced their intention to "de-emphasize" LINQ to SQL, and guided us to use the Entity Framework, instead. This is not too surprising, considering that LINQ to SQL was never supposed to exist in the first place. But, just like with WinForms, a lot of people have used LINQ to SQL in production code [...]]]></description>
      <content:encoded><![CDATA[<p>Microsoft has announced their intention to <a href="http://blogs.msdn.com/adonet/archive/2008/10/29/update-on-linq-to-sql-and-linq-to-entities-roadmap.aspx">"de-emphasize" LINQ to SQL, and guided us to use the Entity Framework, instead</a>. This is not too surprising, considering that <a href="http://blogs.msdn.com/mattwar/archive/2007/05/31/the-origin-of-linq-to-sql.aspx" title="The Origin of LINQ to SQL">LINQ to SQL was never supposed to exist in the first place</a>. But, just like with WinForms, a lot of people have used LINQ to SQL in production code in no small part because the preferred solution wasn&#8217;t ready yet, and LINQ to SQL includes features which are not in the current released version of the Entity Framework.</p>
<p>This speaks to the importance of abstracting data access.  The nice thing about object relational mapping is that once you&#8217;ve read the data, your data are just objects, whether or not they&#8217;re POCOs. You can and should emphasize this encapsulation by hiding the reading and writing behind a framework such as the <a href="http://martinfowler.com/eaaCatalog/repository.html">Repository pattern</a>.  It is, IMHO, a mistake to ever call something like Context.SaveChanges inside of a controller.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37844&amp;akst_action=share-this" onclick="akst_share('37844', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F11%2F03%2F37844%2F', 'LINQ+to+SQL+%3A+Entity+Framework+%3A%3A+WinForms+%3A+WPF'); return false;" title="Post to del.icio.us, etc." id="akst_link_37844" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=LINQ%20to%20SQL%20%3A%20Entity%20Framework%20%3A%3A%20WinForms%20%3A%20WPF&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F11%2F03%2F37844%2F" id="akst_email_37844" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Transforming Models</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/10/30/37843/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/10/30/37843/#comments</comments>
    <pubDate>Thu, 30 Oct 2008 17:48:45 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/10/30/37843</guid>
    <description><![CDATA[In my last post, "&#8216;Model&#8217; Is an Overloaded Word," I discussed several types of models which might be present in an MVC application. But I limited the discussion to models which are actually in the executable.  There may of course be additional models, such as ERDs, UML models, etc., which exist in the development environment, [...]]]></description>
      <content:encoded><![CDATA[<p>In my last post, "<a href="http://blogs.teamb.com/craigstuntz/2008/10/28/37842">&#8216;Model&#8217; Is an Overloaded Word</a>," I discussed several types of models which might be present in an MVC application. But I limited the discussion to models which are actually in the executable.  There may of course be additional models, such as <acronym title="Entity Relationship Diagram">ERD</acronym>s, UML models, etc., which exist in the development environment, but are not actually part of the executable.</p>
<p>It is often the case that we use software tools to transform these conceptual models into executable code of one form or another.  For example, a database management tool may know how to transform an ERD into physical database metadata.  A UML design surface might know how to transform a UML model into compilable code.  Most object-relational mappers designed for non-dynamic languages such as C# and Java seem to work by transforming some kind of schema file, usually XML, into compilable code.  And so on&#8230;</p>
<p>Inside the application, at runtime, a similar transformation of models occurs.  Let&#8217;s examine the pipeline which results in transforming data in a database into HTML which a user can view:</p>
<ol>
<li>The user invokes an action.  This starts a chain of events ultimately resulting in a call to the database server in the form of an SQL statement.  The database server transforms its will on-disk representation of the data into a result set understandable by the data access components.</li>
<li>The object-relational mapping transforms the result set into entity instances — instances of classes in a form useful to implementers of business logic.</li>
<li>If the application is using the Repository pattern, these entity instances may be passed directly to the controller.  Or they may be transformed into lightweight data access objects.</li>
<li>Whatever their form, the entity instances will be wrapped up into a model containing all of the information required to render a view.</li>
<li>The view will transform the entities into a different kind of model: HTML.</li>
<li>The browser will transform the HTML into a DOM which can be further manipulated via JavaScript.</li>
</ol>
<p>A similar series of transformations between model types occurs when we accept user input and store it back in the database.</p>
<p>These series of transformations are not so different from the transformations I mentioned above, like transforming a UML model into executable code.  Indeed, compilation itself is just another kind of model transformation, changing a representation which is (hopefully!) readable by a developer into a representation readable by a machine.  If the transformation is lossless, then it can probably be done in both directions.</p>
<p>So one way to look at an application is as a series of transformations from one model type to another, not only in execution, but also in the manner in which the application itself is built. However, the transformations are performed with wildly different implementations:</p>
<ul>
<li>A special-purpose executable (e.g., a compiler) can be used to transform the models. Such executables are typically fairly limited; most compilers support only one language, and do not, for example, transform UML models into code.</li>
<li> We can write code in a high-level language to transform the models, often in a way which is dependent on the specific types or properties involved (e.g, A.Foo = b.Foo), or possibly at a more generic level, such as with a common interface.</li>
<li>We can create informally-specified principles for model transformation, such as "<a href="http://en.wikipedia.org/wiki/Convention_over_Configuration">convention over configuration</a>," which are often sufficient to completely specify the transformation without requiring code.</li>
<li>We can create systems of rules for model transformation. The formal name for such a system of rules is an <a href="http://mathworld.wolfram.com/Algebra.html">algebra</a>, not to be confused with the <a href="http://en.wikipedia.org/wiki/Elementary_algebra">elementary algebra</a> you learned in high school. This is a set of simple rules designed to be composed into more advanced transformations. One such system is <a href="http://www.vocw.vn/content/m10536/latest/">relational algebra</a>, which surfaces (in a heavily mutilated form) in SQL databases.</li>
</ul>
<p>Now, my purpose in this post is not to claim that one of these methods is superior to the others.  "The best tool for the job" still applies.  The idea of model transformation, however, encompasses more parts of a software system than many programmers commonly suppose.  The notion of treating your source code as a model which can be transformed via an algebra into an equivalent, but faster and provably correct, application <a title="Can Programming Be Liberated from the von Neumann Style?  A Functional Style and Its Algebra of Programs" href="http://www.stanford.edu/class/cs242/readings/backus.pdf">is not new</a>, but is perhaps surprising to programmers who have not studied functional programming. So the question is not "How do I create an instance of Bar from an instance of Foo?," but "What kind of transformation is this, and how does it fit into the context of the other transformations I&#8217;m performing in this application?"</p>
<p>Such a worldview makes technologies like Haskell&#8217;s monads and LINQ, designed as generic solutions for the problem of transforming one type of set into another, even more interesting than they already are.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37843&amp;akst_action=share-this" onclick="akst_share('37843', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F30%2F37843%2F', 'Transforming+Models'); return false;" title="Post to del.icio.us, etc." id="akst_link_37843" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Transforming%20Models&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F30%2F37843%2F" id="akst_email_37843" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>"Model" Is an Overloaded Word</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/10/28/37842/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/10/28/37842/#comments</comments>
    <pubDate>Tue, 28 Oct 2008 14:44:59 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/10/28/37842</guid>
    <description><![CDATA[Let&#8217;s say you&#8217;re writing a web application, and using the Model View Controller design.  Maybe you&#8217;re using an out-of-the-box framework like the ASP.NET MVC Framework or Rails, or maybe you&#8217;re using a different implementation; it doesn&#8217;t matter.  It&#8217;s pretty obvious that the "View" portion of the design is the part which provides a template for [...]]]></description>
      <content:encoded><![CDATA[<p>Let&#8217;s say you&#8217;re writing a web application, and using the Model View Controller design.  Maybe you&#8217;re using an out-of-the-box framework like the ASP.NET MVC Framework or Rails, or maybe you&#8217;re using a different implementation; it doesn&#8217;t matter.  It&#8217;s pretty obvious that the "View" portion of the design is the part which provides a template for rendered HTML, and that the "Controller" portion of the design is the part which handles requests, specifying the general outline for what should be returned to the user.  But what about the "Model?"</p>
<p>Most non-trivial applications have many different models, and for good reason.  If the application uses a relational database, it will have a relational model.  A non-trivial web application may use an application server, containing an entity model with an object-relational mapping, perhaps based on a framework like the Entity Framework or NHibernate.  In some designs, these entity types are not exposed from the application server, but rather represented as lightweight <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html">data access objects</a>.  These data access objects are made available to clients of the application server, such as a web application.</p>
<p>Inside the web application, it&#8217;s possible that the lightweight data access objects will be made available directly to the View, without being wrapped up inside any other type.  But it&#8217;s more likely that additional information will need to be passed to the View, requiring the use of an additional model type, which wraps up the information required by a particular View.  Or, a View might require a different representation of the data access objects, such as XML or JSON.</p>
<p>So let&#8217;s count the different types of "Models" I&#8217;ve listed so far:</p>
<ol>
<li>Relational data model</li>
<li>Entity model, perhaps with an object-relational mapping</li>
<li>Lightweight data access objects</li>
<li>View-specific models</li>
</ol>
<p>To be clear, I don&#8217;t think the existence of multiple types of models is by itself a problem.  But I do think that the overloading of the term create some confusion about how to follow the MVC application design.</p>
<p>When you create a new ASP.NET MVC web application, Visual Studio creates a Solution containing a single project for the web application itself, with a folder called Models.  Many of the demonstrations of ASP.NET MVC projects that I&#8217;ve seen drop a LINQ-to-SQL model inside of this folder.  I understand that people like to keep their demonstrations simple, but as a rule I think that any type of object-relational model should be in a separate assembly from the web application, along with any business logic implementation required.  This second assembly becomes the API for your data which the web application will use.  It can be a web service, or an assembly which exposes methods for accessing the data directly, e.g. with the <a href="http://martinfowler.com/eaaCatalog/repository.html">Repository pattern</a>. However, I keep the Models folder in the web application, and use it for "View models," which handle things like pagination, aggregation of multiple instances required by the view, etc.</p>
<p>Maybe MVC should stand for Model<strong>s</strong> View Controller?</p>
<p>In the second part of this series, I will examine additional types of models, and <a title="Transforming Models" href="http://blogs.teamb.com/craigstuntz/2008/10/30/37843">the general problem of transforming one model into another</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37842&amp;akst_action=share-this" onclick="akst_share('37842', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F28%2F37842%2F', '%22Model%22+Is+an+Overloaded+Word'); return false;" title="Post to del.icio.us, etc." id="akst_link_37842" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=%22Model%22%20Is%20an%20Overloaded%20Word&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F28%2F37842%2F" id="akst_email_37842" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Database Workbench Lite for InterBase</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/10/20/37841/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/10/20/37841/#comments</comments>
    <pubDate>Mon, 20 Oct 2008 20:53:50 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/10/20/37841</guid>
    <description><![CDATA[Martijn Tonies e-mailed me to inform me of the release of Database Workbench Lite for InterBase.  It&#8217;s a free version of Database Workbench, a full-featured administration tool for InterBase and other database servers.  You can compare the "lite" and "professional" feature sets here. Upscene had also just released version 3.2 of Database Workbench Professional.
Share This [...]]]></description>
      <content:encoded><![CDATA[<p>Martijn Tonies e-mailed me to inform me of the <a href="http://www.upscene.com/index.htm?./news/20081020b.htm">release</a> of <a href="http://www.upscene.com/index.htm?./products/dbw/index.htm">Database Workbench Lite for InterBase</a>.  It&#8217;s a free version of Database Workbench, a full-featured administration tool for InterBase and other database servers.  You can <a href="http://www.upscene.com/documentation/dbw3/index.html?gs_editions.htm">compare the "lite" and "professional" feature sets here</a>. Upscene had also just released version 3.2 of Database Workbench Professional.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37841&amp;akst_action=share-this" onclick="akst_share('37841', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F20%2F37841%2F', 'Database+Workbench+Lite+for+InterBase'); return false;" title="Post to del.icio.us, etc." id="akst_link_37841" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Database%20Workbench%20Lite%20for%20InterBase&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F20%2F37841%2F" id="akst_email_37841" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>OpenCTF - Component Test Framework</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/10/15/37840/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/10/15/37840/#comments</comments>
    <pubDate>Wed, 15 Oct 2008 18:36:19 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/10/15/37840</guid>
    <description><![CDATA[In my CodeRage presentation last year, I demonstrated a framework for semi-automatically building unit tests of Delphi components.  I left the project very much in an alpha state, and haven&#8217;t had time to return to it, as other things are taking up my time recently.  I still think, however, that the concept of automatically generating [...]]]></description>
      <content:encoded><![CDATA[<p>In my CodeRage presentation last year, I demonstrated <a href="http://cc.codegear.com/Item/25266">a framework for semi-automatically building unit tests of Delphi components</a>.  I left the project very much in an alpha state, and haven&#8217;t had time to return to it, as other things are taking up my time recently.  I still think, however, that the concept of automatically generating test cases is a good one.</p>
<p>So I&#8217;d like to note another project which uses the same general concept in a very different manner.  <a href="http://www.mikejustin.com/products.html#item_261">OpenCTF </a>is a free framework which generates DUnit test cases by looking for certain "known" errors in arbitrary components.</p>
<p>Delphi&#8217;s relatively limited introspection/RTTI features restrict how far you can go with projects like this.  It&#8217;s really only possible to automatically test published properties and published methods with known signatures.  Likewise, most of the Delphi-aware automated testing tools require that you change your application to include special testing interfaces in order to get full functionality from the tool. One of the benefits of enhanced RTTI in the future would be more options for automated testing.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37840&amp;akst_action=share-this" onclick="akst_share('37840', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F15%2F37840%2F', 'OpenCTF+-+Component+Test+Framework'); return false;" title="Post to del.icio.us, etc." id="akst_link_37840" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=OpenCTF%20-%20Component%20Test%20Framework&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F15%2F37840%2F" id="akst_email_37840" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Implementing Memoize in Delphi 2009</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/10/01/37839/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/10/01/37839/#comments</comments>
    <pubDate>Wed, 01 Oct 2008 18:30:10 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/10/01/37839</guid>
    <description><![CDATA[My last series on Delphi 2009&#8217;s generics was self-consciously investigating a corner case.  This post, however, is going to bring us back to Earth very quickly, so prepare for a steep descent!  I&#8217;m going to implement a useful, higher-order function, Memoize, using Delphi 2009&#8217;s generics and anonymous methods.
Memoization is a generic solution to the problem [...]]]></description>
      <content:encoded><![CDATA[<p><a title="Building a Generic Statistics Library" href="http://blogs.teamb.com/craigstuntz/2008/09/09/37833">My last series on Delphi 2009&#8217;s generics</a> was self-consciously investigating a corner case.  This post, however, is going to bring us back to Earth very quickly, so prepare for a steep descent!  I&#8217;m going to implement a useful, higher-order function, <a href="http://en.wikipedia.org/wiki/Memoization">Memoize</a>, using Delphi 2009&#8217;s generics and anonymous methods.</p>
<p>Memoization is a generic solution to the problem of caching function results. The function Memoize accepts a function as an argument and returns a function which does exactly the same thing, except that it caches the results.  Here&#8217;s the prototype:</p>
<blockquote>
<pre><code><strong>class function </strong>Memoize&lt;A, R&gt;(AFunc: TFunc&lt;A, R&gt;): TFunc&lt;A, R&gt;;</code></pre>
</blockquote>
<p>So my version of Memoize will accept any function which takes a single argument of any type, and returns a result of any type. Memoize returns a new function with exactly the same signature. I&#8217;ve often written systems to cache the results of database queries in my older Delphi code.  Lately, I&#8217;ve been using TClientDataSet to do the same thing, but it still results in several lines of code to accomplish what is essentially a single function call.  Memoize allows me to solve this problem one time and use it for as many situations as I can imagine.</p>
<p>Well, almost any function.  Caching is obviously only useful for functions which are referentially transparent, which is another way of saying that their output is completely determined by their input.  You wouldn&#8217;t want a cached version of "Now()" or "Create()", for example. Memoization is most useful when a function performs a lengthy calculation, or queries a database or a web service with a lot of latency.  In order to simulate such a function for the purpose of testing my implementation of Memoize, I&#8217;ve written the following test function:</p>
<blockquote>
<pre><code><strong>class function </strong>TestTMemoize.SlowIncrement(ANum: integer): integer;<strong>
begin
  </strong>Sleep(100); // simulate web service / db access
  Result := ANum + 1;<strong>
end;</strong></code></pre>
</blockquote>
<p>This is useless, but it allows me to distribute a testable version of the project without having any dependency on any specific database or Web service.  Feel free to substitute a more useful function if you try this yourself. <img src='http://blogs.teamb.com/feeds/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> In order to create a memoized version of this function, I just pass it to Memoize, and call the function that is returned instead of the original one:</p>
<blockquote>
<pre><code><strong>procedure </strong>DoStuff;
<strong>var</strong>
  MemoizedFunc: TFunc&lt;integer,integer&gt;;
  iResult: integer;
<strong>begin</strong>
  MemoizedFunc := TMemoize.Memoize&lt;integer,integer&gt;(SlowIncrement);
  iResult := MemoizedFunc(1);
<strong>end</strong>;</code></pre>
</blockquote>
<p>The Memoize function certainly sounds useful, but how could I write such a thing?  Well, I obviously need generics, or my version of Memoize would be limited to functions which only accepted and returned one specific type.  And I need anonymous methods, because that is the only way that I can return new functions at runtime.  Finally, I need some kind of cache to store pairs of arguments and results, so that successive executions with the same argument can find result in the cache.</p>
<p>Let&#8217;s examine the last requirement first.  Delphi 2009&#8217;s Generics.Collections unit includes a TDictionary&lt;TKey,TValue&gt; type which, at first glance, it appears to do what I need.  Unfortunately, it isn&#8217;t lifetime-managed. So I will just subtype Delphi 2009&#8217;s TDictionary&lt;TKey,TValue&gt; and implement a new IDictionary&lt;TKey,TValue&gt; interface I will create.</p>
<p>I will explain why it is important to have a lifetime-managed dictionary in order to implement this function at the end of this post. You can easily understand the rest of the post without grasping this detail, if you&#8217;re willing to take my word on the fact that I need a lifetime-managed list. For the time being, let&#8217;s just continue with the code. Here&#8217;s the full source code for Memoize, which is actually very simple:</p>
<blockquote>
<pre><code><strong>class function</strong> TMemoize.Memoize&lt;A,R&gt;(AFunc: TFunc&lt;A, R&gt;): TFunc&lt;A, R&gt;;
<strong>var</strong>
  Map: IDictionary&lt;A, R&gt;;
<strong>begin</strong>
  Map := TManagedDictionary&lt;A, R&gt;.Create;

  Result := <strong>function</strong>(arg: A): R
  <strong>var</strong>
    FuncResult: R;
  <strong>begin</strong>
    <strong>if </strong>Map.TryGetValue(arg, FuncResult) <strong>then begin</strong>
      Exit(FuncResult);
    <strong>end</strong>;
    FuncResult := AFunc(arg);
    Map.Add(arg, FuncResult);
    Exit(FuncResult);
  <strong>end</strong>;
<strong>end</strong>;</code></pre>
</blockquote>
<p>In Delphi 2009, you can call Exit with an argument in order to return a certain value from a function immediately, as if you had assigned Result and then called Exit without the argument.  Other than that, I don&#8217;t think there is too much to explain about the implementation above.</p>
<p>In order to prove that it works, I wrote a unit test.  The unit test shows that the second execution of a Memoized version of a slow function for the same argument (1) returns the same value and (2) is more than two orders of magnitude faster.  One of the reasons I included this unit test was to demonstrate that unit tests can be used to verify performance goals as well as functional specifications.  In order to profile the function, I&#8217;ve "borrowed" <a title="Anonymous methods in testing / profiling situations" href="http://barrkel.blogspot.com/2008/08/anonymous-methods-in-testing-profiling.html">Barry Kelly&#8217;s useful TBenchmarker class</a>. Here&#8217;s the test:</p>
<blockquote>
<pre><code><strong>procedure</strong> TestTMemoize.TestMemoize;
<strong>var</strong>
  Cold, Warm: Double;
  ColdResult, WarmResult, AnonResult: integer;
  MemoizedSlowInc: TFunc&lt;integer, integer&gt;;
  BenchmarkProc: TProc;
<strong>begin</strong>
  MemoizedSlowInc := TMemoize.Memoize&lt;integer,integer&gt;(SlowIncrement);
  BenchmarkProc := <strong>procedure</strong>()
  <strong>begin</strong>
    AnonResult := MemoizedSlowInc(1);
  <strong>end</strong>;

  // first execution should be slow
  Cold := TBenchmarker.Benchmark(BenchmarkProc, 1, 0);
  ColdResult := AnonResult;
  // next time for same value should be fast
  Warm := TBenchmarker.Benchmark(BenchmarkProc, 1, 0);
  WarmResult := AnonResult;

  CheckEquals(ColdResult, WarmResult);
  CheckTrue(Warm &lt; (Cold / 100));
<strong>end</strong>;</code></pre>
</blockquote>
<p>You can download the <a title="Memoize implementation for Delphi 2009" href="http://cc.codegear.com/item/26106">full source code</a> from CodeCentral.</p>
<p>Finally, here&#8217;s the full explanation for why I needed to create a lifetime-managed dictionary:</p>
<p>Anonymous methods, in every implementation I&#8217;ve ever seen, can "capture" variables in the declaring method.  This means that you can use variables (or method arguments) declared in the method which defines the anonymous method, without passing them as arguments.  But since we are going to return the anonymous function as the result of the defining function, any object referenced in the anonymous function must not be freed by the defining function.  In Delphi 2009, captured variables are captured by reference (this is similar to C#, but different than JavaScript).  Recall that anonymous methods are reference counted.  When an anonymous method captures a variable in the declaring method, it will be freed when there are no more references to the anonymous method, provided that the captured variable is a lifetime-managed type, such as a string, a record, an interface, etc.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37839&amp;akst_action=share-this" onclick="akst_share('37839', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F01%2F37839%2F', 'Implementing+Memoize+in+Delphi+2009'); return false;" title="Post to del.icio.us, etc." id="akst_link_37839" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Implementing%20Memoize%20in%20Delphi%202009&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F10%2F01%2F37839%2F" id="akst_email_37839" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>CDN Search, Part 3: Search Results</title>
    <link>http://blogs.teamb.com/yaminov/2008/09/24/cdn-search-part-3-search-results/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/09/24/cdn-search-part-3-search-results/#comments</comments>
    <pubDate>Wed, 24 Sep 2008 17:44:19 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[CDN]]></category>

		<category><![CDATA[GetPublished]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/09/24/cdn-search-part-3-search-results/</guid>
    <description><![CDATA[Previously on this blog: we deployed a new search engine and used background jobs to index content.
When you run a search query on CDN, you&#8217;ll see just below your search results line of text that looks something like this:
Query processed in 375ms (31.25ms server/network, 343.75ms database)
This text describes exactly how long it took to prepare [...]]]></description>
      <content:encoded><![CDATA[<p>Previously on this blog: we <a href="http://blogs.teamb.com/yaminov/2008/09/21/cdn-search-part-1-new-search-engine/">deployed a new search engine</a> and <a href="http://blogs.teamb.com/yaminov/2008/09/23/cdn-search-part-2-background-jobs/">used background jobs</a> to index content.</p>
<p>When you run a search query on CDN, you&#8217;ll see just below your search results line of text that looks something like this:</p>
<p>Query processed in 375ms (31.25ms server/network, 343.75ms database)</p>
<p>This text describes exactly how long it took to prepare the query, run it, retrieve all information required for display from the database, check the visibility of every result, sort the results according to the user&#8217;s preference, and prepare the set of results in the current page for display.</p>
<p>The times I quoted above came from a run of <a href="http://dn.codegear.com/search?qall=TClientDataSet&amp;in=source&amp;sourcelang=cpp&amp;allsites=y">this query</a>, which searches all indexed sites for C++ source code that contains the word "TClientDataSet". The text is slightly inaccurate: although the total processing time was indeed 375ms, there are other valid methods of counting the other times.</p>
<p>The "server/network" time represents the time it took to send the query to Lucene, get the results from the web service, and convert them to classes and records GetPublished can process. Over 95% of that time is used for transferring the results over the network. The rest is taken by the actual search engine on the Lucene server and the result processing code on the server running GetPublished.</p>
<p>Almost everything else GetPublished does with the results involves the database, so we say the rest of the time belongs to "database". However, for large result sets the Lucene engine processing time - and certainly network transfer time - will be longer. GetPublished actually uses that time to execute additional queries, by running the code in multiple threads.</p>
<p>Here&#8217;s the actual processing log from GetPublished for the same query:</p>
<pre>Search expression started
Getting list of sites to include in the search
Search includes one or more GetPublished sites
Retrieving external sites
Search includes one or more external sites
Building Lucene query
Lucene query: +appid:(gp blogs blogsteamb cc qc) AND (cpp.source:(+TClientDataSet))
Search sites: 1,5,7,9,10,11,12
Search thread starting
Retrieving language ID
Retrieving site names
Retrieving visible version IDs
Retrieving staged visible version IDs
Retrieving welcome content types for welcome page queries
Welcome content filter:  IN (26,314,322)
Query completed in 31.25ms
The web service returned in 31.25ms
The search engine ran the query in 0ms
Total number of results: 59
Sorting results by AppID and version ID
Adding information for live versions in search results
Adding information for staged versions in search results
Removing versions that are not visible to the user
Updated number of items in search results: 59
Sorting results for welcome page processing
Query ran before retrieving live welcome versions - retrieving now
Live welcome versions:
Language ID: 1
Country ID: 239
Removing welcome pages that are not visible to the user
Final number of items in search results: 59
Parsing dates for sorting
Sorting results
Creating result list
Updating site names for visible results
Creating article headers for display and loading additional information
Search expression processing completed in 375ms</pre>
<p>As you can see, GetPublished does a lot more than just run the search query. The reason it does so is that it needs to convert the search results - a list of version records - to a list of articles the user can see. Here are some of the things that affect the visibility of articles and versions:</p>
<ol>
<li>Articles can have multiple versions, but only one version per article can be "live" (that is, visible to users).
<li>Articles can be mapped to multiple sites, and have different publishing and expiration dates on each site.
<li>GetPublished supports "staging sites", that use a different set of versions.
<li>Articles are filtered based on the user&#8217;s <a href="http://dn.codegear.com/article/33608">preferred language</a>.
<li>Certain articles may only be visible in <a href="http://blogs.teamb.com/yaminov/2008/04/25/select-your-location/">specific countries or regions</a>.
<li>Articles of a special type, known as a "welcome page", are shown on specific site areas instead of in article lists. On such pages, only one "welcome page" can be visible.</li>
</ol>
<p>The list of results returned by the search web service is trimmed and expanded based on the search criteria, user preferences, and visibility settings:</p>
<ol>
<li>Versions that are not visible to the user are removed from the list.
<li>If an article is mapped to multiple sites that are included in the search, additional result records are created for each site.
<li>Welcome pages that are mapped to multiple area are stored once per site, but all valid links are stored in the result record to be displayed later.
<li>Of multiple welcome pages mapped to a single area, only the one visible by the user is kept.</li>
</ol>
<p>Many of these checks can run concurrently. For example, if the search engine takes a while to process the query, GetPublished retrieves all visible articles and welcome pages from the database. If the engine returns quickly, GetPublished only checks the database for versions that are included in the search results. Similarly, GetPublished tries to reduce the working result set as much as possible. For example, when sorting by site name, GetPublished has to set the site name of every result before sorting and paging. When sorting by other fields, GetPublished waits until the results are sorted and only sets the site name for results that are going to be displayed.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=40&amp;akst_action=share-this" onclick="akst_share('40', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F09%2F24%2Fcdn-search-part-3-search-results%2F', 'CDN+Search%2C+Part+3%3A+Search+Results'); return false;" title="Post to del.icio.us, etc." id="akst_link_40" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=CDN%20Search%2C%20Part%203%3A%20Search%20Results&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F09%2F24%2Fcdn-search-part-3-search-results%2F" id="akst_email_40" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Building a Generic Statistics Library, Part 5: Implementation</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/09/24/37838/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/09/24/37838/#comments</comments>
    <pubDate>Wed, 24 Sep 2008 12:55:45 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/09/24/37838</guid>
    <description><![CDATA[This post is the last in my series on building a statistics library using Delphi 2009’s new generic types.  Having implemented the functions FoldL and Map, and having used FoldL to implement Count and Sum, implementing Average and StandardDeviation are now trivial [...]]]></description>
      <content:encoded><![CDATA[<p>This post is the last in my series on building a statistics library using Delphi 2009’s new generic types.  If you’re new to the series, you might want to start with <a href="http://blogs.teamb.com/craigstuntz/2008/09/09/37833" title="Building a Generic Statistics Library, Part 1: Interface">the first post</a>. Having implemented the functions <a href="http://blogs.teamb.com/craigstuntz/2008/09/11/37836">FoldL</a> and <a href="http://blogs.teamb.com/craigstuntz/2008/09/17/37837">Map</a>, and having used FoldL to implement <a href="http://blogs.teamb.com/craigstuntz/2008/09/11/37836">Count and Sum</a>, implementing Average and StandardDeviation are now trivial:</p>
<blockquote>
<pre><code><strong>class function </strong>TStatistics&lt;T&gt;.Average(
  <strong>const </strong>AData: TEnumerable&lt;T&gt;;
  AAdder: TBinaryOp&lt;T&gt;;
  ADivider: TBinaryOp&lt;T&gt;;
  AExplicitCast: TFunc&lt;integer, T&gt;): T;
<strong>var</strong>
  Total, Num: T;
<strong>begin</strong>
  Total := Sum(AData, AAdder, AExplicitCast);
  Num := Count(AData, AAdder, AExplicitCast);
  Result := ADivider(Total, Num);
<strong>end</strong>;

<strong>class function </strong>TStatistics&lt;T&gt;.StandardDeviation(
  <strong>const </strong>AData: TEnumerable&lt;T&gt;;
  ADeviation, AAdder, ADivider:TBinaryOp&lt;T&gt;;
  ARoot, ASquare: TUnaryOp&lt;T&gt;;
  AExplicitCast: TFunc&lt;integer, T&gt;): T;
<strong>var</strong>
  Avg, Variance: T;
  SquaredDeviations: TEnumerable&lt;T&gt;;
<strong>begin</strong>
  Avg := Average(AData, AAdder, ADivider, AExplicitCast);
  SquaredDeviations := Map(
    <strong>function</strong>(AValue: T): T
    <strong>begin</strong>
      Result := ASquare(ADeviation(AValue, Avg));
    <strong>end</strong>,
    AData);
  <strong>try</strong>
    Variance := Average(SquaredDeviations, AAdder, ADivider, AExplicitCast);
    Result := ARoot(Variance);
  <strong>finally</strong>
    SquaredDeviations.Free;
  <strong>end</strong>;
<strong>end</strong>;
</code></pre>
</blockquote>
<p>You can download <a href="http://cc.codegear.com/item/26088" title="26088, Generic Statistics Demo">the complete project</a> from CodeCentral.</p>
<p>Even having to use functions like "AAdder" in place of the more conventional "+", I think the algorithm is still fairly easy to read here, at least if you understand the <a href="http://en.wikipedia.org/wiki/Standard_deviation">standard deviation</a>.  As <a href="http://blogs.teamb.com/craigstuntz/2008/09/17/37837#comment-3847">Raymond points out in comments to the previous post</a>, however, the syntax may not be familiar to see folks who have spent most of their time in older versions of Delphi.</p>
<p>I&#8217;m afraid you&#8217;re just going to have to get used to it.  Delphi is well behind the pack in getting support for anonymous methods, and in many environments it is difficult to get much done without them.  JavaScript comes to mind; the asynchronous nature of much of what you have to do in JavaScript <a href="http://marijn.haverbeke.nl/cps/" title="Continuation-Passing Style and why JavaScript developers might be interested in it">makes a continuation-passing style quite practical</a>.  Lambda expressions, which are, very roughly, a more concise version of an anonymous function, are required to do any useful work in LINQ.  In languages like Lisp and Haskell, all "lines" of code are (again, very roughly) functions, which are anonymous by default. Few mainstream languages don&#8217;t support this, and many environments leverage it heavily. If you don&#8217;t understand such syntax well, you will find it hard to work outside of Delphi, like a COBOL programmer who doesn&#8217;t understand OO. You aren&#8217;t required to like it, but you <strong>have</strong> to understand it.</p>
<blockquote>
<pre></pre>
</blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37838&amp;akst_action=share-this" onclick="akst_share('37838', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F09%2F24%2F37838%2F', 'Building+a+Generic+Statistics+Library%2C+Part+5%3A+Implementation'); return false;" title="Post to del.icio.us, etc." id="akst_link_37838" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Building%20a%20Generic%20Statistics%20Library%2C%20Part%205%3A%20Implementation&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F09%2F24%2F37838%2F" id="akst_email_37838" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>CDN Search, Part 2: Background Jobs</title>
    <link>http://blogs.teamb.com/yaminov/2008/09/23/cdn-search-part-2-background-jobs/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/09/23/cdn-search-part-2-background-jobs/#comments</comments>
    <pubDate>Tue, 23 Sep 2008 08:39:22 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[CDN]]></category>

		<category><![CDATA[GetPublished]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/09/23/cdn-search-part-2-background-jobs/</guid>
    <description><![CDATA[The previous post in this series described how GetPublished processes content and passes it to the Lucene index. I noted there was a problem with the final steps of the process, which were:

GetPublished indexes the content by calling the search web service.
GetPublished stores all data in the database.

The problem is that since we&#8217;re updating multiple [...]]]></description>
      <content:encoded><![CDATA[<p>The <a href="http://blogs.teamb.com/yaminov/2008/09/21/cdn-search-part-1-new-search-engine/">previous post</a> in this series described how GetPublished processes content and passes it to the Lucene index. I noted there was a problem with the final steps of the process, which were:</p>
<ol>
<li>GetPublished indexes the content by calling the search web service.
<li>GetPublished stores all data in the database.</li>
</ol>
<p>The problem is that since we&#8217;re updating multiple data stores (the Lucene index and GetPublished&#8217;s database), we have no way of controlling the entire process as a single transaction. Writing a distributed transaction manager and extending both GetPublished and Lucene to use it wasn&#8217;t really an option, but we needed a way to make sure the database and the Lucene index matched.</p>
<p>When faced with complex design decisions, it help to analyze the risks involved. Here&#8217;s my initial risk assessment. It estimates the risk of receiving incorrect search results for index-only and database-only failures (if both operations succeed or fail, the database and index match, and we have no problem). </p>
<table cellspacing="0" cellpadding="2" border="1">
<tbody>
<tr>
<td valign="top" width="133">&nbsp;</td>
<td valign="top" width="133">Index-only failure</td>
<td valign="top" width="133">Database-only failure</td>
</tr>
<tr>
<td valign="top" width="133">New content</td>
<td valign="top" width="133">Medium</td>
<td valign="top" width="133">None</td>
</tr>
<tr>
<td valign="top" width="133">Changed content</td>
<td valign="top" width="133">Low</td>
<td valign="top" width="133">High</td>
</tr>
<tr>
<td valign="top" width="133">Deleted content</td>
<td valign="top" width="133">None</td>
<td valign="top" width="133">High</td>
</tr>
</tbody>
</table>
<p>The risks are based on the following assumptions:</p>
<ol>
<li>Only content in the database is "real" - this is what users see.
<li>GetPublished rarely modifies existing content - most edits generate new versions.
<li>All search results have to be filtered for visibility by GetPublished.</li>
</ol>
<p>Based on these assumptions, we can determine that there&#8217;s generally little risk in index failures. That risk can be further mitigated by retrying to index later. On the other hand, database-only failures are usually a high risk, so we&#8217;d better find a way to avoid them. I therefore based the design on the following requirements:</p>
<ol>
<li>If we were unable to commit changes to the database, we must not update the index.
<li>If we were unable to update the index, we should retry later.</li>
</ol>
<p>The first part is easy: all we have to do is make sure all processing is wrapped in a database transaction. Only if the transaction is successfully committed, can we index the content. By only reading committed data and running the indexing code outside the content processing transaction we can make sure we&#8217;re only indexing successfully committed data.</p>
<p>The second part is the real problem. Once data is committed, we have to try to index it. But what if we can&#8217;t? We can&#8217;t keep trying indefinitely - we need to respond to user requests. So, we need to run the indexing request in another thread, one that can keep trying while we return control to the user.</p>
<p>Background threads are a particular problem in web applications. Web applications usually only live for the duration of a single request. The web server software (IIS, in GetPublished&#8217;s case) can - and will - terminate the process, including background thread, at any time. Additional complications arise from GetPublished&#8217;s distributed architecture and ASP.NET&#8217;s application model. GetPublished is designed to run on multiple servers concurrently (web farm). ASP.NET applications run in application pools, which may be recycled (manually by administrators, or automatically by the server or external monitoring tools), terminating all running threads.</p>
<p>GetPublished solves this problem by implementing a system of background jobs. Instead of arbitrary threads, jobs are special classes that can be tracked and monitored by GetPublished. Since the application runs on multiple servers, and can be restarted at any time, jobs are stored in the database. When GetPublished starts, it creates a job monitoring thread, whose job is to periodically check the database and start job threads as necessary:</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="251" alt="Background Jobs" src="http://blogs.teamb.com/files/2008/09/backgroundjobs_787.png" width="531" border="0"> </p>
<p>Requests that require processing that may take longer than a normal web request can use background jobs. Instead of spawning worker threads, requests can create job records in the database. The job monitoring thread will then pick up the request and spawn a worker thread next time it checks the database. GetPublished even lets administrators monitor, stop, and restart running jobs:</p>
<p><a href="http://blogs.teamb.com/files/2008/09/clip-image002_789.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="58" alt="Job Monitoring View" src="http://blogs.teamb.com/files/2008/09/clip-image002-thumb_791.jpg" width="640" border="0"></a></p>
<p>Using background jobs, we can now change the article submission process:</p>
<p><a href="http://blogs.teamb.com/files/2008/09/submittransactional_793.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="480" alt="Transactional submission process" src="http://blogs.teamb.com/files/2008/09/submittransactional-thumb_795.png" width="614" border="0"></a> </p>
<p>The indexing job is created as part of the same transaction that stores the content. This means the job will only run if the data has been successfully committed. The job calls the web service to index the content, and can safely retry the operation if necessary without blocking the user.</p>
<p>So far, we&#8217;ve covered indexing. That&#8217;s only half the job of a search engine. <a href="http://blogs.teamb.com/yaminov/2008/09/24/cdn-search-part-3-search-results/">Next time</a>, I&#8217;ll describe the actual search.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=39&amp;akst_action=share-this" onclick="akst_share('39', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F09%2F23%2Fcdn-search-part-2-background-jobs%2F', 'CDN+Search%2C+Part+2%3A+Background+Jobs'); return false;" title="Post to del.icio.us, etc." id="akst_link_39" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=CDN%20Search%2C%20Part%202%3A%20Background%20Jobs&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F09%2F23%2Fcdn-search-part-2-background-jobs%2F" id="akst_email_39" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>CDN Search, Part 1: New Search Engine</title>
    <link>http://blogs.teamb.com/yaminov/2008/09/21/cdn-search-part-1-new-search-engine/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/09/21/cdn-search-part-1-new-search-engine/#comments</comments>
    <pubDate>Sun, 21 Sep 2008 15:29:36 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[CDN]]></category>

		<category><![CDATA[GetPublished]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/09/21/cdn-search-part-1-new-search-engine/</guid>
    <description><![CDATA[A few days ago we deployed a new search engine on all major CodeGear sites. At the heart of the engine is the Apache Lucene library, which I highly recommend. We&#8217;ll be providing more information about our overall implementation in the near future (update: John Kaster published an article about this), but I wanted to [...]]]></description>
      <content:encoded><![CDATA[<p>A few days ago we deployed a <a href="http://dn.codegear.com/article/38720">new search engine</a> on all major CodeGear sites. At the heart of the engine is the <a href="http://lucene.apache.org/java/docs/">Apache Lucene</a> library, which I highly recommend. We&#8217;ll be providing more information about our overall implementation in the near future (update: John Kaster published <a href="http://dn.codegear.com/article/38723">an article about this</a>), but I wanted to discuss some of the implementation details specific to GetPublished. There&#8217;s a lot to cover, so I&#8217;ll post this as a multi-part series.</p>
<p>The previous search engine was based on keywords rather the full-text, and had several limitations:</p>
<ul>
<li>The keyword parser did not correctly handle Unicode text, particularly east-Asian languages.
<li>Lack of a full-text index prevented phrase and proximity searches, and did not allow correct scoring of search results.
<li>The use of multiple databases by CDN applications prevented unified searches across all web sites.
<li>It was slow.</li>
</ul>
<p>Obviously, the engine needed to be replaced. We&#8217;ve looked at several search engines in the past, but didn&#8217;t find one that matched our needs. We started rewriting our parser, but decided to take another look at the latest version of Lucene - and were pleasantly surprised. Lucene seemed more than capable of handling our needs, and since it is open source, we knew we could tweak it if necessary.</p>
<p>The first problem we needed to solve was how to integrate the Lucene index into our applications. CDN applications are written in several languages (Delphi, Java, C#, and PHP), run on multiple platforms (Native Windows, ASP.NET, and Linux), and use several databases (InterBase, Blackfish SQL, Oracle, and Microsoft SQL Server). In addition, most CDN applications run on multiple load-balanced application servers.</p>
<p>One solution would have been to let Lucene access our databases directly. This would have involved setting up special tables that match the index structure, and maintaining application-specific information on the indexing server. For multiple applications and databases, this can become a serious headache. Instead, we wrapped the search engine in a web service. Each application already controls its content, and notifies the search engine of content changes - indexing new content, re-indexing updated content, and removing deleted content:</p>
<p><a href="http://blogs.teamb.com/files/2008/09/luceneservice_779.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="165" alt="Search web service" src="http://blogs.teamb.com/files/2008/09/luceneservice-thumb_781.png" width="640" border="0"></a> </p>
<p>Next, we had to decide what constitutes a "document" in the index. A document is a single entry, identified by a unique ID, that can be return as a search result. A single document can have multiple fields, but is included no more than once in search results. Each CDN application has a different concept of a document, which may or may not correspond to what users may consider a single piece of content. Here&#8217;s what we came up with:</p>
<ul>
<li>For blogs, a single blog post is a document.
<li>For CodeCentral, both a complete submission and a single source code file within a submission are considered documents. They are indexed using different IDs, so we can search for submissions, source code, or both.
<li>For GetPublished, a single version of an article is considered a document. GetPublished articles can have multiple versions, and GetPublished uses a complex set of rules to determine actual content visibility on its sites. Instead of indexing all possible visibility combinations, we index each version once, and let GetPublished convert search results into a set of articles visible to the user.
<li>For QualityCentral, a single report is a document.</li>
</ul>
<p>GetPublished uses <a href="http://blogs.teamb.com/yaminov/2008/05/02/document-adapters/">DocAdapter</a> to process submitted files and convert them into HTML articles. Among other things, DocAdapter extracts source code snippets from the submitted document and uses <a href="http://lingua.codegear.com/yapp/">YAPP</a> to <a href="http://dn.codegear.com/article/34095">automatically syntax-highlight</a> them. Since DocAdapter already knew how to extract source code from an article, it was fairly simple to extend the code to return the original snippets to GetPublished, so they could be indexed by Lucene.</p>
<p>Here is what happens when a user submits an article to GetPublished:</p>
<p><a href="http://blogs.teamb.com/files/2008/09/submitworkflow_783.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="384" alt="Article submission processing" src="http://blogs.teamb.com/files/2008/09/submitworkflow-thumb_785.png" width="640" border="0"></a> </p>
<p>Roughly, the steps are:</p>
<ol>
<li>GetPublished checks the submitted files and form fields and generates the necessary data for the article (for example, a unique article ID for a new article).
<li>GetPublished then sends the content to DocAdapter for processing.
<li>DocAdapter converts the content to HTML, and extracts all code snippets.
<li>Each code snippet is stored, then sent to YAPP for syntax highlighting.
<li>DocAdapter merges the syntax-highlighted snippets into the final HMTL.
<li>DocAdapter returns the merged HTML, all source code snippets, and any additional required information to GetPublished.
<li>GetPublished indexes the content by calling the search web service.
<li>GetPublished stores all data in the database.</li>
</ol>
<p>You&#8217;ll notice I painted the line from GetPublished to the web service red. This is because there&#8217;s a problem here: the process I just describes only works when there&#8217;s no error. If either step 7 (indexing) or step 8 (data storage) fails, we&#8217;re left with inconsistent data.</p>
<p>One possible solution would be to switch steps 7 and 8. After we store the data (and commit the transaction) successfully, we can safely call the web service, knowing we&#8217;re indexing valid content. This still doesn&#8217;t solve the problem of index failure: if the web service call then fails, we&#8217;re left with new content that&#8217;s not indexed.</p>
<p>Another option is to roll back the entire transaction if step 7 fails. This works in case of an indexing error, but doesn&#8217;t help us if indexing succeeded but the database commit failed. Once again, the database and index won&#8217;t match.</p>
<p>Since we don&#8217;t have distributed transactions with the Lucene index, what we need is a way to tie an indexing request to a successful commit, and the ability to ensure the indexing request succeeds - or at least, notify an administrator if there&#8217;s a problem.</p>
<p>In my <a href="http://blogs.teamb.com/yaminov/2008/09/23/cdn-search-part-2-background-jobs/">next post</a>, I&#8217;ll describe how GetPublished accomplishes this task.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=33&amp;akst_action=share-this" onclick="akst_share('33', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F09%2F21%2Fcdn-search-part-1-new-search-engine%2F', 'CDN+Search%2C+Part+1%3A+New+Search+Engine'); return false;" title="Post to del.icio.us, etc." id="akst_link_33" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=CDN%20Search%2C%20Part%201%3A%20New%20Search%20Engine&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F09%2F21%2Fcdn-search-part-1-new-search-engine%2F" id="akst_email_33" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Building a Generic Statistics Library, Part 4: Map</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/09/17/37837/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/09/17/37837/#comments</comments>
    <pubDate>Wed, 17 Sep 2008 23:11:55 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/09/17/37837</guid>
    <description><![CDATA[It&#8217;s been a busy week here in Columbus, what with the highest wind speeds ever recorded in the city and no power in my house — or 1/2 million others — since Sunday.  But don&#8217;t feel too bad for me; a lot of people have it worse. Anyway, this will be a fairly short post.
This [...]]]></description>
      <content:encoded><![CDATA[<p>It&#8217;s been a busy week here in Columbus, what with the highest wind speeds ever recorded in the city and no power in my house — <a href="http://www.dispatch.com/live/content/local_news/stories/2008/09/16/stormfollow.ART_ART_09-16-08_A1_KPBBBMU.html?sid=101" title="Some power back; Columbus schools will stay closed Wednesday">or 1/2 million others</a> — since Sunday.  But don&#8217;t feel too bad for me; <a href="http://www.boston.com/bigpicture/2008/09/the_short_but_eventful_life_of.html" title="The short - but eventful - life of Ike">a lot of people have it worse</a>. Anyway, this will be a fairly short post.</p>
<p>This post is the fourth in my series on building a statistics library using Delphi 2009&#8217;s new generic types.  If you&#8217;re new to the series, you might want to start with <a href="http://blogs.teamb.com/craigstuntz/2008/09/09/37833" title="Building a Generic Statistics Library, Part 1: Interface">the first post</a>.  Today I&#8217;m going to discuss the second higher-order function that the library uses internally, <a href="http://en.wikipedia.org/wiki/Map_(higher-order_function)">Map</a>.</p>
<p>Map is a function which takes a list, and a function which operates on individual items in the list, and returns a new list, formed by executing the function against each entry in the original list.  For example, suppose I had this list of integers:</p>
<blockquote><p>1, 2, 3, 4, 5</p></blockquote>
<p>Now let&#8217;s say that I call Map, passing this list, and the function Inc(). The result would be this list:</p>
<blockquote><p>2, 3, 4, 5, 6</p></blockquote>
<p>Don&#8217;t confuse Map with functions like jQuery&#8217;s <a href="http://docs.jquery.com/Core/each">each</a> which merely iterate the list and call a passed function without returning a new list.  That&#8217;s a different kind of function.</p>
<p>To calculate the standard deviation of a list, I first need to create a list of the squares of the deviations of each entry in the list. Later, I will perform additional calculations to compute the standard deviation, but first I need this list.  Here&#8217;s how I do it, using Map:</p>
<blockquote>
<pre><code>  SquaredDeviations := Map(<strong>function</strong>(AValue: T): T
    <strong>begin</strong>
      Result := ASquare(ADeviation(AValue, Avg));
    <strong>end</strong>,
    AData);
    // [...]
</code></pre>
</blockquote>
<p>The anonymous function I pass as an argument to Map computes the <a href="http://mathworld.wolfram.com/Deviation.html">deviation</a> of the individual item it is passed, squares it, and returns a value.  This anonymous function is called once for each item in the original list. And here is the implementation of Map itself:</p>
<blockquote>
<pre><code><strong>class function </strong>TStatistics&lt;T&gt;.Map(
  AFunc: TUnaryOp&lt;T&gt;;
  <strong>const </strong>AData: TEnumerable&lt;T&gt;): TEnumerable&lt;T&gt;;
<strong>var</strong>
  Current: T;
  NewList: TList&lt;T&gt;;
<strong>begin</strong>
  NewList := TList&lt;T&gt;.Create;
  <strong>for </strong>Current <strong>in </strong>AData <strong>do begin</strong>
    NewList.Add(AFunc(Current));
  <strong>end</strong>;
  Result := NewList;
<strong>end</strong>;
</code></pre>
</blockquote>
<p>Note that I have Map returning a new instance.  It is behaving as a constructor of sorts.  Indeed, it might make sense to have a constructor of this style on a list type. You could also write a version of Map which accepted an entity list to use as the result if it makes your lifetime management easier.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37837&amp;akst_action=share-this" onclick="akst_share('37837', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F09%2F17%2F37837%2F', 'Building+a+Generic+Statistics+Library%2C+Part+4%3A+Map'); return false;" title="Post to del.icio.us, etc." id="akst_link_37837" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Building%20a%20Generic%20Statistics%20Library%2C%20Part%204%3A%20Map&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F09%2F17%2F37837%2F" id="akst_email_37837" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
</channel>
</rss>
<!-- 453 queries 3.038 seconds. -->
