<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/wordpress-mu-1.2.3-2.2.1" -->
<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>Wed, 14 May 2008 20:54:08 +0000</pubDate>
  <generator>http://wordpress.org/?v=wordpress-mu-1.2.3-2.2.1</generator>
  <language>en</language>
  <item>
    <title>Covariant and Contravariant Subtyping In the .NET 2.0 CLR</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/05/14/37818/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/05/14/37818/#comments</comments>
    <pubDate>Wed, 14 May 2008 20:54:08 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[C#]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/05/14/37818</guid>
    <description><![CDATA[Danny Thorpe used to say that he was very much interested in things that the .NET CLR did which C# did not support. Examples include unmanaged Win32 exports and exception filters. One thing which had previously escaped my notice is covariant and contravariant subtyping of generic types, which was apparently introduced along with generics in [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.dannythorpe.com/">Danny Thorpe</a> used to say that he was very much interested in things that the .NET CLR did which C# did not support. Examples include unmanaged Win32 exports and exception filters. One thing which had previously escaped my notice is <a href="http://research.microsoft.com/~akenn/generics/FOOL2007.pdf" title="On Decidability of Nominal Subtyping with Variance">covariant and contravariant subtyping of generic types</a>, which was apparently introduced along with generics in the 2.0 CLR. C# does not presently have a syntax for this, although <a href="http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx" title="Eric Lippert's posts on covariance and contravariance">the team is talking about it</a>. Of course, some would question whether adding such support is such a good idea.  Steve Yegge proposes that <a href="http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html" title="Dynamic Languages Strike Back">dynamic languages are a better solution to the problem</a>.  Since I, when thinking about covariance and contravariance, have a hard time remembering which is which, and since I suspect that many programmers don&#8217;t understand them at all, I can sympathize with his position.</p>
<p>On an unrelated point, I enjoyed the Steve Yegge blog post that I referenced earlier.  There&#8217;s a lot of good stuff referenced there, and not just for users of dynamic languages.  He cites work on, for example, how to <a href="http://research.sun.com/self/papers/pldi94.ps.gz">make virtual method calls (nearly) as fast as static method calls</a>, it least in places where it counts. From a paper published in 1994.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37818&amp;akst_action=share-this" onclick="akst_share('37818', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F14%2F37818%2F', 'Covariant+and+Contravariant+Subtyping+In+the+.NET+2.0+CLR'); return false;" title="Post to del.icio.us, etc." id="akst_link_37818" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Covariant%20and%20Contravariant%20Subtyping%20In%20the%20.NET%202.0%20CLR&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F14%2F37818%2F" id="akst_email_37818" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Embarcadero</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/05/09/37817/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/05/09/37817/#comments</comments>
    <pubDate>Fri, 09 May 2008 13:38:23 +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/05/09/37817</guid>
    <description><![CDATA[The Embarcadero deal seems, from my outsider&#8217;s point of view, to be a great deal for CodeGear and for Embarcadero.  There are so many different ways that the two companies&#8217; products can work together that it just makes a great deal of sense to me. It&#8217;s less clear to me how it makes sense [...]]]></description>
      <content:encoded><![CDATA[<p>The Embarcadero deal seems, from my outsider&#8217;s point of view, to be a great deal for CodeGear and for Embarcadero.  There are so many different ways that the two companies&#8217; products can work together that it just makes a great deal of sense to me. It&#8217;s less clear to me how it makes sense for Borland, but that&#8217;s their problem.  I&#8217;m curious about one thing, though.  Embarcadero is, at present, a database tools vendor.  With their purchase of CodeGear, they are acquiring two fine databases: InterBase and Blackfish SQL.  Thus far, they&#8217;ve said very little about their intentions for these products, at least relative to what they&#8217;ve said about other CodeGear tools.  Again, it seems like a great fit for Embarcadero&#8217;s product line; there&#8217;s lots of ways this could make sense.  But I&#8217;d be interested to know what their plans are.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37817&amp;akst_action=share-this" onclick="akst_share('37817', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F09%2F37817%2F', 'Embarcadero'); return false;" title="Post to del.icio.us, etc." id="akst_link_37817" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Embarcadero&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F09%2F37817%2F" id="akst_email_37817" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Add a Feature, Write an Article</title>
    <link>http://blogs.teamb.com/yaminov/2008/05/06/add-a-feature-write-an-article/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/05/06/add-a-feature-write-an-article/#comments</comments>
    <pubDate>Tue, 06 May 2008 18:21:37 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/05/06/add-a-feature-write-an-article/</guid>
    <description><![CDATA[I just implemented support for client-side caching for the CodeGear sites. Here&#8217;s how it works:
Enabling Client-Side Caching of Generated Content in ASP.NET.
]]></description>
      <content:encoded><![CDATA[<p>I just implemented support for client-side caching for the CodeGear sites. Here&#8217;s how it works:</p>
<p><a href="http://dn.codegear.com/article/38123">Enabling Client-Side Caching of Generated Content in ASP.NET</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=22&amp;akst_action=share-this" onclick="akst_share('22', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F05%2F06%2Fadd-a-feature-write-an-article%2F', 'Add+a+Feature%2C+Write+an+Article'); return false;" title="Post to del.icio.us, etc." id="akst_link_22" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Add%20a%20Feature%2C%20Write%20an%20Article&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F05%2F06%2Fadd-a-feature-write-an-article%2F" id="akst_email_22" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>If You Use OnUpdate, Your Code Must Be Perfect</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/05/05/37816/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/05/05/37816/#comments</comments>
    <pubDate>Mon, 05 May 2008 15:04:13 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/05/05/37816</guid>
    <description><![CDATA[I've never particularly liked the idea of OnUpdate events. ]]></description>
      <content:encoded><![CDATA[<p>I&#8217;ve never particularly liked the idea of OnUpdate events.  They have always seemed kind of inelegant to me, but I haven&#8217;t talked about it much since I don&#8217;t really have a compelling argument against them, save for "bad smells."  Today, though, I was using RAD Studio and saw an access violation error in the IDE.  This was immediately followed by the following error, which repeated over and over again.  The stack dump tells the story:</p>
<blockquote><p>[20A635EB]{coreide100.bpl} DocModul.AnyModuleModified (Line 3466, "DocModul.pas" + 10) + $41<br />
[20A635E5]{coreide100.bpl} DocModul.AnyModuleModified (Line 3466, "DocModul.pas" + 10) + $3B<br />
<strong>[00419D8B]{bds.exe} AppMain.TAppBuilder.FileSaveAllActionUpdate (Line 4067, "ui\AppMain.pas" + 1) + $0</strong><br />
[200401A7]{rtl100.bpl  } Classes.TBasicAction.SetOnExecute (Line 11109, "common\Classes.pas" + 9) + $9<br />
[201513B1]{vcl100.bpl  } Forms..TScrollBox + $231<br />
[2004009D]{rtl100.bpl  } Classes.TBasicAction.Destroy (Line 11048, "common\Classes.pas" + 2) + $5<br />
[2013D8C7]{vcl100.bpl  } Controls.TControl.ScaleConstraints (Line 4033, "Controls.pas" + 12) + $7<br />
[2015E854]{vcl100.bpl  } Forms.DoPosition (Line 6778, "Forms.pas" + 44) + $2<br />
[2015E86E]{vcl100.bpl  } Forms.DoPosition (Line 6778, "Forms.pas" + 44) + $1C<br />
[2015E8DC]{vcl100.bpl  } Forms.DoAlign (Line 6795, "Forms.pas" + 0) + $4<br />
[201631AA]{vcl100.bpl  } Clipbrd.TClipboard.AssignPicture (Line 386, "Clipbrd.pas" + 7) + $14<br />
[201632F9]{vcl100.bpl  } Clipbrd.TClipboard.SetAsHandle (Line 430, "Clipbrd.pas" + 0) + $9<br />
[20162637]{vcl100.bpl  } Forms.TCustomFormHelper.WriteGlassFrameBottom (Line 8945, "Forms.pas" + 2) + $0<br />
[2016291F]{vcl100.bpl  } Forms.TApplicationHelper.GetEnumAllWindowsOnActivateHint (Line 9087, "Forms.pas" + 0) + $3<br />
[0042297A]{bds.exe     } bds.bds (Line 195, "" + 7) + $7</p></blockquote>
<p>Note the line in bold.  Because this is an OnUpdate event, it&#8217;s going to repeat forever.  The user is trapped.  There is no chance to save your work, or to exit the IDE normally.  You have to end task.  Sure, this is a secondary error; it&#8217;s almost certainly the consequence of the preceding access violation, rather than a defect in the OnUpdate event itself.  But because that event is not robust enough to handle the consequences of the previous error, the user is trapped.</p>
<p>My conclusion is that OnUpdate event handlers are dangerous if they do not detect anything that could possibly go wrong with the references they use, and exit gracefully in that case.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37816&amp;akst_action=share-this" onclick="akst_share('37816', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F05%2F37816%2F', 'If+You+Use+OnUpdate%2C+Your+Code+Must+Be+Perfect'); return false;" title="Post to del.icio.us, etc." id="akst_link_37816" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=If%20You%20Use%20OnUpdate%2C%20Your%20Code%20Must%20Be%20Perfect&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F05%2F37816%2F" id="akst_email_37816" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>New Delphi Blog</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/05/02/37815/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/05/02/37815/#comments</comments>
    <pubDate>Fri, 02 May 2008 14:47:16 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/05/02/37815</guid>
    <description><![CDATA[ MelanderBlog is the home of Anders Melander, who, among other things, developed the TGIFImage component included with Delphi 2007. This site includes a number of useful Delphi components.
]]></description>
      <content:encoded><![CDATA[<p> <a href="http://melander.dk/">MelanderBlog</a> is the home of Anders Melander, who, among other things, developed the TGIFImage component included with Delphi 2007. This site includes a number of <a href="http://melander.dk/download/">useful Delphi components</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37815&amp;akst_action=share-this" onclick="akst_share('37815', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F02%2F37815%2F', 'New+Delphi+Blog'); return false;" title="Post to del.icio.us, etc." id="akst_link_37815" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=New%20Delphi%20Blog&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F02%2F37815%2F" id="akst_email_37815" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Document Adapters</title>
    <link>http://blogs.teamb.com/yaminov/2008/05/02/document-adapters/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/05/02/document-adapters/#comments</comments>
    <pubDate>Fri, 02 May 2008 10:10:48 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[GetPublished]]></category>

		<category><![CDATA[CDN]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/05/02/document-adapters/</guid>
    <description><![CDATA[One of the core elements of GetPublished is the Document Adapter, or DocAdapter. DocAdapter is a set of web services and .NET assemblies for converting rich documents into standard HTML articles that can be displayed on the CodeGear Developer Network sites. By using DocAdapter, we can accept articles in multiple formats, and ensure we get [...]]]></description>
      <content:encoded><![CDATA[<p>One of the core elements of <a href="http://gp.codegear.com">GetPublished</a> is the Document Adapter, or <strong>DocAdapter</strong>. DocAdapter is a set of web services and .NET assemblies for converting rich documents into standard HTML articles that can be displayed on the CodeGear Developer Network sites. By using DocAdapter, we can accept articles in multiple formats, and ensure we get valid HTML that works with the site&#8217;s overall look and feel.</p>
<p>DocAdapter is accessible in two ways: as a set of web services and as a set of .NET assemblies/Delphi packages. The web services and assemblies reference each other (the web service calls the assemblies to perform its tasks, and the assemblies can reference the web service to perform their tasks remotely). Because the web service and the assemblies know each other, we don&#8217;t have to worry about type matching (making sure the types used by the web service match those used by the assemblies).</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="256" alt="DocAdapter" src="http://blogs.teamb.com/files/2008/05/docadapter_437.png" width="600" border="0"> </p>
<p>Client applications can use either technology, or both. GetPublished, for example, uses the DocAdapter web service to perform the conversion from the source format to XHTML, and the CDN.Documents assembly to generate HTML, thumbnails, and other document elements.</p>
<h1></h1>
<h3>Format Conversion</h3>
<p>The CDN.DocumentConverters assembly (and its web service wrapper, cleverly titled DocAdapterService) contains conversion classes capable of reading files in several formats. The classes convert document text to XHTML, which is a convenient format for additional processing. Depending on the format, they can also extract additional data. For example, the Word conversion class extracts embedded images from Word documents, stores them as separate files, and creates &lt;img&gt; elements in the XHTML that refer to these files. A conversion class is any implementation of the <strong>IDocumentImport</strong> interface:</p>
<pre>IDocumentImport = <code>interface</code>
  <code>procedure</code> Import(inputStream: Stream; docAdapter: DocumentAdapter;
    extractFields: Boolean);
<code>end</code>;
</pre>
<p>Because we&#8217;re using an interface, the <strong>DocumentAdapter</strong> class doesn&#8217;t need to know anything about the conversion class other than the fact it implements the interface. This means we can implement converters without recompiling the CDN.Documents assembly, and add them as plug-ins to the calling application.</p>
<p>The <strong>WebServiceConversion</strong> class is a special implementation of the <strong>IDocumentImport</strong> interface that calls DocAdapter web services. All DocAdapter services are based on the same definition, expressed in WSDL. All a client application needs in order to convert a document to XHTML to to pass the URL of such a web service to the <strong>WebServiceConversion</strong> class. GetPublished stores the URLs of the DocAdapter services in the database, so new formats can be supported by simply deploying a web service and adding a single record to GetPublished&#8217;s database.</p>
<h3>Document Processing</h3>
<p>Once the text and images are extracted, DocAdapter can create the HTML and necessary supporting files that can be displayed on a web site. This is done by calling a single method, <em>CreateDocumentArchive</em>, which returns a <strong>DocumentArchive</strong> object. The <strong>DocumentArchive</strong> object contains all the necessary information, such as the final HTML (including <a href="http://dn.codegear.com/article/34095">syntax highlighting</a>), all referenced images, thumbnails, a table of contents, keywords, and other information that may be useful. The generation of these elements is controlled by parameters passed to the <em>CreateDocumentArchive</em> method. Some of these parameters are:</p>
<ul>
<li>Maximum image width. Images wider than this value will be replaced by thumbnails that link to the full-size image.
<li>Maximum image height. Images taller than this value will be replaced by thumbnails that link to the full-size image.
<li>The width of thumbnail images generated for images wider than the maximum specified width or taller than the maximum specified height.
<li>Whether to keep embedded images in the final document (external image references remain unmodified).
<li>The depth of the table of content to generate.
<li>Whether to produce printer-friendly output, which doesn’t include JavaScript elements for dynamically hiding and showing images and sections.</li>
</ul>
<p>In GetPublished, most of these parameters are associated with specific content types configurable by system administrators.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=18&amp;akst_action=share-this" onclick="akst_share('18', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F05%2F02%2Fdocument-adapters%2F', 'Document+Adapters'); return false;" title="Post to del.icio.us, etc." id="akst_link_18" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Document%20Adapters&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F05%2F02%2Fdocument-adapters%2F" id="akst_email_18" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>CDN Technology Overview</title>
    <link>http://blogs.teamb.com/yaminov/2008/05/02/cdn-technology-overview/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/05/02/cdn-technology-overview/#comments</comments>
    <pubDate>Fri, 02 May 2008 06:35:29 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[GetPublished]]></category>

		<category><![CDATA[CDN]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/05/02/cdn-technology-overview/</guid>
    <description><![CDATA[In response to some questions in the newsgroups, I thought I&#8217;d write a short overview of the tools and technologies used to manage and display the CodeGear web site.
The CodeGear web site, as well as the Developer Network, the CodeGear Support site, and several other sites all run as part of a single application. This [...]]]></description>
      <content:encoded><![CDATA[<p>In response to some questions in the newsgroups, I thought I&#8217;d write a short overview of the tools and technologies used to manage and display the <a href="http://www.codegear.com/">CodeGear web site</a>.</p>
<p>The CodeGear web site, as well as the <a href="http://dn.codegear.com/">Developer Network</a>, the <a href="http://support.codegear.com/">CodeGear Support site</a>, and several other sites all run as part of a single application. This application is an ASP.NET 2.0 application, written in Delphi using <a href="http://www.codegear.com/products/radstudio">RAD Studio 2007</a>, and running on several load-balanced Windows servers.</p>
<p><a href="http://gp.codegear.com">GetPublished</a> is the content management system. It&#8217;s also an ASP.NET 2.0 application, written in Delphi. On the client side, we also have some JavaScript code. GetPublished does most of the heavy lifting - content management, author roles and permissions, workflow, support for multiple sites, languages, and locations, and all direct data access.</p>
<p>SiteCentral is the internal name of the presentation layer - the application that displays web pages when you go to any of the CodeGear sites. The application doesn&#8217;t access data directly - it uses GetPublished (in a .NET assembly) as its data access and processing layer. In addition to standard pages, such as article lists and article pages, SiteCentral includes a set of pluggable modules. A lot of stuff you see on the page, such as the table of contents, article ratings, and even actual content, is displayed by these modules, which are configurable in GetPublished by users with sufficient permissions.
<p>Content posted to the sites is processed by Document Adapters, which are pluggable modules capable of converting content in various formats to HTML that can be placed on the site. Document adapters are also written in Delphi, and are used as .NET assemblies and as a web service.
<p>The applications talk to other CDN services, such as the <a href="https://members.codegear.com/">membership</a> service to access user accounts and the digital signatures service to accept digital signatures for submitted content.
<p>Pages use a special template page class, which lets us separate the overall look and feel from both functional and content pages. The concept is similar to ASP.NET 2.0 master pages, but the implementation is different (mostly because we wrote it before .NET 2.0 was released), and in some ways, more flexible. For example, it&#8217;s very easy for us to replace the templates without recompiling the application.
<p>The pages also support localization, and localized strings are also managed independently of the application. In fact, we encourage community members to help in providing localized strings in their own language, and provide a tool for this. See <a href="http://dn.codegear.com/article/33873">http://dn.codegear.com/article/33873</a> for details.
<p>You can find some user-oriented documentation for the sites and application in the <a href="http://dn.codegear.com/help">Help area of the Developer Network</a>. I&#8217;ll also try to post more technical information here and/or on the Developer Network from time to time.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=15&amp;akst_action=share-this" onclick="akst_share('15', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F05%2F02%2Fcdn-technology-overview%2F', 'CDN+Technology+Overview'); return false;" title="Post to del.icio.us, etc." id="akst_link_15" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=CDN%20Technology%20Overview&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F05%2F02%2Fcdn-technology-overview%2F" id="akst_email_15" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Stupid PageControl Tricks</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/05/01/37814/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/05/01/37814/#comments</comments>
    <pubDate>Thu, 01 May 2008 18:26:36 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/05/01/37814</guid>
    <description><![CDATA[Most of the user interface for our Delphi applications is generated dynamically, at runtime.  When we display this dynamically-generated user interface in a page control, we don&#8217;t generate the user interface for each page until you first go to it.  This is for performance reasons, as there is some overhead to this, mostly [...]]]></description>
      <content:encoded><![CDATA[<p>Most of the user interface for our Delphi applications is generated dynamically, at runtime.  When we display this dynamically-generated user interface in a page control, we don&#8217;t generate the user interface for each page until you first go to it.  This is for performance reasons, as there is some overhead to this, mostly due to database access.</p>
<p>When we enabled XP themes for our applications, I started noticing a flashing on the screen the first time you went to each tab in the page control.  A little testing demonstrated that the gradient background of the tab was being rendered before the controls were created.</p>
<p>This turned out to be a fairly difficult problem to solve.  When the user changes tabs, I need to figure out to which tab they are changing, and create the controls for that tab if they are not already created.  In the TPageControl.OnChanging event, I don&#8217;t know to which tab the user is changing.  Unfortunately, both the TPageControl.OnChange and the TTabSheet.OnShow event occur after the background of the tab has already been painted.  I needed a way to render the controls, if necessary, in between these events, but after the tab to which the user is changing is already known.</p>
<p>After some rooting around in the VCL source code, I came up with the following solution.</p>
<blockquote>
<pre><code><strong>type</strong>
  TChangeToPageEvent = <strong>procedure </strong>(Sender: TObject; <strong>const </strong>APageIndex: Integer) <strong>of object</strong>;
  TChangeToEventPageControl = <strong>class</strong>(TPageControl)
  <strong>private</strong>
    FOnChangeToPage: TChangeToPageEvent;
    <strong>procedure </strong>DoOnChangeToPage(<strong>const </strong>APageIndex: Integer);
  <strong>protected</strong>
    <strong>procedure </strong>Change; <strong>override</strong>;
  <strong>public</strong>
    <strong>property </strong>OnChangeToPage: TChangeToPageEvent <strong>read </strong>FOnChangeToPage <strong>write </strong>FOnChangeToPage;
  <strong>end</strong>;

<em>{ TChangeToEventPageControl }</em>

<strong>procedure </strong>TChangeToEventPageControl.Change;
<strong>begin</strong>
  DoOnChangeToPage(TabIndex);
  <strong>inherited</strong>;
<strong>end</strong>;

<strong>procedure </strong>TChangeToEventPageControl.DoOnChangeToPage(<strong>const </strong>APageIndex: Integer);
<strong>begin</strong>
  <strong>if </strong>Assigned(FOnChangeToPage) <strong>then begin</strong>
    FOnChangeToPage(Self, APageIndex);
  <strong>end;</strong>
<strong>end</strong>;</code></pre>
</blockquote>
<p>Since I also create the page control itself dynamically, I don&#8217;t even have to install this on the component palette to make it work.  Handling the OnChangeToPage event allows me to create the controls when the page to which the user is changing is known, but before the tab itself renders.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37814&amp;akst_action=share-this" onclick="akst_share('37814', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F01%2F37814%2F', 'Stupid+PageControl+Tricks'); return false;" title="Post to del.icio.us, etc." id="akst_link_37814" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Stupid%20PageControl%20Tricks&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F05%2F01%2F37814%2F" id="akst_email_37814" 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 Membership</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/04/29/37813/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/04/29/37813/#comments</comments>
    <pubDate>Tue, 29 Apr 2008 15:20:50 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

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

		<category><![CDATA[.NET]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/04/29/37813</guid>
    <description><![CDATA[One of my disappointments with Ruby on Rails is that it provides no support whatsoever for site logins/membership, which I consider to be a fundamental part of many database-driven websites. Of course, the Rails community has responded — and responded, and responded, and responded — to this need.  The Rails wiki notes that there [...]]]></description>
      <content:encoded><![CDATA[<p>One of my disappointments with Ruby on Rails is that it provides no support whatsoever for site logins/membership, which I consider to be a fundamental part of many database-driven websites. Of course, the Rails community has responded — and responded, and responded, and responded — to this need.  The Rails wiki notes that there are about a "<a href="http://wiki.rubyonrails.org/rails/pages/Authentication" title="Ruby on Rails Authentication">gazillion</a>" different systems for solving this problem in Rails. I&#8217;ve tried acts_as_authenticated, which does work, but, at least at the time I tried it, required quite a bit of manual tweaking and patching to get it going.</p>
<p>ASP.NET 2.0 and higher, on the other hand, includes a standard membership framework which is sufficiently extensible that I&#8217;ve never seen an application which it couldn&#8217;t be adapted to fit, and, for most applications, it will work right out of the box.</p>
<p>The usual way to configure page access rights for the ASP.NET membership (in web.config), however, isn&#8217;t really applicable to the new <a href="http://www.asp.net/downloads/3.5-extensions/">MVC framework</a>. <a href="http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx" title="ASP.NET MVC Framework (Part 1)">Scott Guthrie had promised to cover this subject</a>, but it was Rob Conery who <a href="http://blog.wekeroad.com/blog/aspnet-mvc-securing-your-controller-actions/" title="ASP.NET MVC: Securing Your Controller Actions">finally delivered the goods</a>. In short, you decorate your controller actions with attributes specifying whether the current user must be logged in, or be within a certain role, and a controller filter handles the work of validating those security assertions at runtime. <a href="http://www.squaredroot.com/post/2008/04/MVC-Membership-Starter-Kit.aspx">Troy Goode built upon Rob&#8217;s original code</a>, producing the <a href="http://www.codeplex.com/MvcMembership">ASP.Net MVC Membership Starter Kit</a>.</p>
<p>The Starter Kit includes a lot of really valuable code, but very little documentation, so I&#8217;m going to write out instructions for "getting started with the Starter Kit." I&#8217;m presuming that you&#8217;re going to use the SQL membership provider in this example, although the membership framework does include support for OpenID and Windows Live authentication as well.  You can, of course, use any authentication framework you care to.</p>
<ol>
<li>Download the full installer from the <a href="http://www.codeplex.com/MvcMembership/Release/ProjectReleases.aspx">Releases tab</a> at CodePlex. I&#8217;d also strongly recommend getting the source code download, which is available on the same page.</li>
<li>Run the installer.</li>
<li>If you&#8217;re using Visual Studio, you want to install the templates into VS.  There&#8217;s an item on your Start menu (in the "Starter Kits") folder which will do that.</li>
<li>If you are creating a brand-new site, you can start by just copying the sample project included with the download. Skip ahead to step 10.</li>
<li>If you are adding membership support to an existing project, there&#8217;s a few things you need to do. First, you need to reference the assembly you&#8217;ve just installed.  One way to do this is to simply reference the StarterKits.Mvc assembly in your project.  But I chose to add the source code for the StarterKits.Mvc project to my solution instead, which helps with debugging.</li>
<li>If you haven&#8217;t done so already, edit your web.config to include Forms authentication and set the Login URL, and specify a ConnectionString if you&#8217;re not using the default.  I&#8217;ll include an example of this below.  Note that you need to include a membership provider <em>and</em> a role provider.  Also, if you&#8217;re not using the default database, <a href="http://msdn2.microsoft.com/en-us/library/ms229862(VS.80).aspx">run aspnet_regsql.exe to add the required metadata to your database</a>.</li>
<li>You are not required to use the controllers or views supplied with the Starter Kit.  The filters in the Starter Kit will work fine with any controller you care to write.  However, it&#8217;s probably easiest, especially at the beginning, to use the supplied code.  If you&#8217;re using Visual Studio, you can do this with the templates you installed in step 3. Right click the Controllers folder in Solution Explorer, choose Add New Item, then choose MvcMembership Controllers FormsAuthenticationController. Do the same for FormsAuthenticationAdministrationController.  Right click the Views folder, and add both View templates.</li>
<li>The current release of the Starter Kit has <a href="http://www.codeplex.com/MvcMembership/WorkItem/View.aspx?WorkItemId=679">a bug where the codebehind and codegen files are not added along with the aspx files to the FormsAuthenticationAdministration views</a>.  This will be fixed in the next release (see <a href="http://blogs.teamb.com/craigstuntz/2008/04/29/37813#comment-3509">Troy Goode&#8217;s comment below</a> for details), but if you encounter this bug, I&#8217;ve included a workaround in my defect report.</li>
<li>You need to add a couple of lines to Global.asax in order to register the routes for the new controllers.  You can copy those from the sample project.</li>
<li>Your site should now work, but there are a few things you need to do in order to configure e-mail and the like.  These are indicated with TODO comments.  You can find these in the Task List.</li>
</ol>
<p>As promised, here is what you need to add to web.config to use a custom database.  I&#8217;ve omitted the connection string definition, which is specified like any other connection string.</p>
<blockquote>
<pre><code>&lt;authentication mode="Forms"&gt;
  &lt;forms loginUrl="/Login"/&gt;
&lt;/authentication&gt;
&lt;roleManager enabled="true"&gt;
  &lt;providers&gt;
    &lt;clear/&gt;
    &lt;add name="AspNetSqlRoleProvider" connectionStringName="MyConnectionString"
      applicationName="MyApp" type="System.Web.Security.SqlRoleProvider, System.Web,
      Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /&gt;
    &lt;/providers&gt;
&lt;/roleManager&gt;
&lt;membership defaultProvider="MySqlMembershipProvider"&gt;
  &lt;providers&gt;
    &lt;add name="MySqlMembershipProvider"
      type="System.Web.Security.SqlMembershipProvider"
      connectionStringName="MyConnectionString"
      enablePasswordRetrieval="false"
      enablePasswordReset="true"
      requiresQuestionAndAnswer="true"
      applicationName="MyApp"
      requiresUniqueEmail="true"
      passwordFormat="Hashed"
      maxInvalidPasswordAttempts="5"
      minRequiredPasswordLength="7"
      minRequiredNonalphanumericCharacters="1"
      passwordAttemptWindow="10"
      passwordStrengthRegularExpression=""/&gt;
    &lt;/providers&gt;
&lt;/membership&gt;</code></pre>
</blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37813&amp;akst_action=share-this" onclick="akst_share('37813', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F29%2F37813%2F', 'ASP.NET+MVC+Membership'); return false;" title="Post to del.icio.us, etc." id="akst_link_37813" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=ASP.NET%20MVC%20Membership&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F29%2F37813%2F" id="akst_email_37813" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Literate Programming</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/04/28/37812/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/04/28/37812/#comments</comments>
    <pubDate>Mon, 28 Apr 2008 21:03:50 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/04/28/37812</guid>
    <description><![CDATA[Andrew Binstock&#8217;s recent interview with Donald Knuth has received a lot of attention for his comments about unit testing, multicore, and other things of which Knuth is skeptical, but I was more interested in his comments on the topics which he endorses.  Knuth is the originator of (amongst many other things) literate programming.  [...]]]></description>
      <content:encoded><![CDATA[<p>Andrew Binstock&#8217;s recent <a href="http://www.informit.com/articles/article.aspx?p=1193856">interview with Donald Knuth</a> has received a lot of attention for his comments about unit testing, multicore, and other things of which Knuth is skeptical, but I was more interested in his comments on the topics which he endorses.  Knuth is the originator of (amongst many other things) <a href="http://en.wikipedia.org/wiki/Literate_programming">literate programming</a>.  One way to think about literate programming is that it turns the notion of commenting on its head.  In a traditional program, you use relatively few comments, and partition the comments with the limiters.  Literate programs are mostly English text, with compilable code delimited.</p>
<p>Knuth seems uncertain as to why literate programming hasn&#8217;t really taken off:</p>
<blockquote><p><a href="http://en.wikipedia.org/wiki/Jon_Bentley">Jon Bentley</a> probably hit the nail on the head when he once was asked why literate programming hasn’t taken the whole world by storm. He observed that a small percentage of the world’s population is good at programming, and a small percentage is good at writing; apparently I am asking everybody to be in both subsets.</p></blockquote>
<p>Well, sure, but even if one assumes that 1/10 of working programmers are decent at their job, and 1/10 of those can express themselves in English and a reasonably clear manner, that&#8217;s not really enough to account for the low use of literate code.  There are number of good bloggers and technical publication authors, and literate coding would seem to be well suited for these tasks. Maybe we just need some better examples to get the ball rolling.</p>
<p>You don&#8217;t have to read it many books on software development before you&#8217;ll encounter one with source code examples which produce erroneous results, or even fail to compile altogether.  It&#8217;s an absurdly common error.  <a href="http://www.boyet.com/Articles/WorstComputerBook.html">Taken to an extreme, it can be maddening</a>.  In the past month or so, I&#8217;ve been reading the preprints at <a href="http://www.mindviewinc.com/Books/CSharp/Index.php" title="C# Query Expressions and Supporting Features in C# 3.0">Bruce Eckel and Jamie King&#8217;s new book on LINQ</a>.  One interesting thing about this book is that in the process of writing it, the authors have developed a build system which builds all of the source code examples, including verifying the in-line assertions, and even goes so far as to ensure that the examples which are not supposed to build at all really do fail to compile.  The finished book may not be flawless, but the examples are going to work.</p>
<p>I think it&#8217;s a perfect application of literate programming; I cannot think of a better solution to this problem.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37812&amp;akst_action=share-this" onclick="akst_share('37812', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F28%2F37812%2F', 'Literate+Programming'); return false;" title="Post to del.icio.us, etc." id="akst_link_37812" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Literate%20Programming&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F28%2F37812%2F" id="akst_email_37812" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Select your location</title>
    <link>http://blogs.teamb.com/yaminov/2008/04/25/select-your-location/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/04/25/select-your-location/#comments</comments>
    <pubDate>Fri, 25 Apr 2008 05:56:56 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[CDN]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/04/25/select-your-location/</guid>
    <description><![CDATA[There&#8217;s more to the new web site than first meets the eye. One of the features we&#8217;ve added is making it much easier to buy CodeGear products online. If you look at the top-right corner of the page, you&#8217;ll see a bunch of icons, and a drop-down menu that let you select your location.
Selecting your [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://blogs.teamb.com/files/2008/04/image_408.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="160" alt="Buttons!" src="http://blogs.teamb.com/files/2008/04/image-thumb_410.png" width="247" align="right" border="0"></a>There&#8217;s more to the new <a href="http://www.codegear.com">web site</a> than first meets the eye. One of the features we&#8217;ve added is making it much easier to buy CodeGear products online. If you look at the top-right corner of the page, you&#8217;ll see a bunch of icons, and a drop-down menu that let you select your location.</p>
<p>Selecting your location is a Good Thing™ - when you click on the "buy" icon (the one that looks like a couple of credit cards), the site redirects you to the correct shop site for your selected location. If you&#8217;re logged in, the site uses your country selection from your <a href="https://members.codegear.com/editaccount.aspx">CDN account</a>, but you can override this setting by selecting a location from the menu. To go back to your account settings, select "My default location" from the menu.</p>
<p>The cool thing about these buttons is that they&#8217;re automatically generated based on a database of products, shop sites, and locations. Both the "download" and the "buy" buttons are generated based on where you are (physically and on the site). At least, I think it&#8217;s cool. Users don&#8217;t really case, but developers should appreciate how much cleaner this is than manually typing in links for each product page.</p>
<p>Anyway, getting the correct shop site is just one of many things the web site can do once you select your location. It can give you content specific to your location, for example. Other features will be made visible in the future, so make sure you set your location.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=14&amp;akst_action=share-this" onclick="akst_share('14', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F04%2F25%2Fselect-your-location%2F', 'Select+your+location'); return false;" title="Post to del.icio.us, etc." id="akst_link_14" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Select%20your%20location&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F04%2F25%2Fselect-your-location%2F" id="akst_email_14" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Automating SQL Server backup</title>
    <link>http://blogs.teamb.com/yaminov/2008/04/25/automating-sql-server-backup/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/04/25/automating-sql-server-backup/#comments</comments>
    <pubDate>Fri, 25 Apr 2008 05:20:08 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[GetPublished]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/04/25/automating-sql-server-backup/</guid>
    <description><![CDATA[As you may have noticed, the CodeGear web site has undergone significant changes. The new look has been applied to all CodeGear sites (including this one), but the site also has a lot of new and updated content. The new content has been staged in GetPublished, and once it was ready, all we had to [...]]]></description>
      <content:encoded><![CDATA[<p>As you may have noticed, the <a href="http://www.codegear.com">CodeGear web site</a> has undergone significant changes. The new look has been applied to all CodeGear sites (including this one), but the site also has a lot of new and updated content. The new content has been staged in <a href="http://gp.codegear.com">GetPublished</a>, and once it was ready, all we had to do was click a single button to replace all the content on the live site. We did, however, want to make sure we can revert all the changes if something goes horribly wrong, so we prepared a backup database server for "<a href="http://en.wikipedia.org/wiki/Hot_swapping">hot swapping</a>". Being programmers, we also wanted to automate that process, so we wrote a bunch of batch files to backup the database, copy it over to the new machine, and restore it (along with some other internal maintenance tasks). Here are slightly modified versions of these files, in case you ever need to do something similar:</p>
<p>1. <strong>Backup.sql</strong></p>
<p>This is the backup script. Because the GetPublished database is quite large, and is constantly being updated, the script creates two backups - a full database backup, and a transaction log backup. The log backup contains all transactions since the last full backup, so we can minimize downtime and data loss in case we have to take the live database offline and swap to the new server. The backup is verified, and displays progress. Replace "my_db" with your database name, and "D:\backup" with your backup directory:</p>
<pre>BACKUP DATABASE [my_db] TO  DISK = N'D:backupmy_db.bak'
  WITH  INIT ,  NOUNLOAD ,  NAME = N'my_db backup',  NOSKIP ,  STATS = 10,  NOFORMAT
DECLARE @i INT
select @i = position from msdb..backupset
where database_name='my_db' and type!='F' and
  backup_set_id=(select max(backup_set_id)
from msdb..backupset where database_name='my_db')
RESTORE VERIFYONLY
FROM   DISK = N'D:backupmy_db.bak'
WITH FILE = @i
GO

BACKUP LOG [my_db] TO  DISK = N'D:backupmy_db_log.bak'
  WITH  INIT ,  NOUNLOAD ,  NAME = N'my_db backup',  NOSKIP ,  STATS = 10,  NOFORMAT
DECLARE @i INT
select @i = position from msdb..backupset
where database_name='my_db'and type!='F' and
  backup_set_id=(select max(backup_set_id)
from msdb..backupset where database_name='my_db')
RESTORE VERIFYONLY
FROM   DISK = N'D:backupmy_db_log.bak'
WITH FILE = @i
GO
</pre>
<p>2. <strong>Backup.cmd</strong></p>
<p>This batch file simply runs the backup script:</p>
<pre>@echo Backup started at %time%
osql -S <em>server_name</em> -U <em>user_name</em> -P <em>password</em> -i backup.sql
@echo Backup completed at %time%</pre>
<p>Replace <em>server_name</em> with your database server name, <em>user_name</em> with the name of a database user with sufficient permissions to backup the database, and <em>password</em> with that user&#8217;s password (yes, I know that was pretty obvious). The nice thing about this batch file is that you can run it remotely. This allowed us to run everything in a single batch file on the "hot swap" machine.</p>
<p>3. <strong>Restore.cmd</strong></p>
<p>This batch file restores the database and log backups on the local machine, using Windows authentication (you can use the -S, -U, and -P parameters to provide a SQL Server user instead):</p>
<pre>@echo Restore started at %time%
osql -E -Q "RESTORE DATABASE [my_db] FROM DISK = 'D:backupmy_db.bak'
  WITH NORECOVERY;
  RESTORE LOG [my_db]
  FROM DISK = 'D:backupmy_db_log.bak' WITH RECOVERY;"
@echo Restore completed at %time%</pre>
<p>Note that the call to <strong>osql</strong> has to be in a single line. </p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=11&amp;akst_action=share-this" onclick="akst_share('11', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F04%2F25%2Fautomating-sql-server-backup%2F', 'Automating+SQL+Server+backup'); return false;" title="Post to del.icio.us, etc." id="akst_link_11" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Automating%20SQL%20Server%20backup&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F04%2F25%2Fautomating-sql-server-backup%2F" id="akst_email_11" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Two Updated Delphi Books</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/04/15/37811/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/04/15/37811/#comments</comments>
    <pubDate>Tue, 15 Apr 2008 13:32:57 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/04/15/37811</guid>
    <description><![CDATA[Bob Swart has updated two of his books: Delphi for Win32 VCL Database Development and Delphi 2007 for Win32 Development Essentials.
]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.drbob42.com/">Bob Swart</a> has updated two of his books: <a href="http://www.lulu.com/content/1165954">Delphi for Win32 VCL Database Development</a> and <a href="http://www.lulu.com/content/2064073">Delphi 2007 for Win32 Development Essentials</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37811&amp;akst_action=share-this" onclick="akst_share('37811', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F15%2F37811%2F', 'Two+Updated+Delphi+Books'); return false;" title="Post to del.icio.us, etc." id="akst_link_37811" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Two%20Updated%20Delphi%20Books&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F15%2F37811%2F" id="akst_email_37811" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>SQL-to-Code Macro</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/04/04/37810/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/04/04/37810/#comments</comments>
    <pubDate>Fri, 04 Apr 2008 14:48:40 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/04/04/37810</guid>
    <description><![CDATA[OK, I&#8217;m not trying to steal Joe White&#8217;s thunder here on Delphi macros, but when I plugged Joe&#8217;s series, I mentioned that I use Delphi macros for converting SQL created in a query analysis tool into Delphi constants, and commenter Jack asked for more details on this.  I thought it would make a better [...]]]></description>
      <content:encoded><![CDATA[<p>OK, I&#8217;m not trying to steal Joe White&#8217;s thunder here on Delphi macros, but when I plugged <a href="http://blog.excastle.com/tag/macros/">Joe&#8217;s series</a>, I mentioned that I use Delphi macros for converting SQL created in a query analysis tool into Delphi constants, and <a href="http://blogs.teamb.com/craigstuntz/2008/03/31/37808#comment-3451">commenter Jack asked</a> for more details on this.  I thought it would make a better post than comment.</p>
<p>The general idea is that we want to start with an SQL statement, like this:</p>
<blockquote>
<pre><code>SELECT
  *
FROM
  MY_TABLE;</code></pre>
</blockquote>
<p>&#8230;and turn it into a Delphi constant, like this:</p>
<blockquote>
<pre><code><b>const</b>
  MySQL = &#8216;SELECT &#8216;
        + &#8216;  * &#8216;
        + &#8216;FROM &#8216;
        + &#8216;  MY_TABLE;&#8217;;</code></pre>
</blockquote>
<p>The first step is to paste the SQL into the code at the appropriate place.  We need to type the non-repeating portion of the constant, and then paste in the SQL:</p>
<pre><code><b>const</b>
  MySQL = &#8216;SELECT
  *
FROM
  MY_TABLE;</code></pre>
<p>Now, record the macro:</p>
<ol>
<li>Press the End key to go to the end of the line</li>
<li>Press Ctrl+Shift+R to start recording</li>
<li>Type a space, then the closing single quote</li>
<li>Press the down arrow, then the Home key to go to the beginning of the next line</li>
<li>Type the appropriate whitespace, then a &#8216;+&#8217; sign (for string concatenation), then the open single quote character</li>
<li>Press the End key to go to the end of line, <a href="http://blog.excastle.com/2008/04/01/delphi-macro-power-tip-advance-last/" title="Advance last">to be ready for the next time the macro is played back</a></li>
<li>Press Ctrl+Shift+R to stop recording</li>
</ol>
<p>To use the macro, press and hold Ctrl+Shift+P. The keyboard auto-repeat who repeatedly play back the macro, formatting the rest of the query.  Don&#8217;t worry about going too far, since you can always press Ctrl+Z to undo if you do.  Since the final closing single quote and semicolon are different from how the rest of the lines are formatted, just type them.</p>
<p>By the way, the Delphi editor works really well for editing plain SQL.  If you are editing a file with the &#8216;. SQL&#8217; extension, it does syntax highlighting (and printing) for SQL.  You can also use macros like the one described above when creating your SQL or DDL.  For example, I often use macros to turn an <code>INSERT</code> statement into a <code>UPDATE</code> statement with parameters or trigger variable references, and similarly to turn a <code>SELECT</code> into a <code>CREATE VIEW</code> statement.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37810&amp;akst_action=share-this" onclick="akst_share('37810', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F04%2F37810%2F', 'SQL-to-Code+Macro'); return false;" title="Post to del.icio.us, etc." id="akst_link_37810" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=SQL-to-Code%20Macro&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F04%2F37810%2F" id="akst_email_37810" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>ADO.NET 2.0 Driver for InterBase</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/04/01/37809/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/04/01/37809/#comments</comments>
    <pubDate>Wed, 02 Apr 2008 03:02:46 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/04/01/37809</guid>
    <description><![CDATA[An ADO.NET 2.0 driver for InterBase is available for free download from the IB registered users page. Delphi users already have this; you only need it if you want to connect to IB from a .NET language other than Delphi and you don&#8217;t already own Delphi/RAD Studio.
]]></description>
      <content:encoded><![CDATA[<p>An ADO.NET 2.0 driver for InterBase is available for free download from the <a href="http://cc.codegear.com/reg/interbase">IB registered users page</a>. Delphi users already have this; you only need it if you want to connect to IB from a .NET language other than Delphi and you don&#8217;t already own Delphi/RAD Studio.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37809&amp;akst_action=share-this" onclick="akst_share('37809', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F01%2F37809%2F', 'ADO.NET+2.0+Driver+for+InterBase'); return false;" title="Post to del.icio.us, etc." id="akst_link_37809" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=ADO.NET%202.0%20Driver%20for%20InterBase&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F04%2F01%2F37809%2F" id="akst_email_37809" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Macro Tip: Don&#8217;t Be Afraid to Make Mistakes</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/31/37808/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/31/37808/#comments</comments>
    <pubDate>Mon, 31 Mar 2008 17:36:18 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/31/37808</guid>
    <description><![CDATA[Joe White is blogging about Delphi IDE macros, so I&#8217;ll throw in a useful tip: When recording a macro, it&#8217;s OK to make a mistake. Just type Ctrl+Z (Undo) or hit Backspace and retype what you were doing; the correction becomes part of the macro, and it&#8217;s a lot easier than re-recording the macro from [...]]]></description>
      <content:encoded><![CDATA[<p>Joe White is blogging about <a href="http://blog.excastle.com/tag/macros/">Delphi IDE macros</a>, so I&#8217;ll throw in a useful tip: When recording a macro, it&#8217;s OK to make a mistake. Just type Ctrl+Z (Undo) or hit Backspace and retype what you were doing; the correction becomes part of the macro, and it&#8217;s a lot easier than re-recording the macro from the start.</p>
<p>I use macros pretty heavily.  They&#8217;re handy for just about any bulk editing task. For example, I often use them when I write SQL in InterBase PLANalyzer, and then need to paste the SQL into source code.  I paste in the entire query, and then use macros to handle the quoting and string concatenation needed to turn the query statement into a valid source code, spanning several lines in the editor.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37808&amp;akst_action=share-this" onclick="akst_share('37808', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F31%2F37808%2F', 'Macro+Tip%3A+Don%27t+Be+Afraid+to+Make+Mistakes'); return false;" title="Post to del.icio.us, etc." id="akst_link_37808" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Macro%20Tip%3A%20Don%27t%20Be%20Afraid%20to%20Make%20Mistakes&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F31%2F37808%2F" id="akst_email_37808" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Buy Delphi, Get Marco Cantù&#8217;s Handbook Free</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/27/37807/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/27/37807/#comments</comments>
    <pubDate>Thu, 27 Mar 2008 20:01:50 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/27/37807</guid>
    <description><![CDATA[You asked for it; you got it. Buy D2007 and get the PDF version of Cantù&#8217;s Handbook free.
Update: "This offer expires March 31, 2008."
]]></description>
      <content:encoded><![CDATA[<p>You asked for it; <a href="http://blog.marcocantu.com/blog/Delphi2007_plus_handbook.html">you got it.</a> Buy D2007 and get the PDF version of Cantù&#8217;s <a href="http://www.marcocantu.com/dh2007/">Handbook</a> free.</p>
<p><strong>Update: </strong>"<font color="#000000"><span class="preorderText">This offer expires March 31, 2008."</span></font></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37807&amp;akst_action=share-this" onclick="akst_share('37807', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F27%2F37807%2F', 'Buy+Delphi%2C+Get+Marco+Cant%C3%B9%27s+Handbook+Free'); return false;" title="Post to del.icio.us, etc." id="akst_link_37807" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Buy%20Delphi%2C%20Get%20Marco%20Cant%C3%B9%27s%20Handbook%20Free&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F27%2F37807%2F" id="akst_email_37807" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Grammar Mistake of the Year (So Far)</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/25/37806/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/25/37806/#comments</comments>
    <pubDate>Tue, 25 Mar 2008 13:14:23 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/25/37806</guid>
    <description><![CDATA[From the index of the user manual to Nuance&#8217;s Dragon NaturallySpeaking 9:
possessives.  See apostrophe&#8217;s
(Why is this funny?)
I know. I&#8217;m amused easily.
]]></description>
      <content:encoded><![CDATA[<p>From the index of the user manual to Nuance&#8217;s Dragon NaturallySpeaking 9:</p>
<blockquote><p>possessives.  <em>See </em>apostrophe&#8217;s</p></blockquote>
<p>(<a href="http://www.angryflower.com/bobsqu.gif">Why is this funny?</a>)</p>
<p>I know. I&#8217;m amused easily.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37806&amp;akst_action=share-this" onclick="akst_share('37806', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F25%2F37806%2F', 'Grammar+Mistake+of+the+Year+%28So+Far%29'); return false;" title="Post to del.icio.us, etc." id="akst_link_37806" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Grammar%20Mistake%20of%20the%20Year%20%28So%20Far%29&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F25%2F37806%2F" id="akst_email_37806" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Solution to Crossword No. 1</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/24/37805/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/24/37805/#comments</comments>
    <pubDate>Mon, 24 Mar 2008 22:38:50 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Crosswords]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/24/37805</guid>
    <description><![CDATA[The solution to Crossword No. 1 is below the break.
]]></description>
      <content:encoded><![CDATA[<p>The solution to Crossword No. 1 is below the break.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37805&amp;akst_action=share-this" onclick="akst_share('37805', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F24%2F37805%2F', 'Solution+to+Crossword+No.+1'); return false;" title="Post to del.icio.us, etc." id="akst_link_37805" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Solution%20to%20Crossword%20No.%201&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F24%2F37805%2F" id="akst_email_37805" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Crossword No. 1</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/21/37802/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/21/37802/#comments</comments>
    <pubDate>Fri, 21 Mar 2008 13:22:40 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Crosswords]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/21/37802</guid>
    <description><![CDATA[Remember, Googling the clues is cheating. 
Unfortunately, I have to post this as an image since WordPress&#8217;s editor screws with my CSS.
I&#8217;ll post the solution on Monday.

Across
1. Article
4. Someone who works with you, but not for you
8.  Memory
9.  Camera part
10.  AOL service
11.  Fishy comment?
12.  Division
14.  Character encoding
18.  Java [...]]]></description>
      <content:encoded><![CDATA[<p>Remember, Googling the clues is cheating. <img src='http://blogs.teamb.com/feeds/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Unfortunately, I have to post this as an image since WordPress&#8217;s editor screws with my CSS.</p>
<p>I&#8217;ll post <a href="http://blogs.teamb.com/craigstuntz/2008/03/24/37805">the solution</a> on Monday.</p>
<p><img src="http://blogs.teamb.com/files/2008/03/crossword_314.png" alt="Crossword No. 1" /></p>
<h4>Across</h4>
<p><strong>1.</strong> Article<br />
<strong>4.</strong> Someone who works with you, but not for you<br />
<strong>8.</strong>  Memory<br />
<strong>9.  </strong>Camera part<br />
<strong>10.</strong>  AOL service<br />
<strong>11.</strong>  Fishy comment?<br />
<strong>12.</strong>  Division<br />
<strong>14.</strong>  Character encoding<br />
<strong>18.</strong>  Java component<br />
<strong>21.</strong>  Toss<br />
<strong>22.</strong>  "I&#8217;m ___!"<br />
<strong>23.</strong>  Apple&#8217;s address on Infinite Loop<br />
<strong>24.</strong>  Irish high king<br />
<strong>25.</strong>  It&#8217;s illegal at the polls</p>
<h4>Down</h4>
<p><strong>1.</strong>  Programmer&#8217;s wiki<br />
<strong>2.</strong>  Broadway musical<br />
<strong>3.</strong>  Austen novel<br />
<strong>4.</strong>  CPU clock counts<br />
<strong>5.</strong> Period<br />
<strong>6.</strong>  Peace, to Putin<br />
<strong>7.</strong>  Game machine<br />
<strong>13.</strong>  Tech book writer<br />
<strong>15.</strong>  Stroke cause<br />
<strong>16.</strong>  Scottish island, possible birthplace of the Book of Kells<br />
<strong>17.</strong>  Long-horned mountain goat<br />
<strong>18.</strong>  Deprecated Microsoft product<br />
<strong>19.</strong>  Composer Brian<br />
<strong>20.</strong>  Adobe development framework</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37802&amp;akst_action=share-this" onclick="akst_share('37802', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F21%2F37802%2F', 'Crossword+No.+1'); return false;" title="Post to del.icio.us, etc." id="akst_link_37802" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Crossword%20No.%201&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F21%2F37802%2F" id="akst_email_37802" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Columbus Snow</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/20/37801/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/20/37801/#comments</comments>
    <pubDate>Thu, 20 Mar 2008 21:42:32 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/20/37801</guid>
    <description><![CDATA[I promised someone on the newsgroups that I&#8217;d post some photos of the snow in Columbus from the week before last. We got 20 inches in 24 hours.


]]></description>
      <content:encoded><![CDATA[<p>I promised someone on the newsgroups that I&#8217;d post some photos of the snow in Columbus from the week before last. We got 20 inches in 24 hours.</p>
<p><a href="/files/2008/03/dsc01132_308.JPG" title="Snow 1"><img src="/files/2008/03/dsc01132_308.thumbnail.JPG" alt="Snow 1" /></a></p>
<p><a href="/files/2008/03/dsc01123_310.JPG" title="Snow 2"><img src="/files/2008/03/dsc01123_310.thumbnail.JPG" alt="Snow 2" /></a></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37801&amp;akst_action=share-this" onclick="akst_share('37801', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F20%2F37801%2F', 'Columbus+Snow'); return false;" title="Post to del.icio.us, etc." id="akst_link_37801" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Columbus%20Snow&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F20%2F37801%2F" id="akst_email_37801" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>InterBase for Mac Now Supports Tiger, Leopard</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/14/37798/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/14/37798/#comments</comments>
    <pubDate>Fri, 14 Mar 2008 13:56:55 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/14/37798</guid>
    <description><![CDATA[The developer edition of InterBase for Mac have been updated to support Tiger and Leopard.
]]></description>
      <content:encoded><![CDATA[<p>The <a href="http://cc.codegear.com/free/interbase">developer edition of InterBase</a> for Mac have been updated to support Tiger and Leopard.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37798&amp;akst_action=share-this" onclick="akst_share('37798', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F14%2F37798%2F', 'InterBase+for+Mac+Now+Supports+Tiger%2C+Leopard'); return false;" title="Post to del.icio.us, etc." id="akst_link_37798" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=InterBase%20for%20Mac%20Now%20Supports%20Tiger%2C%20Leopard&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F14%2F37798%2F" id="akst_email_37798" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Updating an ASP.NET MVC App to Preview 2</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/12/37797/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/12/37797/#comments</comments>
    <pubDate>Wed, 12 Mar 2008 19:47:56 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/12/37797</guid>
    <description><![CDATA[There&#8217;s a whole lot of ground not covered in the official update instructions.
The MVC Web UI helpers are now in the framework. But they&#8217;ve changed quite a bit. So you must:

Remove the assembly from your project.
UpdateFrom is no longer an extension method. It&#8217;s now a static method in System.Web.Mvc.BindingHelperExtensions. So you have to change anywhere [...]]]></description>
      <content:encoded><![CDATA[<p>There&#8217;s a whole lot of ground not covered in the <a href="http://www.asp.net/downloads/3.5-extensions/readme/Preview2.aspx">official update instructions</a>.</p>
<p>The <a href="http://blog.wekeroad.com/2007/12/05/aspnet-mvc-preview-using-the-mvc-ui-helpers/">MVC Web UI helpers</a> are now in the framework. But they&#8217;ve changed quite a bit. So you must:</p>
<ol>
<li>Remove the assembly from your project.</li>
<li>UpdateFrom is no longer an extension method. It&#8217;s now a static method in <code>System.Web.Mvc.BindingHelperExtensions</code>. So you have to change anywhere you called that.</li>
<li>Just to keep you on your toes, <code>System.Web.Mvc.BindingHelperExtensions</code> <a href="http://forums.asp.net/p/1231619/2227810.aspx">will probably be renamed soon</a>.</li>
<li>RedirectToAction is now in <code>System.Web.Routing</code>. Edit your controllers.</li>
<li>RedirectToAction now takes a RouteValueDictionary instead of an anonymous type. You can stuff your old anonymous type into the constructor for RouteValueDictionary.</li>
<li>If you have unit tests you have to update that project, too. In a big way. All that stuff Phil Haack had on his blog as a download a while back is now in the framework. IHttpContext is now HttpContextBase. I&#8217;m still figuring this stuff out. I may have to rebuild the unit tests from scratch.</li>
</ol>
<p>I think it&#8217;s fair to say that the unit test portion of MVC is in even greater flux than the rest of the framework at present.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37797&amp;akst_action=share-this" onclick="akst_share('37797', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F12%2F37797%2F', 'Updating+an+ASP.NET+MVC+App+to+Preview+2'); return false;" title="Post to del.icio.us, etc." id="akst_link_37797" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Updating%20an%20ASP.NET%20MVC%20App%20to%20Preview%202&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F12%2F37797%2F" id="akst_email_37797" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Dynamic Creation of IntraWeb Components, Part 2</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/10/37795/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/10/37795/#comments</comments>
    <pubDate>Mon, 10 Mar 2008 13:51:46 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/10/37795</guid>
    <description><![CDATA[I recently wrote about limitations in creating IntraWeb components dynamically when using the template processor component. It looks like the Arcana template processor, recently released as open source, may allow this. Worth investigating, anyway.
]]></description>
      <content:encoded><![CDATA[<p>I recently wrote about limitations in <a href="http://blogs.teamb.com/craigstuntz/2008/03/05/37793">creating IntraWeb components dynamically</a> when using the template processor component. It looks like the <a href="http://code.google.com/p/iwelite/" title="Elite Suite for IntraWeb / VCL for the Web">Arcana template processor</a>, recently released as open source, may allow this. Worth investigating, anyway.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37795&amp;akst_action=share-this" onclick="akst_share('37795', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F10%2F37795%2F', 'Dynamic+Creation+of+IntraWeb+Components%2C+Part+2'); return false;" title="Post to del.icio.us, etc." id="akst_link_37795" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Dynamic%20Creation%20of%20IntraWeb%20Components%2C%20Part%202&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F10%2F37795%2F" id="akst_email_37795" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>The Bleeding Edge Gets Painful</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/06/37794/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/06/37794/#comments</comments>
    <pubDate>Thu, 06 Mar 2008 14:57:57 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

		<category><![CDATA[.NET]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/06/37794</guid>
    <description><![CDATA[The March 2008 ASP.NET MVC Preview 2 is incompatible with AJAX and Dynamic Data. Ouch!
AJAX and dynamic data features cannot be mixed in the same Web site or application as the new ASP.NET MVC. You should use separate Web sites or applications.
]]></description>
      <content:encoded><![CDATA[<p>The March 2008 ASP.NET MVC Preview 2 is <a href="http://www.asp.net/downloads/3.5-extensions/readme/Preview2.aspx#_Toc192423251" title="ASP.NET MVC Preview 2 and ASP.NET Server Controls for Silverlight">incompatible with AJAX and Dynamic Data</a>. Ouch!</p>
<blockquote><p>AJAX and dynamic data features cannot be mixed in the same Web site or application as the new ASP.NET MVC. You should use separate Web sites or applications.</p></blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37794&amp;akst_action=share-this" onclick="akst_share('37794', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F06%2F37794%2F', 'The+Bleeding+Edge+Gets+Painful'); return false;" title="Post to del.icio.us, etc." id="akst_link_37794" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=The%20Bleeding%20Edge%20Gets%20Painful&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F06%2F37794%2F" id="akst_email_37794" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Dynamic Creation of IntraWeb Components</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/03/05/37793/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/03/05/37793/#comments</comments>
    <pubDate>Wed, 05 Mar 2008 18:26:59 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/03/05/37793</guid>
    <description><![CDATA[For the past couple of days I’ve been working on an experimental IntraWeb (a.k.a., "VCL for the Web") project. Since I typically generate user interfaces dynamically, I wanted to see how that worked with IntraWeb. On the surface, it’s fairly similar to the regular VCL, but there are some important differences.]]></description>
      <content:encoded><![CDATA[<p>For the past couple of days I’ve been working on an experimental IntraWeb (a.k.a., "VCL for the Web") project. Since I typically generate user interfaces dynamically, I wanted to see how that worked with IntraWeb. On the surface, it’s fairly similar to the regular VCL, but there are some important differences.</p>
<p>Rule number one is that <strong>all components you create must have the Name property set</strong>. The regular VCL doesn’t require this for components created in code, but IntraWeb uses the Component.Name as part of the HTML id, and if the id isn’t set, the JavaScript generated by IntraWeb won’t work. So always set the Name.</p>
<p>Another thing to note is that the default property values don’t always make sense. If a component looks different when you dynamically generated at runtime versus when you drop it on an IntraWeb form in the designer, take a close look at the text DFM. You’ll probably find non-default property values set by the designer. If you replicate this in your code, you should end up with a component looks the same at runtime.</p>
<p>With all that said, here’s some simple code to add tabs at runtime to an existing tab control:</p>
<blockquote>
<pre><code><strong>uses</strong>   Graphics, IWContainerBorderOptions;

<strong>procedure </strong>TfrmUIPageGroup.ClearPageControls;
<strong>var</strong>
  iPage: integer;
<strong>begin</strong>
  <strong>for </strong>iPage := Pred(TabControl.Pages.Count) <strong>downto </strong>0 <strong>do begin</strong>
    TObject(TabControl.Pages[iPage]).Free;
  <strong>end</strong>;
<strong>end</strong>;

<strong>procedure </strong>TMyIntraWebForm.AddSomeTabs;
<strong>var</strong>
  iPage, iTabTop, iTabHeight, iTabWidth: integer;
  NewTab: TIWTabPage;
<strong>begin</strong>
  <em>// need to have a design-time page to copy sizing properties from</em>
  Assert(TabControl.Pages.Count &gt; 0);
  iTabTop := TIWTabPage(TabControl.Pages[0]).Top;
  iTabHeight := TIWTabPage(TabControl.Pages[0]).Height;
  iTabWidth := TIWTabPage(TabControl.Pages[0]).Width;
  ClearPageControls;
  <strong>for </strong>iPage := 0 <strong>to </strong>2 <strong>do begin</strong>
    NewTab := TIWTabPage.Create(TabControl);
    NewTab.BorderOptions.NumericWidth := 0;
    NewTab.BorderOptions.BorderWidth := cbwNumeric;
    NewTab.BorderOptions.Style := cbsNone;
    NewTab.BorderOptions.Color := clNone;
    NewTab.Color := clWebWHITE;
    NewTab.Top := iTabTop;
    NewTab.Width := iTabWidth;
    NewTab.Height := iTabHeight;
<em>    // WordPress changes the single quote to a typographic quote here, so cutting
    // and pasting the next two lines won&#8217;t work. Sorry; I haven&#8217;t figured out how
    // to stop that
</em>    NewTab.Name := &#8216;DynamicPage&#8217; + IntToStr(iPage);
    NewTab.Title :=  &#8216;Page &#8216; + IntToStr(iPage);
    NewTab.Parent := TabControl;
    <em>// TabOrder determines the order of tabs (really!) in this control
    // It must be set *after* Parent</em>
    NewTab.TabOrder := iPage;
  <strong>end</strong>;
<strong>end</strong>;
</code></pre>
</blockquote>
<p>Alignment may not work as expected, either.  If I build on this example by creating a control, parenting it to the tab sheet, and setting the Align property to alClient, that control&#8217;s size or position doesn&#8217;t actually change.</p>
<p>Finally, there is the issue of layout managers. If you use TIWTemplateProcessorHTML or TIWLayoutMgrHTML, there will not be a placeholder in your template for your dynamically generated component. There is probably a way around this, but I have not fully investigated the issue yet. One possible solution would be to do the dynamic component generation inside of a custom IntraWeb control.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37793&amp;akst_action=share-this" onclick="akst_share('37793', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F05%2F37793%2F', 'Dynamic+Creation+of+IntraWeb+Components'); return false;" title="Post to del.icio.us, etc." id="akst_link_37793" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Dynamic%20Creation%20of%20IntraWeb%20Components&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F03%2F05%2F37793%2F" id="akst_email_37793" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>clMenuBar Renders Black on Windows 2000</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/02/28/37792/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/02/28/37792/#comments</comments>
    <pubDate>Thu, 28 Feb 2008 21:51:26 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/02/28/37792</guid>
    <description><![CDATA[In Delphi 2007, you may notice some newer color constants towards the end of the list, with names like clMenuBar and clMenuHighlight. Beware! These color constants aren&#8217;t supported on Windows 2000, and they render as black. Since the default menu text is also black, this makes the menus rather tough to read! If you use [...]]]></description>
      <content:encoded><![CDATA[<p>In Delphi 2007, you may notice some newer color constants towards the end of the list, with names like clMenuBar and clMenuHighlight. Beware! <a href="http://msdn2.microsoft.com/en-us/library/ms724371.aspx" title="GetSysColor Function">These color constants aren&#8217;t supported on Windows 2000</a>, and they render as black. Since the default menu text is also black, this makes the menus rather tough to read! If you use them then you should detect Win2000 (and possibly earlier OSs) in code and replace them with a supported constant such as clBtnFace.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37792&amp;akst_action=share-this" onclick="akst_share('37792', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F02%2F28%2F37792%2F', 'clMenuBar+Renders+Black+on+Windows+2000'); return false;" title="Post to del.icio.us, etc." id="akst_link_37792" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=clMenuBar%20Renders%20Black%20on%20Windows%202000&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F02%2F28%2F37792%2F" id="akst_email_37792" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Why an App Might Disappear Without Notice</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/02/15/37791/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/02/15/37791/#comments</comments>
    <pubDate>Fri, 15 Feb 2008 16:51:27 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/02/15/37791</guid>
    <description><![CDATA[I was previously aware of two reasons that an application might simply disappear, without any notification to the user:

A stack overflow (you sometimes get a message box about this, but not always)
Data execution prevention

Raymond Chen adds another item to the list today:

Doing ugly things to the stack

Know of anything else? Add it in comments.
Share This [...]]]></description>
      <content:encoded><![CDATA[<p>I was previously aware of two reasons that an application might simply disappear, without any notification to the user:</p>
<ul>
<li>A stack overflow (you sometimes get a message box about this, but not always)</li>
<li><a href="http://blogs.teamb.com/craigstuntz/2007/11/27/37772" title="My Application Dies on Server 2003">Data execution prevention</a></li>
</ul>
<p>Raymond Chen adds another item to the list today:</p>
<ul>
<li><a href="http://blogs.msdn.com/oldnewthing/archive/2008/02/15/7703995.aspx" title="There's more to switching stacks than just loading a new stack pointer">Doing ugly things to the stack</a></li>
</ul>
<p>Know of anything else? Add it in comments.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37791&amp;akst_action=share-this" onclick="akst_share('37791', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F02%2F15%2F37791%2F', 'Why+an+App+Might+Disappear+Without+Notice'); return false;" title="Post to del.icio.us, etc." id="akst_link_37791" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Why%20an%20App%20Might%20Disappear%20Without%20Notice&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F02%2F15%2F37791%2F" id="akst_email_37791" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Versioning DB Metadata Changes and Performance</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/02/04/37790/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/02/04/37790/#comments</comments>
    <pubDate>Mon, 04 Feb 2008 16:16:44 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/02/04/37790</guid>
    <description><![CDATA[Here&#8217;s yet another guy with more good ideas on how to version database metadata changes.  Unfortunately, the ideal method of database metadata versioning remains to be discovered.  The ideas discussed in K. Scott Allen&#8217;s series are good from a version control point of view, but they will have serious, negative performance implications in [...]]]></description>
      <content:encoded><![CDATA[<p>Here&#8217;s <a href="http://odetocode.com/Blogs/scott/archive/2008/02/03/11746.aspx" title="Versioning Databases – Branching and Merging">yet another guy with more good ideas on how to version database metadata changes</a>.  Unfortunately, the ideal method of database metadata versioning remains to be discovered.  The ideas discussed in K. Scott Allen&#8217;s series are good from a version control point of view, but they will have serious, negative performance implications in the real world.  In particular, <a href="http://odetocode.com/Blogs/scott/archive/2008/02/02/11721.aspx" title="Versioning Databases – Change Scripts">this bit</a>:</p>
<blockquote><p>Once a script is published into source control, it <em>cannot be changed</em>! Once someone updates their database with an update script, they should never have to run the same script on that same database.</p></blockquote>
<p>Now, I think that, in general, immutability is a good thing, and it goes without saying that back version since source control should be immutable.  But these scripts are not backed versions of a file; they&#8217;re a list of the DDL scripts which will actually be run on the end user&#8217;s server. And there&#8217;s the rub. Let&#8217;s say that in developing feature 100, you decide that you need to add a new column to a large table:</p>
<pre><code>ALTER TABLE BIG_TABLE
  ADD FEATURE_100_COLUMN MY_DOMAIN;
UPDATE BIG_TABLE
  SET FEATURE_100_COLUMN = DEFAULT_VALUE;</code></pre>
<p>Naturally, you add this script to version control, with whatever method you are using to version your database metadata changes.  Later, you work on feature 150, which requires another column on the same table:</p>
<pre><code>ALTER TABLE BIG_TABLE
  ADD FEATURE_150_COLUMN MY_DOMAIN;
UPDATE BIG_TABLE
  SET FEATURE_150_COLUMN = DEFAULT_VALUE;</code></pre>
<p>Simply concatenating these two scripts together, as you must do if the scripts are immutable, results in an update process for the end-user which takes far longer than necessary, as the table must be altered and updated twice. It would be far more efficient to merge the two scripts:</p>
<pre><code>ALTER TABLE BIG_TABLE
  ADD FEATURE_100_COLUMN MY_DOMAIN,
  ADD FEATURE_150_COLUMN MY_DOMAIN;
UPDATE BIG_TABLE
  SET FEATURE_100_COLUMN = DEFAULT_VALUE,
  SET FEATURE_150_COLUMN = DEFAULT_VALUE;</code></pre>
<p>This merged script should run an approximately half of the time it takes to run the two scripts separately.</p>
<p>And yet, as I said earlier, treating the scripts as immutable is a good idea from a source control point of view.  In particular, you want to be able to extract the metadata changes used to implement a particular feature by themselves.  Hence, it makes sense to use a database metadata version control strategy which treats these two goals separately, instead of trying to combine them into a single feature.  It makes sense to me to store these scripts for individual features, and have a separate script used to update a customer database.</p>
<p>One of Scott&#8217;s goals in developing a system he advocates is to allow/require developers to work on their own copy of the development database, which they can update along with checking out the corresponding source code, instead of using a shared, centralized development database.  Merging the DDL scripts from multiple feature implementations means that one can no longer update one&#8217;s personal development database to include arbitrary new features.  Instead, it is necessary to start with the metadata for the last released version of the software, and then apply the tip revision of the update script. Many developers might find this inconvenient.</p>
<p>Like I said, the ideal system for this has yet to be invented, as far as I can see.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37790&amp;akst_action=share-this" onclick="akst_share('37790', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F02%2F04%2F37790%2F', 'Versioning+DB+Metadata+Changes+and+Performance'); return false;" title="Post to del.icio.us, etc." id="akst_link_37790" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Versioning%20DB%20Metadata%20Changes%20and%20Performance&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F02%2F04%2F37790%2F" id="akst_email_37790" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Beware of RegexOptions.Compiled</title>
    <link>http://blogs.teamb.com/yaminov/2008/01/31/beware-of-regexoptionscompiled/</link>
    <comments>http://blogs.teamb.com/yaminov/2008/01/31/beware-of-regexoptionscompiled/#comments</comments>
    <pubDate>Fri, 01 Feb 2008 00:08:07 +0000</pubDate>
    <dc:creator>Yorai Aminov</dc:creator>
    
		<category><![CDATA[CDN]]></category>

		<category><![CDATA[.NET]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/yaminov/2008/01/31/beware-of-regexoptionscompiled/</guid>
    <description><![CDATA[You may not have noticed, because they look exactly the same, but as of a couple of hours ago, CodeGear&#8217;s web sites are running a new version of GetPublished. Internally, the biggest change was moving from ASP.NET 1.1 to 2.0. We&#8217;ve been testing the new version for a while now, but just before the upgrade [...]]]></description>
      <content:encoded><![CDATA[<p>You may not have noticed, because they look exactly the same, but as of a couple of hours ago, CodeGear&#8217;s web sites are running a new version of <a href="http://gp.codegear.com">GetPublished</a>. Internally, the biggest change was moving from ASP.NET 1.1 to 2.0. We&#8217;ve been testing the new version for a while now, but just before the upgrade ran into a serious performance issue.</p>
<p>When we first <a href="http://dn.codegear.com/article/33477">migrated the old BDN site</a> to ASP.NET, one of our goals was making sure we didn&#8217;t break existing links. To achieve that goal, we used regular expressions to search for known patterns and either redirect or <a href="http://msdn2.microsoft.com/en-us/library/ms972974.aspx">rewrite</a> the requested URLs. Over time, this became part of GetPublished, and system administrators can now add redirection patterns using the web interface.</p>
<p>Because these patterns have to be checked for every request, we used compiled Regex instances to boost performance. This worked great in .NET 1.1, but when we moved to 2.0, CPU usage on the servers began to spike and performance dropped like a brick. Here&#8217;s why: the .NET Regex class maintains a cache of parsed expressions. In .NET 1.1, this cache is unbounded, so all expressions are cached (until you run out of memory). Unfortunately, this behavior was changed in .NET 2.0. The cache is now limited to 15 expressions (although it is possible to override this value), and regular expressions created by Regex instance methods aren&#8217;t cached at all. <a href="http://blogs.msdn.com/bclteam/archive/2006/10/19/regex-class-caching-changes-between-net-framework-1-1-and-net-framework-2-0-josh-free.aspx">This entry</a> from the BCL team blog explains why.</p>
<p>Removing the RegexOptions.Compiled flag made our code over 50 times faster (or, as some would rather say, using compiled expressions made the code 50 times slower). So, if you&#8217;re using regular expressions, think hard about whether compiling them makes sense for you, and if you&#8217;re moving from .NET 1.1 to 2.0, you now know about this little performance trap just waiting to kill your application.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/yaminov/?p=10&amp;akst_action=share-this" onclick="akst_share('10', 'http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F01%2F31%2Fbeware-of-regexoptionscompiled%2F', 'Beware+of+RegexOptions.Compiled'); return false;" title="Post to del.icio.us, etc." id="akst_link_10" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Beware%20of%20RegexOptions.Compiled&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fyaminov%2F2008%2F01%2F31%2Fbeware-of-regexoptionscompiled%2F" id="akst_email_10" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>On the Ubiquity of Garbage Collection</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/01/25/37788/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/01/25/37788/#comments</comments>
    <pubDate>Fri, 25 Jan 2008 15:36:07 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/01/25/37788</guid>
    <description><![CDATA[As far as I can tell, programming language designers do not seem to be creating non-garbage-collected, general-purpose programming languages anymore. This trend is not restricted to "scripting languages" or languages requiring a run time. Performance-oriented languages designed as potential replacements for C++, such as D and OCaml, are garbage collected, and the forthcoming version of the C++ standard will include features explicitly intended to facilitate use of a garbage collector.]]></description>
      <content:encoded><![CDATA[<p>In previous posts, I have described features of garbage collection which I consider beneficial.  Today I am going to discuss a "feature" which I think is a good <em>reason to learn</em> about garbage collection, but <em>not necessarily a good thing overall</em>.  <a href="http://www.worldwidewords.org/qa/qa-wit1.htm">To wit</a>: If you intend to continue working in the software development industry, you&#8217;re going to be using garbage collection, whether you like it or not.</p>
<p>This may be a hard pill to swallow for so-called "C++ programmers" or "Pascal programmers" who do not know any programming languages designed after the 1970s.  But change is the rule in the software industry.  If you are not learning new skills, you are eventually going to be left behind. (Note that I am not claiming that these older languages are going to go away; COBOL is still in use, too, but most people don&#8217;t make that a career goal.)</p>
<p>As far as I can tell, programming language designers do not seem to be creating <a href="http://c2.com/cgi/wiki?LanguagesWithoutGarbageCollection" title="Languages Without Garbage Collection">non-garbage-collected, general-purpose programming languages</a> anymore.  This trend is not restricted to "scripting languages" or languages requiring a run time.  Performance-oriented languages designed as potential replacements for C++, such as D and OCaml, are garbage collected, and the forthcoming version of the C++ standard will include features explicitly intended to facilitate use of a garbage collector.</p>
<p>I do not know what the programming language(s) of the future will be. Steve Yegge <a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html" title="The Next Big Language">discussed the issue at some length</a>, and came to the same conclusion as this post regarding GC:</p>
<blockquote><p>[Next Big Language] is garbage collected.  There will always be a bunch of engineers who think that&#8217;s evil, and they&#8217;ll continue to use C++.</p>
<p>C++ does need to get replaced someday. It&#8217;s just horrid, and everyone knows it. However, there aren&#8217;t very many people trying to replace it, either. The only contenders I&#8217;m aware of are Objective C and the <a href="http://www.digitalmars.com/d">D Programming Language</a>.</p>
<p>D&#8217;s a really beautiful language. By rights it should be the next C++. However, C++ programmers won&#8217;t have it because it&#8217;s garbage collected (even though it can be disabled, and even though <em>Stroustroup [sic.] himself</em> is now advocating adding garbage collection to C++). Walter Bright is one hell of a lot smarter than the C++ programmers who won&#8217;t look at his language, and he has demonstrated that D is as fast as or faster than C++ and nearly as expressive as Ruby or Python. It&#8217;s a secret weapon just waiting to be seized by some smart company or open-source project.</p>
<p>But nobody ever accuses programmers of being <em>wise</em>.</p></blockquote>
<p>Perhaps, some years from now, someone will invent a non-garbage-collected language which will become the dominant language of future days.  But at the present time, I don&#8217;t see any non-garbage-collected candidates for the job.</p>
<p>This makes me a little bit uncomfortable, because, in general, I like to have options.  It would be nice if, 10 years from now, I had more than one choice for heap management (presuming that we still have "heaps" in a decade&#8230;).</p>
<p>Although I like the <em>concept </em>of making garbage collection optional, it&#8217;s much harder to put that option into practice successfully.  The trouble is that most people don&#8217;t just use programming languages, they also use the standard libraries and toolkits which support those languages.  And while it&#8217;s fairly trivial to make use of garbage collection within a programming language optional, it&#8217;s much harder to do it well with a library. So I don&#8217;t think some kind of compiler switch or memory manager plugin will resolve this issue of choice; a real choice would be an environment constructed to work with manual memory release, and I don&#8217;t see anyone building that.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37788&amp;akst_action=share-this" onclick="akst_share('37788', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F25%2F37788%2F', 'On+the+Ubiquity+of+Garbage+Collection'); return false;" title="Post to del.icio.us, etc." id="akst_link_37788" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=On%20the%20Ubiquity%20of%20Garbage%20Collection&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F25%2F37788%2F" id="akst_email_37788" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Garbage Collection and Functional Programming</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/01/24/37787/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/01/24/37787/#comments</comments>
    <pubDate>Thu, 24 Jan 2008 16:24:31 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/01/24/37787</guid>
    <description><![CDATA[This post is going to be short and sweet, because the point is very simple: If you use a functional programming language (and, if you want to learn to think outside of the Delphi box, you should), then you will be using garbage collection.]]></description>
      <content:encoded><![CDATA[<p>This post is going to be short and sweet, because the point is very simple: If you use a functional programming language (and, if you want to learn to think outside of the Delphi box, <a href="http://www.math.chalmers.se/~rjmh/Papers/whyfp.html" title="Why Functional Programming Matters">you should</a>), then you <em>will </em>be using garbage collection.</p>
<p>There are many reasons why this is the case. <a href="http://c2.com/cgi/wiki?FunctionalProgramming">Garbage collection is a core feature of functional programming</a>, because functional programming features do not work well with the semantics of explicit memory release.  It is telling that language implementors have found it <a href="http://portal.acm.org/citation.cfm?id=1292525" title="Towards hard real-time erlang">easier and more correct</a> to create <a href="http://portal.acm.org/citation.cfm?id=802146" title="Improved effectiveness from a real time LISP garbage collector">real-time</a> <a href="http://www.research.ibm.com/metronome/index.html" title="Metronome Project">garbage collectors</a> than to create and work with non-garbage-collected variants of functional languages.</p>
<p>I was unable to find a single example of a truly functional language which did not use garbage collection in any standard version. Haskell, OCaml, Common Lisp, Erlang, ML, Scheme, etc., are all garbage collected. Moreover, functional features are commonly added to languages like C#, Ruby, Python, ECMAScript, and others, which weren&#8217;t designed as functional languages, but happen to be garbage collected. Whereas languages like Delphi/Win32 get fewer such features, despite their continuing evolution. The FC++ library, which adds some functional programming features to C++, uses a reference-counting method of garbage collection internally, to its great benefit. <a href="http://www.cc.gatech.edu/~yannis/fc++/fc++.main.pdf" title="Functional Programming in C++">The authors note</a>:</p>
<blockquote><p>For instance, compared to Läufer’s approach, we achieve an equally safe but more efficient implementation of the basic framework for higher order functions. This is done by allowing function objects to be multiply referenced (aliased), albeit only through garbage collected “pointers”. The difference in performance is substantial: compared to Läufer’s framework, and running with the same client code (the main example implemented by Läufer) we achieve a 4- to 8-fold speedup.</p></blockquote>
<p>The <a href="http://www.digitalmars.com/d/2.0/index.html">D programming language</a> is designed to combine the power of C++ with the productivity and contemporary features of Ruby Python.  It supports <a href="http://www.digitalmars.com/d/2.0/comparison.html">function literals, closures, and lazy evaluation</a>. It doesn&#8217;t use a runtime, or a JIT compiler, but <a href="http://www.digitalmars.com/d/2.0/memory.html">it uses garbage collection for heap management</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37787&amp;akst_action=share-this" onclick="akst_share('37787', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F24%2F37787%2F', 'Garbage+Collection+and+Functional+Programming'); return false;" title="Post to del.icio.us, etc." id="akst_link_37787" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Garbage%20Collection%20and%20Functional%20Programming&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F24%2F37787%2F" id="akst_email_37787" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Non-Reference-Counted Interfaces</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/01/23/37786/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/01/23/37786/#comments</comments>
    <pubDate>Wed, 23 Jan 2008 15:53:25 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/01/23/37786</guid>
    <description><![CDATA[[...] far from solving the problem of conflicting systems of memory management, formal language support for a "non-reference-counted" root interface type in Win32 actually seems to make some of the worse. My conclusion is that the present state of the Delphi language is a better option than this proposed change.]]></description>
      <content:encoded><![CDATA[<p>As I mentioned in <a href="/craigstuntz/2008/01/22/37785" title="Garbage Collection As Unified Memory Management">my last post</a>, I think that non-reference-counted interfaces are a good idea in their own right.  After all, .NET has non-reference-counted interfaces, and they work very well there.  So why shouldn&#8217;t they be included in Delphi for Win32, as well? I remember being at a BorCon just before the release of Kylix and hearing <a href="http://www.removingalldoubt.com/">Chuck Jazdzewski</a> discuss the introduction of a then-new type name, <code>IInterface</code>, which, he said, would be an alias to <code>IUnknown</code>.  Someone in the audience commented that this would be a great opportunity to introduce an interface type intended for non-reference-counted lifetime management as the root interface type. <code>IUnknown</code> could inherit from that and introduce the <code>_AddRef</code> and <code>_Release</code> functions.  Chuck said it was an interesting idea and they would consider it.  Of course, we now know that such a feature was not introduced with Kylix.  Since I take Chuck at his word, I presume that the feature was considered, but that the team eventually decided against it.</p>
<p>Let&#8217;s perform a thought experiment and see what would happen if this feature were added.</p>
<h3>Win32 Interfaces Today</h3>
<p>First, let&#8217;s examine in a bit more detail how interfaces work in Delphi for Win32 today, and the features for non-reference-counted interfaces which are already available.</p>
<p>All interfaces in Delphi in inherit from <code>IInterface</code>/<code>IUnknown</code>.  This interface defines three methods, of which two are interesting in the context of reference counting, <code>_AddRef</code> and <code>_Release</code>.  When an interface reference comes in scope, the compiler inserts a call to <code>_AddRef</code>, and when the reference goes out of scope, the compiler inserts a call to <code>_Release</code>. Both methods are called virtually, which means you need an intact <acronym title="Virtual Method Table">VMT</acronym>; in order for the call to succeed. This means that the instance on which they are called must either still be allocated, or a least that the memory holding their VMT has not been overwritten by other data.</p>
<p><em>You can define a class which supports interfaces and use those interfaces in a roughly non-reference-counted manner today</em>, with certain limitations.  If you implement <code>_AddRef</code> and <code>_Release</code> to both return -1, this is a convention (see comments in <code>Classes.pas</code>) to indicate that you&#8217;re ignoring reference counting, and you can implement <code>_Release</code>  to not free the instance when the ref count goes to 0. Importantly, however, <code>_AddRef</code> and <code>_Release</code> are <em>still going to be called</em> for any non-nil interface reference, whether or not you&#8217;re managing lifetimes via reference counting. The functions don&#8217;t have to do anything, but they will be called anyway.</p>
<p>As I mentioned in my last post, it is a very common case to have multiple references of different interface types to a single instance of an object that supports those interfaces.  This is because of the intentionally limited window into the object&#8217;s features that an interface provides. If you choose to "turn off" reference counting by making <code>_AddRef</code> and <code>_Release</code> return -1, then you must be very careful to manually nil all interface references to an instance before <code>Free</code>-ing the instance with an object reference.  Should you forget to do that, or do it incorrectly, then you will very likely have to debug an access violation in <code>System._IntfClear</code>.  This is usually difficult to do since the reference which raised the access violation is certainly out of scope, and is of type <code>IInterface</code>, which doesn&#8217;t provide a lot of information, especially as a dangling pointer. Despite these obstacles, I use non-reference-counted interfaces quite a bit, because interfaces are a useful programming technique, and I don&#8217;t want to live without them in cases where reference counting cannot be used, as with visual components, which are mostly lifetime-managed via the Ownership mechanism.</p>
<h3>"Non-Reference-Counted" Win32 Interfaces</h3>
<p>So even though we can in fact have an interface reference to something which is not lifetime managed via reference counting, this <code>_AddRef</code> and <code>_Release</code> thing is still a bit of a pain.  Let&#8217;s imagine what would have happened if Chuck had implemented the suggestion to make <code>IInterface </code>not do any kind of reference count calls, and to introduce those in <code>IUnknown</code>, which would then be a subtype of <code>IInterface</code>, rather than an alias.  <code>IInterface</code> would only define the <code>QueryInterface</code> method.</p>
<p>Now, we might think, that the compiler can insert calls to <code>_AddRef</code> and <code>_Release</code> when it sees an interface reference which is of the type which is a subtype of <code>IUnknown</code>, and not to insert those calls when it sees an interface reference which is of a type which is not a subtype of <code>IUnknown</code>.  This seems like a pretty good idea, since it will certainly solve the access violation problem.</p>
<p>However, we quickly hit a roadblock.  What if a class implements both "types" of interface?</p>
<p>With the present system, where <code>_AddRef</code> and <code>_Release</code> are always called, the compiler always knows what to do when it sees an interface reference.  With our proposed new system, it&#8217;s less clear what the compiler should do.  None of the options I can think of looks particularly good:</p>
<ul>
<li>The compiler could insert calls to <code>_AddRef</code> and <code>_Release</code> for a reference of an interface type which is a subtype of <code>IUnknown</code>, and not insert these calls for a reference of an interface type which is not a subtype of <code>IUnknown</code>.  This is dangerous, for reasons which should be obvious. Far from reducing the confusion over different types of memory management, we&#8217;ve made it worse with this option.</li>
<li>When the compiler encounters an interface reference of a type which is not a subtype of <code>IUnknown</code>, the compiler could call <code>QueryInterface</code> to see if the implementor supports <code>IUnknown</code>, and call <code>_AddRef</code> and <code>_Release</code>  if it does.  This means, among other things, that there is now very little advantage over the present method of implementing "non-reference-counted interfaces."  In particular, the access violation problem is back. Worse, it means that the behavior of your application at the site of the interface reference can change when you implement a new interface on a class.</li>
<li>The compiler could simply forbid any class from implementing both "types" of interface.  This is probably the safest option, but it&#8217;s incredibly limiting and it violates the spirit and intention of an interface.  It&#8217;s limiting because it forbids things which are already implemented in the VCL today, like <code>TComponent</code>&#8217;s interface support, which is designed to work both with reference counted and non-reference-counted instances. It violates the intention of an interface because it introduces implementation details into the signature of the interface. Interfaces are supposed to be interfaces only, not implementation.  Having distinct "types" of interfaces leads to the same problems one encounters with multiple implementation inheritance, notably the "<a href="http://en.wikipedia.org/wiki/Diamond_problem">diamond problem</a>." One could very well end up requiring parallel hierarchies of reference counted and non-reference-counted interface types, precisely the problem that interfaces are supposed to overcome.</li>
</ul>
<p>On top of all of this, we still have the problems I referred to in my previous post, such as more dangling pointers.</p>
<p>The bottom line is that, far from solving the problem of conflicting systems of memory management, formal language support for a "non-reference-counted" root interface type in Win32 actually seems to make some of the worse.  My conclusion is that the present state of the Delphi language is a better option than this proposed change.</p>
<p><strong>Update:</strong> Clarified a couple of details regarding non-reference-counted interface features available today.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37786&amp;akst_action=share-this" onclick="akst_share('37786', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F23%2F37786%2F', 'Non-Reference-Counted+Interfaces'); return false;" title="Post to del.icio.us, etc." id="akst_link_37786" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Non-Reference-Counted%20Interfaces&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F23%2F37786%2F" id="akst_email_37786" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Garbage Collection As Unified Memory Management</title>
    <link>http://blogs.teamb.com/craigstuntz/2008/01/22/37785/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2008/01/22/37785/#comments</comments>
    <pubDate>Tue, 22 Jan 2008 14:54:46 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2008/01/22/37785</guid>
    <description><![CDATA[This is the first of what may become a small series of posts on advantages of garbage collection. Garbage collection is often contrasted with "manual" memory management, as though any application which doesn't use garbage collection frees all allocations with an explicit call to Free. But that isn't true at all. In fact, Delphi has several different methods of memory management, depending upon what you're doing.]]></description>
      <content:encoded><![CDATA[<p>This is the first of what may become a small series of posts on advantages of garbage collection.  I am not a person who sees garbage collection is the ideal system of memory management for all applications, but I see a tremendous amount of FUD about garbage collection in the public newsgroups, mostly coming from people who clearly have very little experience using it.  Since the disadvantages of garbage collection are widely, if inaccurately, discussed, I&#8217;d like to shed some light on the other side of that coin.</p>
<p>For me, be general theme of most of the advantages of garbage collection can be summarized as "expressive programming."  This means that your source code can be written to express the concise nature of the problem instead of precisely how to solve it.  Most programmers do not write applications to solve the problem of memory management.  Memory management, instead, is a kind of tax that we have to pay to get to our solution.  Eliminating explicit memory management can allow the programmer to focus most directly on the problem at hand. As a loose analogy, consider the difference between a LINQ query and a traditional for loop. The former asserts the need to iterate, but delegates the method of iteration to the instance to be iterated. The traditional for loop, on the other hand, spells out the precise method of iteration.  The LINQ query, therefore, is more expressive, since it does not pollute the description of what needs to be done with an algorithm for how it is to be done. The difference may seem kind of academic, until you examine <a href="http://blogs.msdn.com/pfxteam/archive/2007/12/07/6696413.aspx" title="Parallelizing a query with multiple from clauses">how easy it is to parallelize the more expressive code</a>.  Then you see the advantage of expressive coating.</p>
<p>Expressing this point another way, manual memory management tends to force programmers to write their code in a way which suits the memory management as well is the problem instead of a way which most directly suits the problem. The most dramatic example of this is functional programming, a powerful technique which is extremely difficult to do well without garbage collection.</p>
<p>Garbage collection is often contrasted with "manual" memory management, as though any application which doesn&#8217;t use garbage collection frees all allocations with an explicit call to Free.  But that isn&#8217;t true at all.  In fact, Delphi has several different methods of memory management, depending upon what you&#8217;re doing.  Off the top of my head:</p>
<ul>
<li>You can free an allocation with an explicit call to Free.</li>
<li>Components can be freed via the Ownership mechanism.  This is critical to streaming.</li>
<li>Components will be freed when their Parent is freed.</li>
<li>Some types are allocated on the stack, and freed when they go out of scope.</li>
<li>Some types are reference counted.</li>
</ul>
<p>Now, that&#8217;s a lot of different methods of handling memory, and I&#8217;m reasonably sure that I have not had all of them.  Worse, they can and do conflict.  This is most commonly noticed when using interfaces, and though it&#8217;s hardly the only example, it is perhaps the one with the greatest potential to cause problems.  So much so, in fact, that I believe it is principally responsible for the fact that interfaces are not widely used in Win32 Delphi code (in contrast, for example, with .NET code), even though they were introduced in Delphi 3.</p>
<p>For just one example of how this conflict between memory management types complicates Win32 programming in Delphi, look closely at the constructor for TXMLDocument. Another is the lengths that you must take to ensure that you explicitly nil all interface references to a non&#8211;reference-counted instance before Freeing it, <a href="/craigstuntz/2005/03/31/3593">or you will almost certainly see an Access Violation in _IntfClear</a>.</p>
<p>People occasionally suggest that reference counting is a holdover from COM, and a solution to this problem would be a non&#8211;reference-counted interface type.  It&#8217;s not a bad idea in its own right, but it doesn&#8217;t really solve the problem of memory management. For various reasons, interfaces and reference counting are useful for any cross language interaction, not just COM.  But even without cross language interaction, some kind of automatic memory management is still useful when using interfaces. The nature of how interfaces work is well-suited to garbage collection.  Given an interface reference, you&#8217;re not really supposed to do low-level operations on the instance. Moreover, because of the limited window into the instance but an interface provides, it is the rule rather than the exception, when working with interfaces, but an application will have multiple references to an instance.  If a particular class implements IFoo and IBar, you will very likely have one reference of each type at some point in the execution of the program.  This is in contrast to object references, where it is more common to have a single reference to an instance, since the type of that reference probably does everything you need.</p>
<p>Contrast the five different types of memory management I&#8217;ve listed with a much simpler scenario for Delphi for .NET.  There, you have only garbage collection of the heap and stack-based allocations, and they never conflict.  Your code focuses on the task at hand, rather than when and how to release each instance you create.</p>
<p>Since a few people seem to read any assertion that garbage collection could possibly have any single redeeming value as a threat to their programming worldview, I will restate that this post is not an assertion that every programmer should give up manual memory management for all tasks, forever.  Rather, it&#8217;s a description of a single feature that I like.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37785&amp;akst_action=share-this" onclick="akst_share('37785', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F22%2F37785%2F', 'Garbage+Collection+As+Unified+Memory+Management'); return false;" title="Post to del.icio.us, etc." id="akst_link_37785" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Garbage%20Collection%20As%20Unified%20Memory%20Management&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2008%2F01%2F22%2F37785%2F" id="akst_email_37785" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>GUIDs: Unfit for Public Consumption</title>
    <link>http://blogs.teamb.com/craigstuntz/2007/12/19/37782/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2007/12/19/37782/#comments</comments>
    <pubDate>Wed, 19 Dec 2007 15:03:49 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/2007/12/19/37782</guid>
    <description><![CDATA[GUIDs are like profanity: A useful item to have in your grammar when you need it, but not what you want for your public discourse.
Places where GUIDs are useful include:

Surrogate key values
Win32 Delphi interfaces
COM registration

Some places where GUIDs are  completely, utterly unfit include:

Directory names
URLs
Product registration codes

]]></description>
      <content:encoded><![CDATA[<p>GUIDs are like profanity: A useful item to have in your grammar when you need it, but not what you want for your public discourse.</p>
<p>Places where GUIDs are useful include:</p>
<ul>
<li>Surrogate key values</li>
<li>Win32 Delphi interfaces</li>
<li>COM registration</li>
</ul>
<p>Some places where GUIDs are  <em>completely, utterly unfit</em> include:</p>
<ul>
<li>Directory names</li>
<li>URLs</li>
<li>Product registration codes</li>
</ul>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37782&amp;akst_action=share-this" onclick="akst_share('37782', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2007%2F12%2F19%2F37782%2F', 'GUIDs%3A+Unfit+for+Public+Consumption'); return false;" title="Post to del.icio.us, etc." id="akst_link_37782" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=GUIDs%3A%20Unfit%20for%20Public%20Consumption&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2007%2F12%2F19%2F37782%2F" id="akst_email_37782" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Comment Spam Filters</title>
    <link>http://blogs.teamb.com/craigstuntz/2007/12/06/37781/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2007/12/06/37781/#comments</comments>
    <pubDate>Thu, 06 Dec 2007 16:21:54 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc