<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7380536</id><updated>2012-02-10T21:23:56.925+02:00</updated><category term='ethics'/><category term='C#'/><category term='coupling'/><category term='blogging tools'/><category term='WCF'/><category term='patterns'/><category term='wpf'/><category term='efficiency'/><category term='best practices'/><category term='DataGrid'/><category term='design'/><category term='syntax highlighting'/><category term='composite applications'/><category term='architecture'/><category term='gray magic'/><category term='SOA'/><category term='leadership'/><category term='threading'/><category term='.NET'/><title type='text'>You only preach what you've just discovered</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>40</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7380536.post-5937589843423958155</id><published>2011-07-04T14:14:00.003+02:00</published><updated>2011-07-04T14:44:46.057+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wpf'/><category scheme='http://www.blogger.com/atom/ns#' term='DataGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>WPF 4's DataGrid - bound template columns, anybody?</title><content type='html'>I recently had occasion to use the WPF DataGrid component introduced in .NET 4.  And here's something really stupid: all the built-in primitive column types (text, checkbox etc.) derive from a DataGridBoundColumn base type.  This allows you to specify a binding for the cell content - very logical and WPFy.&lt;br /&gt;&lt;br /&gt;The DataGridTemplateColumn is the sole exception.  I reflected the code and noticed that they're using a ContentControl internally to present the cell - so &lt;i&gt;how hard would it be&lt;/i&gt; to simply apply the binding to the Content property?  I'll tell you how hard - it's one line of code.&lt;br /&gt;&lt;br /&gt;It's seems like they've done &lt;i&gt;more work&lt;/i&gt; and added an &lt;i&gt;extra base class&lt;/i&gt; simply to make the template column less useful.&lt;br /&gt;&lt;br /&gt;Stupid.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-5937589843423958155?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/5937589843423958155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=5937589843423958155' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5937589843423958155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5937589843423958155'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2011/07/wpf-4s-datagrid-bound-template-columns.html' title='WPF 4&apos;s DataGrid - bound template columns, anybody?'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-3825981626997005046</id><published>2011-07-04T14:04:00.003+02:00</published><updated>2011-07-04T14:44:36.742+02:00</updated><title type='text'>Configuration-driven IoC why?</title><content type='html'>I've recently gone off configuration-driven IoC in a big way.  It certainly has it uses (particularly in web applications, I've found, and especially if you're selling them on).  However it makes no sense at all for desktop apps.  Usually you find that if you change the configuration, you're redeploying the app anyway - so why not have the configuration done centrally in code?  I've never seen a non-programmer change configuration, so this costs you nothing and saves you a ton of supporting infrastructure.&lt;br /&gt;&lt;br /&gt;Also, config-driven code tends to lead to the phenomenon of too much loose coupling.  Since you have to obey the container's rules about initialization, you can't make compile-time assertions about dependencies, which can lead to a sort of "fire away and hope it's there" style of programming.  And plenty of mysterious errors in apparently unrelated parts of the application.&lt;br /&gt;&lt;br /&gt;Just my two cents, I'm not feeling particularly vehement about this one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-3825981626997005046?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/3825981626997005046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=3825981626997005046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3825981626997005046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3825981626997005046'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2011/07/configuration-driven-ioc-why.html' title='Configuration-driven IoC why?'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-4777922289801145193</id><published>2010-07-10T16:19:00.003+02:00</published><updated>2010-07-10T16:22:58.180+02:00</updated><title type='text'>Global events - follow-up and sample</title><content type='html'>&lt;p&gt;After having been asked several times for an example of the new architecture I spoke about in my previous post, I've posted a sample at CodeProject - &lt;a href="http://www.codeproject.com/KB/WPF/ServiceTrees.aspx"&gt;The Service Tree Model&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;It's a short sample, and it's missing the all-important wiring-builder, but you can get an idea of how the configuration is generated and how the app uses it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-4777922289801145193?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/4777922289801145193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=4777922289801145193' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/4777922289801145193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/4777922289801145193'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2010/07/global-events-follow-up-and-sample.html' title='Global events - follow-up and sample'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-5326842620385119479</id><published>2010-06-23T12:27:00.008+02:00</published><updated>2010-06-23T13:07:08.335+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='composite applications'/><category scheme='http://www.blogger.com/atom/ns#' term='best practices'/><category scheme='http://www.blogger.com/atom/ns#' term='wpf'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Global events considered harmful</title><content type='html'>&lt;blockquote style="font-style:italic;"&gt;The “global event architecture” is what could loosely be described as an architectural pattern used principally in composite applications (such as those built using the Smart Client Software Factory or, lately, Prism). It is characterized by loosely-coupled components communicating by means of broadcast events, typically marshaled through an event broker. The events are “broadcast” events in three senses: there is little or no expectation by the sender of what will be receiving the event; a given event may originate in multiple components; and the receipt of events is usually) application-wide, i.e. not confined to any particular context. Also characteristic of this pattern is that senders are connected to recipients implicitly, by the name or the type of the event.&lt;/blockquote&gt;&lt;p&gt;In my article, "&lt;a href="http://docs.google.com/fileview?id=0B0SyTYgHGyh7ZTQzNjFjYTItNjk1MC00NzQxLWFiZmMtMTY0YmY1ZjYxOGQ4&amp;hl=en"&gt;Global events considered harmful&lt;/a&gt;", I attack the global event architecture often found in composite applications.  Having previously worked on three major applications that used the &lt;a href="http://msdn.microsoft.com/en-us/library/ff649866.aspx"&gt;Smart Client Software Factory&lt;/a&gt; architecture or derivatives, I recently was privileged to be able to design a completely new architecture suitable for WPF applications.&lt;/p&gt;&lt;p&gt;By far the largest source of problems in the composite applications I had worked on is what I call the "global event architecture".  The specific problems I identified were:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Implicit contracts are formed by the events and their arguments.&lt;/li&gt;&lt;li&gt;The contracts tend to overlap in function and meaning.&lt;/li&gt;&lt;li&gt;State is scattered throughout the application.&lt;/li&gt;&lt;li&gt;It is difficult to get a picture of the interdependencies of components, as they are implicitly coupled by the events.&lt;/li&gt;&lt;li&gt;It can be difficult to localize the events (e.g. to the scope of a single dialog or view)&lt;/li&gt;&lt;li&gt;Hanging subscriptions can cause serious application errors, and are hard to find and solve.&lt;/li&gt;&lt;li&gt;Event receipt/publication requirements in one module may force code to be written in one or more apparently unrelated modules, introducing nasty cross-cutting concerns and delocalized code.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The new architecture solved these problems, and proved to be far easier to develop on and maintain.  It is based around the idea of having a "wiring builder".  The wiring builder essentially writes a script to run just one application-level controller.  The controller constructs containers, binds component properties (including exported commands and command dependencies), and manages workflow where necessary. From the wiring builder, we can generate dependency diagrams between components, as well as workflow diagrams indicating the transitions between application states.&lt;/p&gt;&lt;p&gt;The bulk of the application consists of many simple components and services, each with a single function.  The components are written so that their dependencies can easily be mocked; this means that contracts between components are well-defined and testable, and also that it is easy to develop the components in isolation.  This also improves reusability.&lt;/p&gt;&lt;p&gt;This new architecture I call the service-tree model, and it has the following advantages:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Having a wiring manager means that applications can quickly be reconfigured in form and function, without the necessity of a binary release.&lt;/li&gt;&lt;li&gt;The wiring manager can give you a view of dependencies and workflows that corresponds to what you would see in a functional spec.&lt;/li&gt;&lt;li&gt;It's much easier to develop the individual components, because they do not rely on external events to drive their state.&lt;/li&gt;&lt;li&gt;The code has much better locality.&lt;/li&gt;&lt;li&gt;The application configuration is centralized.&lt;/li&gt;&lt;li&gt;State contracts are explicit.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If the article seems one-sided, it's because experience with the new architecture has left me absolutely convinced that I'll never again use a non-local event.  Hopefully you'll have the same experience.&lt;/p&gt;&lt;p&gt;Read: &lt;a href="http://docs.google.com/fileview?id=0B0SyTYgHGyh7ZTQzNjFjYTItNjk1MC00NzQxLWFiZmMtMTY0YmY1ZjYxOGQ4&amp;hl=en"&gt;Global events considered harmful&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-5326842620385119479?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/5326842620385119479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=5326842620385119479' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5326842620385119479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5326842620385119479'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2010/06/global-events-considered-harmful.html' title='Global events considered harmful'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-2055943573364180321</id><published>2010-05-13T17:20:00.010+02:00</published><updated>2010-05-13T17:34:25.491+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wpf'/><category scheme='http://www.blogger.com/atom/ns#' term='threading'/><title type='text'>CrossThreadAction</title><content type='html'>Here's another handy class in the spirit of WeakEventHandler.  It's useful when you want to run work on a background thread, but wish to provide a callback that will be run on your own (usually UI) thread.  Apparently Silverlight users will find this particularly useful, there being no Application.Current.Dispatcher in Silverlight, but as an almost-exclusively WPF user, I use it as helpful shorthand for "call me back on my own thread".&lt;br /&gt;&lt;br /&gt;The class:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;br /&gt;public class CrossThreadAction&amp;lt;TData&amp;gt; : DependencyObject&lt;br /&gt;{&lt;br /&gt;    Action&amp;lt;TData&amp;gt; target;&lt;br /&gt;&lt;br /&gt;    public CrossThreadAction(Action&amp;lt;TData&amp;gt; target)&lt;br /&gt;    {&lt;br /&gt;        this.target = target;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void Invoke(TData data)&lt;br /&gt;    {&lt;br /&gt;        Dispatcher.BeginInvoke(target, data);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static implicit operator Action&amp;lt;TData&amp;gt;(&lt;br /&gt;        CrossThreadAction&amp;lt;TData&amp;gt; cta)&lt;br /&gt;    {&lt;br /&gt;        return cta.Invoke;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Use it as follows:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;br /&gt;private void StartWork()&lt;br /&gt;{&lt;br /&gt;    // using a server method with signature&lt;br /&gt;    //   void DoWork(Action&amp;lt;string&amp;gt; callback);&lt;br /&gt;    server.DoWork(new CrossThreadAction&amp;lt;string&amp;gt;(FinishWork));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void FinishWork(string result)&lt;br /&gt;{&lt;br /&gt;    textBlock1.Text = result;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;WPF users may make it slightly less heavy by inheriting from DispatcherObject instead of DependencyObject.  Also, beware of storing an instance in an untyped variable; generally it's a good idea to cast it to Action&amp;lt;TData&amp;gt; as soon as you've created it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-2055943573364180321?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/2055943573364180321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=2055943573364180321' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/2055943573364180321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/2055943573364180321'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2010/05/crossthreadaction.html' title='CrossThreadAction'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-4543309509440908946</id><published>2010-05-07T12:05:00.001+02:00</published><updated>2010-05-07T12:06:58.378+02:00</updated><title type='text'>Electoral Reform in Britain</title><content type='html'>&lt;h2&gt;What’s wrong with the system&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;As anybody who has followed this election will have realised, it’s staggeringly unfair that the Liberal Democrats, with 23% of the popular vote, only got 8% of the seats.  That’s not democratic, and it entrenches the two-party system.  Do you often find it hard to distinguish between the respective policies of Labour and the Tories?  You’re not alone.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The Lib Dems want a proportional representation system.  However such systems have their own problems, the biggest being that MPs would be even less accountable to their constituencies than at present.  Think safe-seat manoeuvres on steroids.  I don’t think that will fly in a nation where constituents are used to being able to chuck out MPs they don’t like.  MPs who are unpopular with the electorate will get in by virtue of their party’s popularity rather than their own.  As Italians will attest, this leads to MPs being able to shrug off the most outrageous of scandals, provided only that they can make good with their party.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;A sensible solution&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Much better would be to implement democracy at a local level.  Suppose that each constituency elected a small parliamentary council, proportionally representative of the candidates (a Single Transferrable Vote system would do very well for these councils).  That parliamentary council would then elect a representative to sit in parliament, but – and here’s where the power really comes to the people – the council would have the power to instruct its representative on which way to vote.  That means that votes in parliament would be on the basis of what the constituencies want, rather than what the party wants.  Real democracy!&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Why this will never happen&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;The problem is this: the parties simply won’t wear it.  Being unable to whip their MPs into line, party policies would become not so much policies as guidelines.  An MP might join a party to benefit from collective think-tanks on the issues, but the real power would be taken away from the parties and given instead to the constituencies.  You like it, I like it, politicians hate it.  After all, what’s the use in being Prime Minister if you can’t tell parliament what to do?&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Nice thought, though&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Credit for this idea goes, as far as I can tell, to Sir Antony Jay and Jonathan Lynn.  Wouldn’t it be nice if politicians really did act in the interests of the people who elected them?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-4543309509440908946?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/4543309509440908946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=4543309509440908946' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/4543309509440908946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/4543309509440908946'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2010/05/electoral-reform-in-britain.html' title='Electoral Reform in Britain'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-4901873202428463337</id><published>2009-11-16T10:24:00.003+02:00</published><updated>2009-11-16T11:08:23.757+02:00</updated><title type='text'>Slow file deletion on Windows 7 RTM</title><content type='html'>The picture below says it all:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Ala3XWrpVZ0/SwETmzDY0OI/AAAAAAAAABU/BLx16T9o_u0/s1600/slow-delete.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 237px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5404622585081680098" border="0" alt="" src="http://3.bp.blogspot.com/_Ala3XWrpVZ0/SwETmzDY0OI/AAAAAAAAABU/BLx16T9o_u0/s400/slow-delete.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Of course, it didn't actually take 23 hours.  It &lt;em&gt;actually&lt;/em&gt; took about 45 minutes - that's around 13 items per second.  More than half of which was taken up by calculating how long it was going to take (estimating the quality of the calculation is left to the reader).&lt;br /&gt;&lt;br /&gt;Now I understand the need for transactional semantics during a delete, the necessity of shared filed locking, and the possibility of file system watchers getting involved in their own idiosyncratic ways.&lt;br /&gt;&lt;br /&gt;But 13 items per second?  On a 10,000 RPM drive?  Seriously, guys.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-4901873202428463337?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/4901873202428463337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=4901873202428463337' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/4901873202428463337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/4901873202428463337'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/11/slow-file-deletion-on-windows-7-rtm.html' title='Slow file deletion on Windows 7 RTM'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Ala3XWrpVZ0/SwETmzDY0OI/AAAAAAAAABU/BLx16T9o_u0/s72-c/slow-delete.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-5349207623655598023</id><published>2009-11-13T15:48:00.009+02:00</published><updated>2009-11-13T16:06:57.899+02:00</updated><title type='text'>The WeakEventHandler</title><content type='html'>When your Observer class hooks an event on an Observable, it implicitly creates a strong reference from Observable to Observer.  That means the Observer won't be collected until the Observable is.  That means memory leaks at best; latent bugs due to out-of-date observers at worst.  So I've written a little WeakEventHandler class that behaves like a weak delegate: it allows the Observer to be collected before the Observable is.  Best of all, the syntax is almost identical to the original.&lt;br /&gt;&lt;br /&gt;Instead of writing&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;observable.Event += new EventHandler&amp;lt;MyEventArgs&amp;gt;(this.HandleEvent);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;you'd write&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;observable.Event += new WeakEventHandler&amp;lt;MyEventArgs&amp;gt;(this.HandleEvent);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and the delegate behaves as if it were weak.  However there is one downside: the proxy object that is created to pass the event to the observer hangs around.  This can cause problems if the event is attached to by a great many short-lived observers.  Fortunately there is a solution:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;observable.Event += new WeakEventHandler&amp;lt;MyEventArgs&amp;gt;(this.HandleEvent,&lt;br /&gt;    handler =&amp;gt; observable.Event -= handler);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The implementation of WeakEventHandler is given below.&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;delegate void EventDetacher&amp;lt;TArgs&amp;gt;(EventHandler&amp;lt;TArgs&amp;gt; handler)&lt;br /&gt;    where TArgs : EventArgs;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class WeakEventHandler &amp;lt;TArgs&amp;gt;&lt;br /&gt;    where TArgs : EventArgs&lt;br /&gt;{&lt;br /&gt;    MethodInfo method;&lt;br /&gt;    WeakReference target;&lt;br /&gt;    EventDetacher&amp;lt;TArgs&amp;gt; detacher;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public WeakEventHandler(EventHandler&amp;lt;TArgs&amp;gt; realHandler, EventDetacher&amp;lt;TArgs&amp;gt; detacher)&lt;br /&gt;    {&lt;br /&gt;        this.method = realHandler.Method;&lt;br /&gt;        this.target = new WeakReference(realHandler.Target);&lt;br /&gt;        this.detacher = detacher;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public WeakEventHandler(EventHandler&amp;lt;TArgs&amp;gt; realHandler)&lt;br /&gt;    {&lt;br /&gt;        this.method = realHandler.Method;&lt;br /&gt;        this.target = new WeakReference(realHandler.Target);&lt;br /&gt;        this.detacher = null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    private void HandleEvent(object sender, TArgs args)&lt;br /&gt;    {&lt;br /&gt;        object realObject = target.Target;&lt;br /&gt;        if (realObject == null)&lt;br /&gt;        {&lt;br /&gt;            if (detacher != null)&lt;br /&gt;                detacher(this);&lt;br /&gt;        }&lt;br /&gt;        else&lt;br /&gt;        {&lt;br /&gt;            method.Invoke(realObject, new object[] { sender, args });&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static implicit operator EventHandler&amp;lt;TArgs&amp;gt;(WeakEventHandler&amp;lt;TArgs&amp;gt; proxy)&lt;br /&gt;    {&lt;br /&gt;        return proxy.HandleEvent;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-5349207623655598023?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/5349207623655598023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=5349207623655598023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5349207623655598023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5349207623655598023'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/11/weakeventhandler.html' title='The WeakEventHandler'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-804501235158478116</id><published>2009-09-20T17:35:00.004+02:00</published><updated>2009-09-20T18:05:37.349+02:00</updated><title type='text'>Science is not about belief</title><content type='html'>Quantum mechanics is a triumph of the scientific method over common sense.  It's weird.  Mathematically weird, and it makes deeply strange predictions.  Albert Einstein found it difficult to accept ("[God] does not play dice"), and spent many of his later years trying to disprove the theory.  Richard Feynman remarked, "I think I can safely say that nobody understands quantum mechanics."&lt;br /&gt;&lt;br /&gt;And yet it has the irritating habit of being right all the time.  And when I said right, I mean it makes predictions that are accurate to upward of 20 decimal places.  That's predictive power.&lt;br /&gt;&lt;br /&gt;The moral of the story is that you don't have to believe science to accept that it is correct.  Science can, and does, do violence to our common sense, our preconceptions, and our intuitions about the way the world works.  Yet it is always correct (within certain parameters); otherwise it wouldn't be science.&lt;br /&gt;&lt;br /&gt;Many people think that science "constantly changes its mind", and that that somehow makes it less worthy of acceptance than, say, religious dogma (which &lt;i&gt;never&lt;/i&gt; changes).  In fact the opposite is true.  Every time a scientific theory is discarded, it's because a better one has come along which explains the evidence more accurately, or over a wider range of phenomena.  That's exactly what happened to Newtonian gravity.  It wasn't that Newton was &lt;i&gt;wrong&lt;/i&gt;; rather Einstein was &lt;i&gt;more right&lt;/i&gt;.  Science is constantly improving, and that's precisely why it is so effective as a naturalistic philosophy.&lt;br /&gt;&lt;br /&gt;And then there are those poor souls who claim things like "evolution is a matter of faith, just as much as creation is!"  Rubbish.  Hogswallop.  I can't think of a word strong enough to describe just how wrong this statement is.  It's an evil perversion of the truth: &lt;i&gt;science is the opposite of faith&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Scientists don't throw the die and pray for a six.  They throw the die over and over, measure the outcomes, and conclude that each number is just as likely to occur as the others.  Or if the die is weighted, they will discover this fact.  Then they think of a hypothesis to explain the phenomenon: "since each surface of the die has an equal area, and since the density is constant, the shape guarantees equal probability of outcomes."  Once thought of, the hypothesis must be tested.  What happens if we reduce the area of one side of the die?  What if we add more sides, but ensure that they have equal area?&lt;br /&gt;&lt;br /&gt;I have no idea if the above hypothesis is correct.  Probably it isn't.  But it illustrates the &lt;i&gt;way scientists proceed&lt;/i&gt;.  The results of their experiments are often surprising.  Sometimes years of accumulated common sense have to be thrown away in a heartbeat.  It can be emotionally wrenching, especially if you have a particular attachment to an idea that now turns out to be wrong.&lt;br /&gt;&lt;br /&gt;This is the ruthless honesty of scientists: they never deny reality, no matter how hard it is to accept.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-804501235158478116?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/804501235158478116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=804501235158478116' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/804501235158478116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/804501235158478116'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/09/science-is-not-about-belief.html' title='Science is not about belief'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-6715264678916812838</id><published>2009-09-18T18:51:00.001+02:00</published><updated>2009-09-18T18:51:56.575+02:00</updated><title type='text'>Government is one big monopoly...</title><content type='html'>...which would be okay if there weren't legislative barriers to competing with it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-6715264678916812838?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/6715264678916812838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=6715264678916812838' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/6715264678916812838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/6715264678916812838'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/09/government-is-one-big-monopoly.html' title='Government is one big monopoly...'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-3015548441394134757</id><published>2009-09-11T09:58:00.000+02:00</published><updated>2009-09-11T10:00:12.556+02:00</updated><title type='text'>My favourite math joke...</title><content type='html'>e-to-the-x and constant-function were walking along happily in Mathland, when suddenly constant-function took fright and tried to hide behind e-to-the-x’s skirts.  “What’s wrong?” asked e-to-the-x, “why are you hiding?”  Constant-function replied, “because I just saw differential operator, and you know what that means.  If he gets near me I’ll be differentiated and vanish!”  “Ah, well, I’m not afraid!” declared e-to-the-x.  “What do I have to worry about?  I’m e-to-the-x!”  Boldly she marched up to differential operator.  “Hello, I’m e-to-the-x!” she announced assertively.  “Pleased to meet you,” replied differential operator – “I’m d-by-dy!”&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-3015548441394134757?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/3015548441394134757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=3015548441394134757' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3015548441394134757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3015548441394134757'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/09/my-favourite-math-joke.html' title='My favourite math joke...'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-2843905715254992751</id><published>2009-08-31T11:56:00.002+02:00</published><updated>2009-08-31T12:10:53.706+02:00</updated><title type='text'>The post hoc visitor</title><content type='html'>The &lt;a href="http://en.wikipedia.org/wiki/Visitor_pattern"&gt;visitor pattern&lt;/a&gt; is an excellent way to separate concerns, by moving operations on a hierarchy of objects out of the hierarchy itself.  Unfortunately it suffers from two major flaws:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;You need to declare and implement the Visit method on each class in the hierarchy, which is not only wasteful of code, but also impossible if you don't have control over the class hierarchy (e.g. it's in an external module).&lt;/li&gt;&lt;br /&gt; &lt;li&gt;You need to implement a receiver method for every node on every visitor, even if the visitor handles a whole sub-hierarchy in the same way.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;What to do?  Well, Python handles this extremely well.  You can inject virtual methods into the class hierarchy, even after instances have been created, as follows:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ASTNode.VisitOptimizer = classmethod(lambda t: None)&lt;br /&gt;ValueNode.VisitOptimizer = classmethod(lambda t: t.Value)&lt;br /&gt;ExpressionNode.VisitOptimizer = classmethod(optimizeExpression)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Calling node.VisitOptimizer will dispatch to the appropriate method.&lt;br /&gt;&lt;br /&gt;Can this be done in C#?  Perhaps in version 4: the jury is out.  What about extension methods, I hear you ask?  Don't bother.  Extension methods match the declared type rather than the actual type, for various good if unfortunate reasons.  In versions prior to 4, the best method I've come up with is to write a facilitator class that uses reflection to find the best (i.e. most closely-typed) method in the visitor, and calls that.  Needless to say, this is heavy.&lt;br /&gt;&lt;br /&gt;Anyone got a better idea?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-2843905715254992751?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/2843905715254992751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=2843905715254992751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/2843905715254992751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/2843905715254992751'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/08/post-hoc-visitor.html' title='The post hoc visitor'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-3484049823334212968</id><published>2009-07-04T15:28:00.000+02:00</published><updated>2009-07-04T15:39:29.609+02:00</updated><title type='text'>Creationism... and Sourceforge.</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Ala3XWrpVZ0/Sk9beQLILhI/AAAAAAAAABM/Fp47s6zMnN4/s1600-h/Creationist.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 356px; height: 373px;" src="http://3.bp.blogspot.com/_Ala3XWrpVZ0/Sk9beQLILhI/AAAAAAAAABM/Fp47s6zMnN4/s400/Creationist.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5354599057262652946" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;PS - The new Sourceforge site looks really cool.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-3484049823334212968?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/3484049823334212968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=3484049823334212968' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3484049823334212968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3484049823334212968'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/07/creationism-and-sourceforge.html' title='Creationism... and Sourceforge.'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Ala3XWrpVZ0/Sk9beQLILhI/AAAAAAAAABM/Fp47s6zMnN4/s72-c/Creationist.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-5263805349869273760</id><published>2009-06-18T14:15:00.003+02:00</published><updated>2009-06-18T14:35:42.983+02:00</updated><title type='text'>What democracy means</title><content type='html'>Earlier today, I posted a &lt;a href="http://www.youtube.com/watch?v=b-tIY99QFFk"&gt;comment on Youtube&lt;/a&gt; where I said that for me, economic liberty is not a question of efficiency or of selfishness.  Instead, it's a moral issue.  I don't believe that the majority has any right to dictate what I do with my money.  I will voluntarily donate to charity (which I think is a good idea by the way), but the point is that it is voluntary.  By what right, I asked, does any other person hold claim to my productive output?&lt;br /&gt;&lt;br /&gt;Now, rickelmonoggin responded, saying that what I had said was that I do not believe in &lt;a href="http://en.wikipedia.org/wiki/Democracy"&gt;democracy&lt;/a&gt;.  That gave me pause.  On reflection, it's true.  We believe in different versions of democracy.  His version may be loosely termed "majority rule".  My version is individual liberty.&lt;br /&gt;&lt;br /&gt;I believe the term democracy is equally applicable to both, and here's why.  The word derives from the Greek demos kratos, meaning literally "people power".  I think individual people should have power, rickelmonoggin believes the majority should have power.  The latter view is immoral in my opinion.  Taking from one person to give to another without voluntary consent is theft, no matter whether it is done by an individual or a government.  I hold that no group of individuals has any more rights than a single individual in that group.  Might does not make right, in other words.&lt;br /&gt;&lt;br /&gt;So what does my vision of democracy look like?  Let's take the example of roads.  I'd support a system where if you don't pay the road tax, you don't get to drive on the roads.  That's fair.  If you don't pay the electricity bill, you don't get electricity.  You have no right to demand that other people pay for services you enjoy.  If they willingly contribute to funding those services, that's absolutely fine.  That way, the amount of funding allocated to services is determined by the market of individual choices, rather than by a sub-committee sitting in a small room somewhere in Washington.&lt;br /&gt;&lt;br /&gt;Perhaps an instinctive reaction to this philosophy is that it is cruel and selfish.  I disagree; I think to say this is to say that man is a mean, selfish little animal, when it is perfectly clear that we're not.  The richest men in the world, Bill Gates and Warren Buffett, are also the largest contributors to charity.  They don't have to contribute, they do so voluntarily.  To me, that's a fine example of the essential good nature of humanity.&lt;br /&gt;&lt;br /&gt;Let's look at the alternative philosophy.  In the philosophy of majority rule, one implicitly accepts the principle that a group of individuals may demand unearned payment from a smaller group of individuals, provided the first group is big enough to establish a majority.  That is a cruel and unjust position to take.  By that logic, it's perfectly acceptable to enslave others, provided most people agree that it's a good idea.&lt;br /&gt;&lt;br /&gt;One of the distinguishing features of the United States is that it has a constitution that prevents precisely this sort of abuse of power.  The constitution, in fact, exists to limit majority rule.  It says that all men have inalienable rights that no decree of congress may abrogate.  The only problem, as I see it, is that it doesn't go far enough.&lt;br /&gt;&lt;br /&gt;So what do you think?  Is majority rule fair, just and moral?  Or is it just an excuse to pick the pockets of the wealthy minority?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-5263805349869273760?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/5263805349869273760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=5263805349869273760' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5263805349869273760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5263805349869273760'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/06/what-democracy-means.html' title='What democracy means'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-1593450804738483262</id><published>2009-06-15T10:07:00.002+02:00</published><updated>2009-06-15T10:42:05.632+02:00</updated><title type='text'>Science: a call to arms</title><content type='html'>We live in a world made by science. From putting on the coffee pot in the morning to switching out the lights at night, everything we do involves some or other product of science. Yet science does not ask that we pay homage to it. It does not require us to attend service or pray at its altar. We do not even have to obtain a minimum understanding of science before we make use of its products.&lt;br /&gt;&lt;br /&gt;Science does not assert truth without reason and evidence. Science does not dictate how we live our lives. The essence of science is a devotion to discovering what is real. It tolerates dissent, and absorbs change when it is clear that the existing understanding is flawed. The professional opinion of one scientist is worth more than the views of a &lt;a href="http://celestialmechanic.com/"&gt;thousand&lt;/a&gt; &lt;a href="http://www.remnantofgod.org/creation.htm"&gt;twittering&lt;/a&gt; &lt;a href="http://www.truechristian.com/dinosaurs.html"&gt;idiots&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And yet, for the very reason that it is so tolerant, science does not respond aggressively when it is &lt;a href="http://www.conservapedia.com/Relativity"&gt;pissed on&lt;/a&gt; by &lt;a href="http://www.discovery.org/"&gt;uninformed&lt;/a&gt; &lt;a href="http://creationmuseum.org/"&gt;morons&lt;/a&gt;. Science makes no philosophical comments. It is polite to its detractors. The irony is that virtually all of the anti-science, anti-reason brigade make active use of technology to opine that science is flawed, untrue or "&lt;a href="http://justatheory.org/"&gt;just a theory&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;It's time for that to change. It's time for us to teach the troglodytes just how powerful a scientific theory is. It's time to show the world that not all opinions are equal. It's time for the &lt;a href="http://www.billoreilly.com/"&gt;talking heads&lt;/a&gt; to show a little goddamned respect to science. They owe it.&lt;br /&gt;&lt;br /&gt;This is a call for scientists to stop appeasing the unwashed masses. Stop allowing them to claim that their ideas are just as valid as scientific theories. Tell them the truth: that when it comes to reality, science is the only game in town. All the rest is noise. When they whine about their personal beliefs, tell them to put up or shut up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-1593450804738483262?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/1593450804738483262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=1593450804738483262' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1593450804738483262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1593450804738483262'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/06/science-call-to-arms.html' title='Science: a call to arms'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-2971655733793325519</id><published>2009-05-30T23:35:00.001+02:00</published><updated>2009-05-30T23:37:07.223+02:00</updated><title type='text'>Amazing lack of grace</title><content type='html'>wwww.conservapedia.com.  Jesus Christ.  That's all I have to say.  Have things really gotten this bad?  Is America turning its back on rationality?  You tell me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-2971655733793325519?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/2971655733793325519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=2971655733793325519' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/2971655733793325519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/2971655733793325519'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/05/amazing-lack-of-grace.html' title='Amazing lack of grace'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-3936924249739390470</id><published>2009-04-06T11:40:00.002+02:00</published><updated>2009-04-06T11:52:54.300+02:00</updated><title type='text'>Fool me can't get fooled again</title><content type='html'>I'm not American.  But hell, it's a free internet, isn't it?  So I'm going to Opine.  Barrack Obama is better than George W. Bush, and here's why.  He's a slimy politician.  That means he says one thing and does another (what most of us would call "lying").  Okay, perhaps he's a bit more sincere than most, but power corrupts, as they say... you can't climb the greasy pole without getting a bit oily.&lt;br /&gt;&lt;br /&gt;So why do I prefer him?  Because if I'm going to be deceived, lied to, misdirected, and politicked generally, then I'd rather it be done by someone with the brains to carry out the scheme successfully.  There GWB falls flat.  If I were an American, I'd want someone on my side who was shrewd, devious, capable of pulling the wool over "them"'s eyes.  Someone like Bill Clinton, in fact.&lt;br /&gt;&lt;br /&gt;Sure, we can admire GWB for his straight-talking, shoot-from-the-hip style, even if we disagree with what he says (and I most vehemently do).  But as &lt;i&gt;president&lt;/i&gt;?  Pull the other one.  Oh wait, you already did...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-3936924249739390470?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/3936924249739390470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=3936924249739390470' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3936924249739390470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3936924249739390470'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/04/fool-me-cant-get-fooled-again.html' title='Fool me can&apos;t get fooled again'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-8285677401888613932</id><published>2009-03-06T15:37:00.002+02:00</published><updated>2009-03-06T15:44:18.789+02:00</updated><title type='text'>Transport after oil</title><content type='html'>&lt;span style="font-weight:bold;"&gt;When the oil runs out:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;I can imagine electric cars&lt;/span&gt;.  Powered ultimately by a combination of coal and nuclear energy.  Wind/water/solar will certainly proliferate as rising energy costs make them more viable, but until the coal runs out, that's where the energy is.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;I forsee nuclear shipping&lt;/span&gt;.  A ship is quite big enough to play host to a reactor, and it's a bit easier politically to put something that might blow up on a vessel that's not likely to be nearby when it does.  Anyway, reactors are getting &lt;a href="http://en.wikipedia.org/wiki/Pebble_bed_reactor"&gt;smaller and safer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;I cannot see myself flying&lt;/span&gt;.  Unless there's a radical breakthrough in propulsion and/or solar technology.  As things stand, solar panels are too inefficient, cell batteries are too heavy and other types of power plants are just too damned big.&lt;br /&gt;&lt;br /&gt;Time to sell those airline stocks?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-8285677401888613932?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/8285677401888613932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=8285677401888613932' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/8285677401888613932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/8285677401888613932'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/03/transport-after-oil.html' title='Transport after oil'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-1313233166873445097</id><published>2009-03-05T10:26:00.002+02:00</published><updated>2009-03-05T11:12:46.257+02:00</updated><title type='text'>What's currency got to do with the price of gold?</title><content type='html'>There are still some &lt;a href="http://www.goldworthfinancial.com/lewrockwell.html"&gt;loons&lt;/a&gt; out there who preach a return to the gold standard.  Yes, loons: crazy and/or simple-minded individuals.  Here's why the epithet is appropriate.&lt;br /&gt;&lt;br /&gt;The argument for the gold standard is essentially this:  currency should be backed by something with intrinsic value; gold has intrinsic value; therefore currency should be backed by gold.  Let's take the second premise first.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Gold has no intrinsic value&lt;/span&gt;.  A hunk of gold in your basement cannot feed, clothe or house you.  It is only beneficiated (given value) by the uses to which it is put.  Those uses include electronics, but primarily gold serves a decorative function, as in jewelery, souvenirs and ornamentation.  Artifacts of fashion, in fact.  Enduring fashion, to be sure, but whimsical nonetheless.&lt;br /&gt;&lt;br /&gt;Now for the first premise: is a floating currency not already backed by something of intrinsic value?  Of course it is.  The intrinsic value here is the ability to purchase the goods and produce of the economies that make use of the currency.  Backing the dollar is the American economy.  Would you trade that for the gold in Fort Knox?&lt;br /&gt;&lt;br /&gt;(On a side note, I believe this is one of the rare instances where Ayn Rand didn't carry her philosophy through to its logical conclusion.  In arguing for the gold standard, she implies that gold has productive power, much as Marx argues that factories do.  Wrong, as she herself pointed out - it's the productive powers of the individuals that count, not the materials they use.)&lt;br /&gt;&lt;br /&gt;But wait, there's more.  Coupling a currency to the value of gold is inherently dangerous, not just because that value is subject to the vagaries of fashion, but precisely because the irrational belief persists that gold has intrinsic value.  What happens to the price of gold when the stock market crashes?  It tends to go up.  Investors buy into gold (and gold producers) just as the demand for consumption of (as opposed to investment demand for) gold goes down.  Safe haven or mirage in the desert?  What happens when the economy recovers, and forward contracts are fixed at economically unsustainable prices?  You have a huge investment surplus undermining an overpriced supply-chain.  Something's gotta give.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-1313233166873445097?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/1313233166873445097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=1313233166873445097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1313233166873445097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1313233166873445097'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2009/03/whats-currency-got-to-do-with-price-of.html' title='What&apos;s currency got to do with the price of gold?'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-1228502208876482633</id><published>2008-03-08T15:50:00.004+02:00</published><updated>2008-03-08T16:03:45.262+02:00</updated><title type='text'>No big deal?</title><content type='html'>Have you ever done something "obvious" and later discovered that it's the topic of a famous paper, or something that gets put in the "advanced" section of the textbooks?&lt;br /&gt;&lt;br /&gt;I just read the &lt;a href="http://en.wikipedia.org/wiki/Tail_recursion"&gt;wikipedia article on tail recursion&lt;/a&gt;, and got a surprise when I read the last section.  &lt;br /&gt;&lt;br /&gt;I've always implemented lists in C along these lines:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;br /&gt;void insert(list_t** list, int idx, list_t* item)&lt;br /&gt;{&lt;br /&gt;  while(*list &amp;&amp; idx--)&lt;br /&gt;    list = &amp;(*list)-&gt;next;&lt;br /&gt;  item-&gt;next = *list;&lt;br /&gt;  *list = item;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now to me, this is pretty obvious stuff.  But it turns out to have a name - "tail recursion modulo cons" - and credit for its invention goes to David H. D. Warren.  Go figure.&lt;br /&gt;&lt;br /&gt;I have to ask, though - are our standards getting higher so fast that an advanced concept from twenty years ago is now not worth mentioning?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-1228502208876482633?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/1228502208876482633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=1228502208876482633' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1228502208876482633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1228502208876482633'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2008/03/no-big-deal.html' title='No big deal?'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-9018638137049727874</id><published>2008-02-22T13:22:00.001+02:00</published><updated>2008-02-22T13:25:59.117+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ethics'/><category scheme='http://www.blogger.com/atom/ns#' term='leadership'/><title type='text'>Are you a follower or a leader?</title><content type='html'>I'm neither.  Certainly not a follower, because I'm independently-minded and naturally suspicious of authority.  Nor am I a leader, because I'm not interested in shepherding my followers (and I don't expect them to agree with or obey me).&lt;br /&gt;&lt;br /&gt;On the other hand, I almost always seem to end up setting the direction, and others usually follow my lead.  Doesn't that make me a leader, and them followers?  Perhaps, but then we have to restate my original question as: are you a boss or an employee?&lt;br /&gt;&lt;br /&gt;But that was how you interpreted the question in the first place, wasn't it?&lt;br /&gt;&lt;br /&gt;;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-9018638137049727874?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/9018638137049727874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=9018638137049727874' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/9018638137049727874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/9018638137049727874'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2008/02/are-you-follower-or-leader.html' title='Are you a follower or a leader?'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-9072187500936683423</id><published>2008-02-22T12:25:00.005+02:00</published><updated>2008-02-26T11:15:43.613+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='efficiency'/><category scheme='http://www.blogger.com/atom/ns#' term='threading'/><title type='text'>Efficient singleton initialization with Interlocked</title><content type='html'>We had (are still having) an interesting discussion over at &lt;a href="http://www.janus-net.de/2008/01/10/double-checked-locking-in-c/"&gt;Sven-Torben Janus's blog&lt;/a&gt;.  The discussion is about singletons, but it reminded me of a pattern I've used which has more general application.  This is how it might be used to initialize a singleton:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;br /&gt;using System.Threading;&lt;br /&gt;&lt;br /&gt;public class Singleton&lt;br /&gt;{&lt;br /&gt;  private Singleton() { /* ... */ }&lt;br /&gt;&lt;br /&gt;  const int NotInitialized = 0;&lt;br /&gt;  const int Initializing = 1;&lt;br /&gt;  const int Initialized = 2;&lt;br /&gt;  static int state;&lt;br /&gt;  static Singleton instance;&lt;br /&gt;&lt;br /&gt;  public static Singleton Instance&lt;br /&gt;  {&lt;br /&gt;    get&lt;br /&gt;    {&lt;br /&gt;      if (instance != null)&lt;br /&gt;        return instance;&lt;br /&gt;      while (true)&lt;br /&gt;      {&lt;br /&gt;        switch (Interlocked.CompareExchange(ref state, Initializing, NotInitialized))&lt;br /&gt;        {&lt;br /&gt;        case NotInitialized:&lt;br /&gt;          Interlocked.Exchange(ref instance, new Singleton());&lt;br /&gt;          Interlocked.Exchange(ref state, Initialized);&lt;br /&gt;          return instance;&lt;br /&gt;        case Initializing:&lt;br /&gt;          Thread.Sleep(0);  // yield and loop until initialization is finished&lt;br /&gt;          break;&lt;br /&gt;        case Initialized:&lt;br /&gt;          return instance;  // does this need to be interlocked?&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This is a much cheaper pattern than the Java-style double-checked locking pattern (which doesn't work on the CLR).  However, I wouldn't use it to initialize singletons, because the CLR already guarantees lazy first-time initialization for static members!  Which means that all you need do is this:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;br /&gt;public class Singleton&lt;br /&gt;{&lt;br /&gt;  static Singleton instance = new Singleton();&lt;br /&gt;  public static Singleton Instance { get { return instance; } }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;However, the pattern is still useful.  I use it for service initialization, for example where I have to run a costly database query before I can start responding to service requests:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;br /&gt;public void GuardInitialized()&lt;br /&gt;{&lt;br /&gt;  switch (Interlocked.CompareExchange(ref state, Initializing, NotInitialized))&lt;br /&gt;  {&lt;br /&gt;    case NotInitialized:&lt;br /&gt;      ThreadPool.QueueUserWorkItem(this.CostlyInitializationFunction);&lt;br /&gt;      throw new FaultException&lt;ServerNotReady&gt;(new ServerNotReady());&lt;br /&gt;    case Initializing:&lt;br /&gt;      throw new FaultException&lt;ServerNotReady&gt;(new ServerNotReady());&lt;br /&gt;    case Initialized:&lt;br /&gt;      break;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;As always, your mileage may vary.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Update:&lt;/strong&gt; Some actual timing tests revealed this this wasn't so efficient after all.  In fact, until I added the "if (instance != null) return instance;" check to the singleton example, it was actually slower than lock() or memory barrier techniques!  With the check, it's faster, but only by 5-10%.  The JITter doesn't recognized the interlocked operations as intrinsic and inline them.  I suspect that the unexpectedly slow performance is due to pinning and CLR synchronization overhead.  Would anyone in the know like to comment?&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Further update:&lt;/strong&gt; I exchanged a few mails with Rico Mariani, and learned that the Monitor primitive actually implements a lock-promotion protocol.  Which means that unless there's actually contention for the lock, it's effectively the same thing as an InterlockedCompareExchange operation.  So for all practical purposes, lock() and Interlocked.CompareExchange are equivalent.  The only time you'll see a real performance difference is when you're writing code where contention is actually a significant factor.  So there you go :-).&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-9072187500936683423?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/9072187500936683423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=9072187500936683423' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/9072187500936683423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/9072187500936683423'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2008/02/efficient-singleton-initialization-with.html' title='Efficient singleton initialization with Interlocked'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-6577629398497403165</id><published>2008-02-18T12:08:00.004+02:00</published><updated>2008-02-18T12:24:03.527+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogging tools'/><category scheme='http://www.blogger.com/atom/ns#' term='syntax highlighting'/><title type='text'>Formatting code blocks in blogs</title><content type='html'>Trying to add nice code samples to blogs can be a bit frustrating.  So I wrote a little bit of Javascript to deal with the problem.  Feel free to leech (it's in the source for this page).  If you make any interesting improvements, let me know!&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;!--&lt;br /&gt;public class Example&lt;T&gt;&lt;br /&gt;{&lt;br /&gt;  public void Main(string[] args)&lt;br /&gt;  {&lt;br /&gt;    for (int i = 0; i &lt; args.Length; ++i)&lt;br /&gt;      Console.WriteLine("Arg {0} is: {1}", i, args[i]);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;--&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-6577629398497403165?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/6577629398497403165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=6577629398497403165' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/6577629398497403165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/6577629398497403165'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2008/02/formatting-code-blocks-in-blogs.html' title='Formatting code blocks in blogs'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-1592791228972170795</id><published>2008-02-15T17:41:00.009+02:00</published><updated>2008-02-20T18:41:58.110+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='best practices'/><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='coupling'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Shared APIs, part 1 of 4: The why and the how</title><content type='html'>So you're writing a three- (or more) tier application.  This is probably &lt;em&gt;the&lt;/em&gt; most common application architecture, so you're in good (or at least well-populated) company.  What I'm going to advocate now is the "shared API" pattern.&lt;br /&gt;&lt;br /&gt;Let's get the most obvious objection out of the way first.  "But," you say, "surely in a service-orientated architecture we want loose coupling?  Doesn't a shared API break that principle?"&lt;br /&gt;&lt;br /&gt;The answer is yes and no.  Yes, a shared API does create tighter coupling &lt;em&gt;at compile time&lt;/em&gt;, but provided the service contract doesn't change (and it shouldn't, after a public release), you are still going to be loosely-coupled at run-time.  That is to say, you don't have to update the client software every time you rebuild the service layer, and vice versa.&lt;br /&gt;&lt;br /&gt;This is really the best of both worlds.  You &lt;em&gt;want&lt;/em&gt; tight coupling at compile time, to prevent your domain model from being (a) duplicated and hence (b) susceptible to client/server drift.  Conversely, at run-time you really want the coupling to be loose, to prevent your users from getting frustrated with having to upgrade their software all the time.&lt;br /&gt;&lt;br /&gt;There are other objections to shared APIs, but I believe that they stem principally from bad design and implementation.  The basic idea of a shared API is that you have to define your service contract &lt;em&gt;up-front&lt;/em&gt;; so arguing against it on the grounds that it makes life difficult for programmers when they want to just make a little change to the domain model or service contract is, in fact, rather perverse.  After all, isn't defining your domain model first one of the most rudimentary design principles?&lt;br /&gt;&lt;br /&gt;So now the question becomes, what does a shared-API architecture look like?  I'll use WCF to illustrate.  There are really two parts to a shared API: the service/data contract and the model.&lt;br /&gt;&lt;br /&gt;Let's start with the model.  You can do it the other way around, but that sometimes leads to problems later on.  Step one is to create a set of interfaces (or abstract classes if you like) that represent your system:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;!--&lt;br /&gt;public interface ICredentialedEntity&lt;br /&gt;{&lt;br /&gt;    string Name { get; }&lt;br /&gt;    string SecurityCode { get; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface IUser : ICredentialedEntity&lt;br /&gt;{&lt;br /&gt;    IGroup[] Groups { get; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface IGroup : ICredentialedEntity&lt;br /&gt;{&lt;br /&gt;    ICredentialedEntity[] Members { get; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface IProcessStep&lt;br /&gt;{&lt;br /&gt;    string Name { get; }&lt;br /&gt;    IProcessStep PreviousStep { get; }&lt;br /&gt;    IProcessStep NextStep { get; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface IProcess&lt;br /&gt;{&lt;br /&gt;    ICredentialedEntity Owner { get; }&lt;br /&gt;    IProcessStep CurrentStep { get; }&lt;br /&gt;    IDictionary&lt;string, object&gt; DataFields { get; }&lt;br /&gt;}&lt;br /&gt;--&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The purpose of this exercise is to get the model right.  At this point we are not considering efficiency or implementation constraints.  The only concern is with the informational content of and structural relationships between the entities.&lt;br /&gt;&lt;br /&gt;Entity relationships can be subtle things.  Everybody's heard of "one-to-one", "one-to-many" and "many-to-many", but there's much more to the story.  One important question to answer is that of ownership.  An object may link to a set of sub-objects, but it doesn't necessarily "own" them.  If a sub-object might be shared between two parents, it's almost certainly not an "owning" relationship.  The other question is that of visibility.  Is the child aware of its parent?  (Why?)  Does the parent know about its children?  Answering these questions is often more of an art than a science, and volumes could be written about the different approaches that are taken.&lt;br /&gt;&lt;br /&gt;At any rate, there are generally three types of relationship: parent contains an array of children, parent points to child(ren), and child points to parent.  Each implies different ownership and visibility semantics.&lt;br /&gt;&lt;br /&gt;Having satisfied ourselves that the domain model is correct, we now turn our attention to the use cases.  Each step in a use case could potentially involve the invocation of a service or services.  The question that must be answered is: "what data must be passed in which direction at this point?"  This is often easy, as in the case of data that is specified to appear on a particular screen, but it can be very much more complicated - as in, what are the services required to update a form or document?&lt;br /&gt;&lt;br /&gt;Transactions must also be considered at this point, not only in terms of the guarantees your system must make, but also in terms of the architecture you intend to use.  For example, if you use MSDTC to manage your transactions, then outbound transaction flow must be enabled on all the client machines.  This could be an administrative and/or security problem, in which case you might be better off changing your service model to explicitly include Begin/Commit/Rollback operations.&lt;br /&gt;&lt;br /&gt;Once you've identified the services you require, and consolidated them as appropriate ("as simple as possible, but not simpler"), you're ready to write your service contract.  There is generally an intersection between your domain model and your service contract.  Try not to focus too much on this!  Remember that the service model is a completely different thing from the domain model.  Services operate in a specific context, whereas domain entities are abstract and generalized.&lt;br /&gt;&lt;br /&gt;Here's an example of a service contract for the domain I described above:&lt;br /&gt;&lt;br /&gt;&lt;code class="csharp"&gt;&lt;!--&lt;br /&gt;[ServiceContract]&lt;br /&gt;public interface IWorkflowManager&lt;br /&gt;{&lt;br /&gt;  // gets processes directly assigned to the specified user&lt;br /&gt;  [OperationContract]&lt;br /&gt;  ProcessHeader[] GetProcessesOwnedByUser(UserRef user);&lt;br /&gt;&lt;br /&gt;  // gets processes assigned to groups that the specified user belongs to&lt;br /&gt;  [OperationContract]&lt;br /&gt;  ProcessHeader[] GetGroupProcessesByUser(UserRef user);&lt;br /&gt;&lt;br /&gt;  // returns all the data for a specified process&lt;br /&gt;  [OperationContract]&lt;br /&gt;  ProcessFieldValue[] GetProcessData(ProcessRef process);&lt;br /&gt;  &lt;br /&gt;  [OperationContract]&lt;br /&gt;  ProcessFieldValue[] GetPartialProcessData(ProcessRef process, params string[] fields);&lt;br /&gt;&lt;br /&gt;  [OperationContract]&lt;br /&gt;  void AdvanceProcess(CredentialedRef nextOwner);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract]&lt;br /&gt;public class ProcessRef&lt;br /&gt;{&lt;br /&gt;  [DataMember] int processId;&lt;br /&gt;&lt;br /&gt;  public int ProcessId { get { return processId; } }&lt;br /&gt;&lt;br /&gt;  public ProcessRef(int processId)&lt;br /&gt;  {&lt;br /&gt;    this.processId = processId;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract]&lt;br /&gt;public class ProcessHeader : ProcessRef&lt;br /&gt;{&lt;br /&gt;  [DataMember] CredentialedHeader owner;&lt;br /&gt;  [DataMember] string title;&lt;br /&gt;&lt;br /&gt;  public CredentialedHeader Owner { get { return owner; } }&lt;br /&gt;  public string Title { get { return title; } }&lt;br /&gt;&lt;br /&gt;  public ProcessHeader(int processId, CredentialedHeader owner, string title)&lt;br /&gt;    : base(processId)&lt;br /&gt;  {&lt;br /&gt;    this.owner = owner;&lt;br /&gt;    this.title = title;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract, KnownType(typeof(UserRef)), KnownType(typeof(GroupRef))]&lt;br /&gt;public abstract class CredentialedRef&lt;br /&gt;{&lt;br /&gt;  [DataMember] string securityCode;&lt;br /&gt;&lt;br /&gt;  public string SecurityCode { get { return securityCode; } }&lt;br /&gt;&lt;br /&gt;  public CredentialedRef(string securityCode)&lt;br /&gt;  {&lt;br /&gt;    this.securityCode = securityCode;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract]&lt;br /&gt;public class UserRef : CredentialedRef&lt;br /&gt;{&lt;br /&gt;  public UserRef(string securityCode) : base(securityCode) { }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract]&lt;br /&gt;public class GroupRef : CredentialedRef&lt;br /&gt;{&lt;br /&gt;  public GroupRef(string securityCode) : base(securityCode) { }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract, KnownType(typeof(UserHeader)), KnownType(typeof(GroupHeader))]&lt;br /&gt;public abstract class CredentialedHeader : CredentialedRef&lt;br /&gt;{&lt;br /&gt;  [DataMember] string name;&lt;br /&gt;&lt;br /&gt;  public string Name { get { return name; } }&lt;br /&gt;&lt;br /&gt;  public CredentialedHeader(string securityCode, string name)&lt;br /&gt;    : base(securityCode)&lt;br /&gt;  {&lt;br /&gt;    this.name = name;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract]&lt;br /&gt;public class UserHeader : CredentialedHeader&lt;br /&gt;{&lt;br /&gt;  public UserHeader(string securityCode, string name)&lt;br /&gt;    : base(securityCode, name)&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract]&lt;br /&gt;public class GroupHeader : CredentialedHeader&lt;br /&gt;{&lt;br /&gt;  public GroupHeader(string securityCode, string name)&lt;br /&gt;    : base(securityCode, name)&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataContract]&lt;br /&gt;public class ProcessFieldValue&lt;br /&gt;{&lt;br /&gt;  [DataMember] string fieldName;&lt;br /&gt;  [DataMember] string clrTypeName;&lt;br /&gt;  [DataMember] string textValue;&lt;br /&gt;&lt;br /&gt;  public string FieldName { get { return fieldName; } }&lt;br /&gt;&lt;br /&gt;  public object Value&lt;br /&gt;  {&lt;br /&gt;    get&lt;br /&gt;    {&lt;br /&gt;      return Convert.ChangeType(textValue, Type.GetType(clrTypeName));&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public ProcessFieldValue(string fieldName, object value)&lt;br /&gt;  {&lt;br /&gt;    this.fieldName = fieldName;&lt;br /&gt;    this.clrTypeName = value.GetType().AssemblyQualifiedName;&lt;br /&gt;    this.textValue = (string)Convert.ChangeType(value, typeof(string));&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;--&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next time I'll talk about the implementation aspects of shared APIs as they relate to their client and server consumers, and also about the limitations of object orientated languages in this respect.  Those familiar with WCF will probably have noticed some problems with the code above, and can therefore anticipate what is coming...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-1592791228972170795?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/1592791228972170795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=1592791228972170795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1592791228972170795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/1592791228972170795'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2008/02/shared-apis-part-1-of-4-why-and-how.html' title='Shared APIs, part 1 of 4: The why and the how'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-5744815588769374056</id><published>2008-02-15T17:36:00.002+02:00</published><updated>2008-02-15T17:40:31.307+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gray magic'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Slicing objects; or, when you only want to pass the piece the method wants</title><content type='html'>I humbly refer you to &lt;a href="http://www.janus-net.de/2008/01/13/wcf-slicing-objects-on-serialization/trackback/"&gt;this post&lt;/a&gt; by Sven-Torben Janus, and add only the following helpful hint: System.Runtime.Serialization.FormatterServices.GetUninitializedObject().&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-5744815588769374056?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/5744815588769374056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=5744815588769374056' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5744815588769374056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/5744815588769374056'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2008/02/slicing-objects-or-when-you-only-want.html' title='Slicing objects; or, when you only want to pass the piece the method wants'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-3245430219104613102</id><published>2007-12-10T10:46:00.000+02:00</published><updated>2007-12-10T10:49:56.460+02:00</updated><title type='text'>Short-lived object manager</title><content type='html'>&lt;p&gt;I don't know if I'm re-inventing the wheel here, but I refactored a couple of server-side objects to arrive at this base class:&lt;/p&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Threading;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; ShortLived : IDisposable&lt;br /&gt;{&lt;br /&gt;    Guid key;&lt;br /&gt;    DateTime lastAccess = DateTime.Now;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; disposed = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; Timer gcThread = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; Dictionary&amp;lt;Guid, ShortLived&amp;gt; objects = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;Guid, ShortLived&amp;gt;();&lt;br /&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; TimeSpan Lifetime = TimeSpan.FromMinutes(5);&lt;br /&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; TimeSpan GcInterval = TimeSpan.FromMinutes(1);&lt;br /&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; syncRoot = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Guid Key&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; key;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; SyncRoot&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; syncRoot;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; T GetObject&amp;lt;T&amp;gt;(Guid key) &lt;span class="kwrd"&gt;where&lt;/span&gt; T : ShortLived&lt;br /&gt;    {&lt;br /&gt;        ShortLived result = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (objects.TryGetValue(key, &lt;span class="kwrd"&gt;out&lt;/span&gt; result))&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; result &lt;span class="kwrd"&gt;as&lt;/span&gt; T;&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;default&lt;/span&gt;(T);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; GetObjects&amp;lt;T&amp;gt;() &lt;span class="kwrd"&gt;where&lt;/span&gt; T : ShortLived&lt;br /&gt;    {&lt;br /&gt;        List&amp;lt;T&amp;gt; results = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;T&amp;gt;();&lt;br /&gt;        &lt;span class="kwrd"&gt;lock&lt;/span&gt; (SyncRoot)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ShortLived obj &lt;span class="kwrd"&gt;in&lt;/span&gt; objects.Values)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (obj &lt;span class="kwrd"&gt;is&lt;/span&gt; T)&lt;br /&gt;                    results.Add((T)obj);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; results;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;void&lt;/span&gt; IDisposable.Dispose()&lt;br /&gt;    {&lt;br /&gt;        Dispose(Interlocked.CompareExchange(&lt;span class="kwrd"&gt;ref&lt;/span&gt; disposed, 1, 0) == 1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose(&lt;span class="kwrd"&gt;bool&lt;/span&gt; disposed)&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; ShortLived()&lt;br /&gt;    {&lt;br /&gt;        key = Guid.NewGuid();&lt;br /&gt;        Init();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; ShortLived(Guid key)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.key = key;&lt;br /&gt;        Init();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Init()&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;lock&lt;/span&gt; (SyncRoot)&lt;br /&gt;            objects.Add(key, &lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br /&gt;        Timer newCollector = &lt;span class="kwrd"&gt;new&lt;/span&gt; Timer(GarbageCollect, &lt;span class="kwrd"&gt;null&lt;/span&gt;, GcInterval, GcInterval);&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (Interlocked.CompareExchange(&lt;span class="kwrd"&gt;ref&lt;/span&gt; gcThread, newCollector, &lt;span class="kwrd"&gt;null&lt;/span&gt;) == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            gcThread.Change(GcInterval, GcInterval);&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            newCollector.Dispose();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; KeepAlive()&lt;br /&gt;    {&lt;br /&gt;        lastAccess = DateTime.Now;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; GarbageCollect(&lt;span class="kwrd"&gt;object&lt;/span&gt; context)&lt;br /&gt;    {&lt;br /&gt;        List&amp;lt;Guid&amp;gt; expired = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Guid&amp;gt;();&lt;br /&gt;        DateTime now = DateTime.Now;&lt;br /&gt;        &lt;span class="kwrd"&gt;lock&lt;/span&gt; (SyncRoot)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (KeyValuePair&amp;lt;Guid, ShortLived&amp;gt; kv &lt;span class="kwrd"&gt;in&lt;/span&gt; objects)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (now - kv.Value.lastAccess &amp;gt; Lifetime)&lt;br /&gt;                    expired.Add(kv.Key);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Guid key &lt;span class="kwrd"&gt;in&lt;/span&gt; expired)&lt;br /&gt;            {&lt;br /&gt;                IDisposable obj = objects[key];&lt;br /&gt;                objects.Remove(key);&lt;br /&gt;                obj.Dispose();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (objects.Count == 0)&lt;br /&gt;            {&lt;br /&gt;                gcThread.Change(Timeout.Infinite, Timeout.Infinite);&lt;br /&gt;                Interlocked.Exchange(&lt;span class="kwrd"&gt;ref&lt;/span&gt; gcThread, &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;To use, just inherit from ShortLived, and call KeepAlive whenever the object is accessed.  &lt;em&gt;Don't&lt;/em&gt; store references to your object; store a reference to its Key property, and use that to look it up when you want it again.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-3245430219104613102?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/3245430219104613102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=3245430219104613102' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3245430219104613102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/3245430219104613102'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2007/12/short-lived-object-manager.html' title='Short-lived object manager'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-8960085292782497941</id><published>2007-12-05T15:27:00.000+02:00</published><updated>2007-12-10T10:53:57.204+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>WCF Services alongside legacy ASMX</title><content type='html'>I guess the situation I found myself in recently is pretty common.  So we have an intranet application which uses .NET 1.1 webservices hosted in IIS 6.  Now we want to add a new batch of WCF services, without clobbering the environment too much.  Transaction support is definitely a must, and obviously we need to be able to determine the client's credentials.  There's a lot of legacy code that refers to HttpContext.Current.User.Identity.Name.  Sounds familiar?&lt;br /&gt;&lt;br /&gt;Right, so the first thing you discover is that only http bindings are supported when the service is hosted in IIS.  So you try basicHttpBinding, but that doesn't support transactions.  That leaves wsHttpBinding.  Now you get an error along the lines of "the service requires Anonymous access but it is not configured in IIS..."  After a bit of digging, you find out that IIS is set up for NTLM authentication only.  wsHttpBinding supports this, but only at a transport level.  Which means https.  So you hack up a certificate for the server and get everything working, but... now transactions can't be flowed because the DTC doesn't have WS-AtomicTransaction support enabled.  More research, and it looks like getting this to happen involves a certificate for &lt;span style="font-style:italic;"&gt;every single client&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;It was about that time that I noticed that girl scout was 6 storeys... I mean I decided to look for alternatives.  To cut a long story short, here's my web.config:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;  &amp;lt;system.serviceModel&amp;gt;&lt;br /&gt;    &amp;lt;serviceHostingEnvironment aspNetCompatibilityEnabled="true"/&amp;gt;&lt;br /&gt;    &amp;lt;bindings&amp;gt;&lt;br /&gt;      &amp;lt;customBinding&amp;gt;&lt;br /&gt;        &amp;lt;binding name="iisat"&amp;gt;&lt;br /&gt;          &amp;lt;transactionFlow transactionProtocol="OleTransactions"/&amp;gt;&lt;br /&gt;          &amp;lt;textMessageEncoding/&amp;gt;&lt;br /&gt;          &amp;lt;httpTransport authenticationScheme="Ntlm"/&amp;gt;&lt;br /&gt;        &amp;lt;/binding&amp;gt;&lt;br /&gt;      &amp;lt;/customBinding&amp;gt;&lt;br /&gt;    &amp;lt;/bindings&amp;gt;&lt;br /&gt;    &amp;lt;services&amp;gt;&lt;br /&gt;      &amp;lt;service name="(censored)"&amp;gt;&lt;br /&gt;        &amp;lt;endpoint&lt;br /&gt;          address=""&lt;br /&gt;          binding="customBinding"&lt;br /&gt;          bindingConfiguration="iisat"&lt;br /&gt;          contract="(censored)" /&amp;gt;&lt;br /&gt;      &amp;lt;/service&amp;gt;&lt;br /&gt;    &amp;lt;/services&amp;gt;&lt;br /&gt;  &amp;lt;/system.serviceModel&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You're also going to want to apply the AspNetCompatibilityRequirementsAttribute to your service implementations.  That gets you access to HttpContext.  Also you need to ensure that the DTC is configured for network access on all participating machines (including the clients).  This is a bit of a pain, but the relevant configuration is at Control Panel/Administrative Tools/Component Services.  Under Component Services/Computers, right-click on My Computer and choose properties.  There's an MSDTC tab.  Click "Security Configuration" and check the relevant tick boxes.  Bear in mind that the &lt;em&gt;client&lt;/em&gt; generally initiates and therefore hosts the transaction.&lt;br /&gt;&lt;br /&gt;HTH.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-8960085292782497941?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/8960085292782497941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=8960085292782497941' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/8960085292782497941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/8960085292782497941'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2007/12/wcf-services-alongside-legacy-asmx.html' title='WCF Services alongside legacy ASMX'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-81217787037790915</id><published>2007-11-29T19:35:00.000+02:00</published><updated>2007-11-29T20:02:01.619+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>WCF: Contract-level FaultContract</title><content type='html'>The FaultContract attribute can only be applied to operations.  This is great for requiring the programmer to be explicit when defining the contract.  However, sometimes we want to indicate that &lt;em&gt;every&lt;/em&gt; operation in a contract may raise a set of "standard" faults.  It's a real pain to mark each operation with the appropriate fault contracts; furthermore it can make the contract very messy, and it's very easy to forget to specify the standard faults.&lt;br /&gt;&lt;br /&gt;So what we really want is a contract-level fault attribute; something like "ContractFault(typeof(Message))".  Or perhaps even better, a "StandardFaults" attribute.&lt;br /&gt;&lt;br /&gt;It turns out that this can be done, but only in a way that according to the MSDN "may result in undefined behavior".  Oh well.  Undefined behavior, here we come.&lt;br /&gt;&lt;br /&gt;The way to do it is to define an attribute that implements IContractBehavior.  This attribute will allow us to insert behavior both when we're starting the service host, and when we're creating a client proxy.  Handily, this approach also affects the WSDL metadata that is exported, so non-WCF clients can work with our services too.  Here's what the StandardFaultsAttribute looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre style="margin: 10px; padding: 10px;"&gt;&lt;br /&gt;[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]&lt;br /&gt;public class StandardFaultsAttribute : Attribute, IContractBehavior&lt;br /&gt;{&lt;br /&gt;    // this is a list of our standard fault detail classes.&lt;br /&gt;    static Type[] Faults = new Type[]&lt;br /&gt;    {&lt;br /&gt;        typeof(AuthFailure),&lt;br /&gt;        typeof(UnexpectedException),&lt;br /&gt;        typeof(UserFriendlyError)&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    public void AddBindingParameters(&lt;br /&gt;        ContractDescription contractDescription,&lt;br /&gt;        ServiceEndpoint endpoint,&lt;br /&gt;        BindingParameterCollection bindingParameters)&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ApplyClientBehavior(&lt;br /&gt;        ContractDescription contractDescription,&lt;br /&gt;        ServiceEndpoint endpoint,&lt;br /&gt;        ClientRuntime clientRuntime)&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ApplyDispatchBehavior(&lt;br /&gt;        ContractDescription contractDescription,&lt;br /&gt;        ServiceEndpoint endpoint,&lt;br /&gt;        DispatchRuntime dispatchRuntime)&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void Validate(&lt;br /&gt;        ContractDescription contractDescription,&lt;br /&gt;        ServiceEndpoint endpoint)&lt;br /&gt;    {&lt;br /&gt;        foreach (OperationDescription op in contractDescription.Operations)&lt;br /&gt;        {&lt;br /&gt;            foreach (Type fault in Faults)&lt;br /&gt;            {&lt;br /&gt;                op.Faults.Add(MakeFault(fault));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private FaultDescription MakeFault(Type detailType)&lt;br /&gt;    {&lt;br /&gt;        string action = detailType.Name;&lt;br /&gt;        DescriptionAttribute description = (DescriptionAttribute)&lt;br /&gt;            Attribute.GetCustomAttribute(detailType, typeof(DescriptionAttribute));&lt;br /&gt;        if (description != null)&lt;br /&gt;            action = description.Description;&lt;br /&gt;        FaultDescription fd = new FaultDescription(action);&lt;br /&gt;        fd.DetailType = detailType;&lt;br /&gt;        fd.Name = detailType.Name;&lt;br /&gt;        return fd;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There are a couple of things to note about this implementation.  First, we actually have to instantiate a new FaultDescription object for each fault on each operation.  There's no way to share FaultDescriptions between operations.  Second, we use the DescriptionAttribute of the detail class (if it's there) to set the Action for the fault.  This gives relatively friendly FaultException&lt;&gt; messages.  Third, the "undefined behavior" I mentioned is the act of modifying the contractDescription in the Validate method.  We're technically not allowed to do that.  But it works.&lt;br /&gt;&lt;br /&gt;To use our new attribute, we simply apply it to the service contract:&lt;br /&gt;&lt;br /&gt;&lt;pre style="margin: 10px; padding: 10px;"&gt;&lt;br /&gt;[ServiceContract, StandardFaults]&lt;br /&gt;public interface IMyService&lt;br /&gt;{&lt;br /&gt;    // ....&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And we're done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-81217787037790915?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/81217787037790915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=81217787037790915' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/81217787037790915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/81217787037790915'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2007/11/wcf-contract-level-faultcontract.html' title='WCF: Contract-level FaultContract'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-7913224862358452735</id><published>2007-10-03T17:11:00.000+02:00</published><updated>2007-10-03T17:44:18.092+02:00</updated><title type='text'>Some observations on good and evil</title><content type='html'>Some quick notes before I forget.  These issues were interesting to me once upon a time.&lt;br /&gt;&lt;br /&gt;Good and evil can only be defined with respect to a moral philosophy.  One can choose to act in accordance with a given morality (good) or against it (evil).  The basis of Christian morality lies in that wonderful and wonderfully ambiguous statement "God is good".  Of course, the nature of God (and therefore of goodness) is defined by church canon.  To my way of thinking, this makes Christian goodness a dangerously arbitrary standard, and one that is highly susceptible to manipulation.&lt;br /&gt;&lt;br /&gt;Is there a first-principles derivation of morality available?  Kant seemed to think so.  I tend to disagree.  My own position is unclear, but I'm inclined towards adopting a gene-centric attitude.  Societal mores develop along lines that are fitted to genetic and memetic survival.  Of course, I am in a position to reason out the consequences of an action in a way that, with any luck, can overcome the limitations of impulsive or instinctive evolved morality.  In other words, it sometimes makes sense to be evil.  The a priori good guys don't always win.  The ultimate winners redefine the concept of good.&lt;br /&gt;&lt;br /&gt;In summary: I see morality as a problem in the domain of game theory.  By Christian standards, I am quite evil.  I'm fine with that.&lt;br /&gt;&lt;br /&gt;"It's a philosophical choice", said Dr Smith.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-7913224862358452735?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/7913224862358452735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=7913224862358452735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/7913224862358452735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/7913224862358452735'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2007/10/some-observations-on-good-and-evil.html' title='Some observations on good and evil'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-117075988234095260</id><published>2007-02-06T13:01:00.000+02:00</published><updated>2007-02-06T13:04:42.366+02:00</updated><title type='text'>Free games</title><content type='html'>I wrote versions of Scrabble and Sudoku in C# for fun.  Both have interesting AIs (computer opponents), which is why I did them.  Download at &lt;a href="http://www.informationlogistics.co.za/games"&gt;http://www.informationlogistics.co.za/games&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-117075988234095260?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/117075988234095260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=117075988234095260' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/117075988234095260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/117075988234095260'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2007/02/free-games.html' title='Free games'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-109757349744191359</id><published>2005-09-27T11:44:00.000+02:00</published><updated>2005-09-27T11:49:02.233+02:00</updated><title type='text'>Some thoughts on database design</title><content type='html'>I occasionally like to read &lt;a href="http://www.joelonsoftware.com/"&gt;Joel on Software&lt;/a&gt;, a sensible site which ought to be required reading for software company managers.  However, today I found some things in the &lt;a href="http://www.joelonsoftware.com/RandomStuff/copilot_spec.pdf"&gt;Aardvark spec&lt;/a&gt; (PDF) which I strongly disagree with.&lt;br /&gt;&lt;br /&gt;Microsoft Access has done some terrible damage to the world of database design. By far the most pernicious effect has been the AutoNumber phenomenon. I've lost track of the number of databases I've seen with foolishness like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; tblCountry (&lt;br /&gt;   CountryID autonumber primary key,&lt;br /&gt;   CountryCode char(2),&lt;br /&gt;   CountryName varchar(50))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What's wrong with this design?  Let me give you a hint.  Here are two rows from an actual database I've worked with:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; 65, 'DE', 'Germany'&lt;br /&gt; 218, 'DE', 'GERMANY, FEDERAL REPUBLIC OF'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Oh dear, oh dear.  A better design for this table is of course:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; tblCountry (&lt;br /&gt;   CountryCode char(2) primary key,&lt;br /&gt;   CountryName varchar(50))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Books have been written about designing tables, but here is a simple rule:  start with the fields you &lt;i&gt;need&lt;/i&gt;, and see if you can find a candidate key amongst them. If you can't, chances are your table doesn't need a primary key in the first place. Here's an example of such a table:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; InvoiceEntries (&lt;br /&gt;   InvoiceNumber int references Invoices (InvoiceNumber),&lt;br /&gt;   ItemCode char(4) references Items (ItemCode),&lt;br /&gt;   Quantity int);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you really, really need to be able to uniquely identify each tuple (row), then an autonumber PK is an option. But in general I try to avoid them at all costs. Here's the reason: autonumber PKs are meaningless. What does CountryID=143 signify? What country is that? If you can't look at the rows of your table and make sense of all the data in one reading, you're in a bad place as a DBA.&lt;br /&gt;&lt;br /&gt;The second bit of lunacy, also attributable to Microsoft in a small way, is the habit of extending Hungarian notation to table naming. I'm talking about tables called tblCountry, tblCustomer, and so forth. Here's another real-life example of what can happen:&lt;br /&gt;&lt;br /&gt;Let's say you start off with a table called tblCustomer. Several months or years later you discover that in fact you have two types of customers, corporate and private.  At this stage you have several thousand lines of legacy code dealing with tblCustomer, so changing the table isn't really an option.&lt;br /&gt;&lt;br /&gt;Fortunately, databases have wonderful things called views and triggers that let you deal with just such a situation in an elegant fashion.  What you need to do is create two new tables, say tblCorporateCustomer and tblPrivateCustomer, and then replace tblCustomer with a view onto the union of these new tables.  You write triggers to support the legacy operations of inserting, updating and deleting on tblCustomer.  This enables your legacy code to continue working seamlessly while you go on to do great things with the new tables.&lt;br /&gt;&lt;br /&gt;There's just one fly in the ointment.  tblCustomer is no longer a table, it's a view.  What's the new guy on the team going to make of a view called tblCustomer?  Exactly what purpose does that "tbl" prefix serve?  What's the point of differentiating between tables and views in the first place?  Confusion to the new guy?  Job security for the greybeards?  You tell me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-109757349744191359?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/109757349744191359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=109757349744191359' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/109757349744191359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/109757349744191359'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2005/09/some-thoughts-on-database-design.html' title='Some thoughts on database design'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-112057137006508857</id><published>2005-07-05T15:27:00.000+02:00</published><updated>2005-09-27T11:43:05.536+02:00</updated><title type='text'>Triggers: instead-of a superset of before?</title><content type='html'>Towards the end of last year I had a flaming argument with a friend over the merits of SQL Server.  One of his counterarguments was that &lt;code&gt;instead of&lt;/code&gt; triggers are an adequate substitute for &lt;code&gt;before&lt;/code&gt; triggers.  Here's an example of why this is not the case.&lt;br /&gt;&lt;br /&gt;Consider the following fairly typical design.  We have an Travel table with a cascade update foreign key on Employees and Agents.  There is a TravelEmployee table, cascade delete FK against Travel.  When TravelEmployee records are deleted, a log table is updated by a trigger, using certain information from the Travel table (travel agent, for example).&lt;br /&gt;&lt;br /&gt;The problem is that occasionally an entire Travel record is deleted, and when this happens, the corresponding TravelEmployee records are deleted, but the log table is not updated.  Surprise!  What's happening is that the trigger on TravelEmployee is doing something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;insert into TravelLog (EmployeeCode, TravelAgent, Action)&lt;br /&gt;select EmployeeCode, TravelAgent, 'Cancelled' as Action&lt;br /&gt;from deleted inner join Travel on deleted.TicketNumber = Travel.TicketNumber&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, by the time this trigger is executed, the record from Travel that contains the TravelAgent field is long gone, so the join produces nothing.  The correct solution to this problem is to change the trigger to a &lt;code&gt;before&lt;/code&gt; trigger.  But SQL Server does not support this.  How about an &lt;code&gt;instead of&lt;/code&gt; trigger, then?  Ah, but TravelEmployee has a cascade-update foreign key, and so SQL Server rightly refuses to create an &lt;code&gt;instead of&lt;/code&gt; trigger on the grounds that it cannot then guarantee referential integrity.&lt;br /&gt;&lt;br /&gt;Oops.  There are a variety of less-than-satisfactory solutions to this problem.  What we ended up doing was dropping the foreign key constraint on TravelEmployee and maintaining referential integrity by other means.  Another possible solution is to create a new table containing deleted Travel records, which can then be used by the above trigger.  There are a few more solutions, which I'm sure you can think of.  All of these solutions have flaws.&lt;br /&gt;&lt;br /&gt;It's cold comfort, but I was quite right: &lt;code&gt;instead of&lt;/code&gt; is no substitute for &lt;code&gt;before&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-112057137006508857?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/112057137006508857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=112057137006508857' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/112057137006508857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/112057137006508857'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2005/07/triggers-instead-of-superset-of-before.html' title='Triggers: instead-of a superset of before?'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-111598724542355374</id><published>2005-05-13T13:54:00.000+02:00</published><updated>2005-05-13T14:27:25.430+02:00</updated><title type='text'>Using databases in C#</title><content type='html'>Having used the excellent &lt;a href="http://gborg.postgresql.org/project/libpqxx/projdisplay.php"&gt;pqxx&lt;/a&gt; library to access &lt;a href="http://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt; databases via C++, I was somewhat less than overwhelmed when confronted with the .NET framework's data access libraries. The latter are really just a trivial evolution of ADO, of which I have few fond memories. But, I remembered, any system lacking sufficiently elegant APIs needs must beget patterns. So here is a handy one to tuck into your copy-paste-coding repository. In C#:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: smaller;"&gt;&lt;br /&gt;// using System.Data.SqlClient;&lt;br /&gt;SqlConnection dbCon = new SqlConnection("server=localhost;database=example;");&lt;br /&gt;dbCon.Open();&lt;br /&gt;&lt;br /&gt;lock (dbCon) using (SqlCommand cmd = dbCon.CreateCommand())&lt;br /&gt;{&lt;br /&gt; cmd.CommandText = "select card_number, surname, name from employees;";&lt;br /&gt; using(SqlDataReader csr = cmd.ExecuteReader()) while (csr.Read())&lt;br /&gt; {&lt;br /&gt;   employeeMap.Add(&lt;br /&gt;     csr.GetInt32(0),&lt;br /&gt;     new Employee(csr.GetInt32(0), csr.GetString(1), csr.GetString(2)));&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is just about the most readable way to process a query on a long-running connection, while maintaining the necessary API contracts. First, observe that the connection object is locked for the duration of the query, thus ensuring that no more than one SqlCommand is created at a time. Furthermore, both the command and the reader are declared in using blocks, ensuring the correct disposal of both objects. And the whole thing manages to only indent twice. Not too bad.&lt;br /&gt;&lt;br /&gt;Of course, when you start using transactions, things get more complicated, and I still haven't found a wholly satisfactory way of laying out transactional code so that it is easy to read, purposeful and not cluttered with adjunct requirements.&lt;br /&gt;&lt;br /&gt;I wish the designers of the System.Data APIs had read Python's &lt;a href="http://www.python.org/peps/pep-0249.html"&gt;DB-API spec&lt;/a&gt;, flawed though it is.  Ideally, we want a &lt;code&gt;connection&lt;/code&gt; entity, from which we can spawn many &lt;code&gt;transaction&lt;/code&gt; entities, which in turn allow us to maintain multiple &lt;code&gt;cursor&lt;/code&gt;s.  Is that too much to ask?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-111598724542355374?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/111598724542355374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=111598724542355374' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/111598724542355374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/111598724542355374'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2005/05/using-databases-in-c.html' title='Using databases in C#'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-111347766980024316</id><published>2005-04-14T13:09:00.000+02:00</published><updated>2005-04-14T13:21:09.800+02:00</updated><title type='text'>AOP</title><content type='html'>It occurred to me that &lt;a href="http://dev.eclipse.org/viewcvs/indextech.cgi/~checkout~/aspectj-home/doc/progguide/index.html"&gt;AOP&lt;/a&gt; corrects many of the deficiencies in Java that cause me to consider it less robust than C++:  most importantly, its inability to guarantee pre- and postconditions after the fashion of &lt;a href="http://www.hackcraft.net/raii/"&gt;RAII&lt;/a&gt;.  I haven't got time to do a formal comparison, so I would be interested to know anybody's opinion on the following topics:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;AOP techniques that can't be represented adequately in "pure" C++ (and by adequate I mean with the same degree of isolation).&lt;/li&gt;&lt;br /&gt; &lt;li&gt;C++ techniques that can't be represented adequately in AspectJ.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-111347766980024316?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/111347766980024316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=111347766980024316' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/111347766980024316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/111347766980024316'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2005/04/aop.html' title='AOP'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-111322059445508782</id><published>2005-04-11T13:22:00.000+02:00</published><updated>2005-04-11T13:56:34.456+02:00</updated><title type='text'>Dispatch Tables in Python</title><content type='html'>I mentioned dispatch tables last time around.  Dispatch tables are basically dictionaries of functions.  Here's a concrete if trivial example of how to use them, written in Python.&lt;br /&gt;&lt;br /&gt;&lt;pre style='font-size: smaller;'&gt;&lt;br /&gt;class Document:&lt;br /&gt;  def __init__(self):&lt;br /&gt;    self.dtable = {&lt;br /&gt;      "color": Document.setColor,&lt;br /&gt;      "text": Document.addText&lt;br /&gt;    }&lt;br /&gt;  def setColor(self, rgb):&lt;br /&gt;     # set the pen colour for the document&lt;br /&gt;     pass&lt;br /&gt;  def addText(self, text):&lt;br /&gt;     # add some text to the document&lt;br /&gt;     pass&lt;br /&gt;  def loadXml(self, node):&lt;br /&gt;    while node:&lt;br /&gt;      self.dtable[node.nodeName](self, node.data)&lt;br /&gt;      node = node.nextSibling&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the loadXml function itself knows nothing about what XML nodes might occur, or what functions must handle them.  This is important because it allows code to handle new nodes (or change the handling of old nodes) to be added in, say, a subclass &lt;span style="font-style:italic;"&gt;without changing the original class at all&lt;/span&gt;.  All that is needed is to modify the dispatch table (&lt;code&gt;dtable&lt;/code&gt;).  This is a powerful technique, and much used in Lisp and C.  It has several advantages over a more conventional if-then-else approach:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;It's more elegant&lt;/strong&gt;.  In most languages (with the curious exception of Java), this technique takes less lines of code and is easier to work with.  Fewer lines of code equals fewer mistakes.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;It's more robust&lt;/strong&gt;.  A mistake in one case won't topple the other cases.  There is more separation between the handlers for various types than with some other techniques; also, the dispatch mechanism need know nothing specific about the handlers.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;It's future-proof&lt;/strong&gt;.  The mapping of metadata to interpretation is independent, in most cases, of the dispatch mechanism.  Changes to input data formats, for example, can be handled with minimal intrusions into existing code.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;It's faster&lt;/strong&gt;.  Surprised?  A dictionary look-up is ideally O(1); a chain of &lt;code&gt;if&lt;/code&gt;s is O(n).&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-111322059445508782?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/111322059445508782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=111322059445508782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/111322059445508782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/111322059445508782'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2005/04/dispatch-tables-in-python.html' title='Dispatch Tables in Python'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-110986488397780599</id><published>2005-03-03T16:57:00.000+02:00</published><updated>2005-03-03T17:49:52.893+02:00</updated><title type='text'>Python and VB</title><content type='html'>So I'm working on a project where VB.NET is mandated by the customer. The reason, presumably, is that it's dead easy to drag any poor schmuck off the streets and have him churn out VB code for minimum wage.&lt;br /&gt;&lt;br /&gt;Leaving the short-sightedness of this aside, I'd like to talk about what a shock it was having to write VB code after having spent some glorious months in Python. To cut to the chase, and without wishing to wallow in warrantless waffle, the kind of shock that it was was this: bad.&lt;br /&gt;&lt;br /&gt;Compare, cherished chums, certain canonical code cases:&lt;br /&gt;&lt;br /&gt;&lt;pre style='font-size:small;'&gt;' VB&lt;br /&gt;Dim doc As new System.Xml.XmlDocument&lt;br /&gt;doc.Load ("test.xml")&lt;br /&gt;Dim pages As System.Xml.XmlNodeList&lt;br /&gt;pages = doc.GetElementsByTagName ("page")&lt;br /&gt;If pages.Count &lt;&gt; 1 Then&lt;br /&gt; throw new Exception ("Invalid XML")&lt;br /&gt;End If&lt;br /&gt;Me.images = new System.Collections.ArrayList&lt;br /&gt;Dim imgentry As System.Xml.XmlNode&lt;br /&gt;Dim attr As System.Xml.XmlNode&lt;br /&gt;For Each imgentry In pages(0).ChildNodes&lt;br /&gt;  If imgentry.Name = "image" Then&lt;br /&gt;    Dim imginfo As New ImageInfo&lt;br /&gt;    Me.images.Add(imginfo)&lt;br /&gt;    For Each attr In imgentry.ChildNodes&lt;br /&gt;      If Attr.Name = "title" Then&lt;br /&gt;        imginfo.title = Attr.FirstChild.Value&lt;br /&gt;      End If&lt;br /&gt;      If Attr.Name = "filename" Then&lt;br /&gt;        imginfo.filename = Attr.FirstChild.Value&lt;br /&gt;      End If&lt;br /&gt;    Next&lt;br /&gt;  End If&lt;br /&gt;Next&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style='font-size:small;'&gt;&lt;br /&gt;# Python&lt;br /&gt;from xml.dom import minidom&lt;br /&gt;doc = dom.parse("test.xml")&lt;br /&gt;pages = doc.getElementsByTagName("page")&lt;br /&gt;if len(pages) != 1:&lt;br /&gt;  raise Exception, "Invalid XML"&lt;br /&gt;self.images = []&lt;br /&gt;for imgentry in pages[0].childNodes:&lt;br /&gt;  if imgentry.nodeName == "image":&lt;br /&gt;    imginfo = ImageInfo()&lt;br /&gt;    self.images.append(imginfo)&lt;br /&gt;    for attr in imgentry.childNodes:&lt;br /&gt;      if attr == "title":&lt;br /&gt;        imginfo.title = attr.firstChild.nodeValue&lt;br /&gt;      if attr == "filename":&lt;br /&gt;        imginfo.filename = attr.firstChild.nodeValue&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, if anything, this example is a little unfair to Python.  Why?  Because a reasonable Python programmer would take one look at the code above, laugh his ass off and rewrite it with a dispatch table and list comprehension.  The same approach would, I'm fairly confident, double the number of lines of VB code required, while halving the number of Python lines.&lt;br /&gt;&lt;br /&gt;By the way, a dispatch table is a far more robust solution to the above problem.  I might discuss them in a future post, although there's plenty of reference material out there on the web.&lt;br /&gt;&lt;br /&gt;At any rate, it should be evident from the above that even a literal translation of VB code into Python results in substantial savings in lines of code, and therefore in time and errors.  Don't even start with the dynamic-versus-static-typing debate:  the fact is that the end result is largely the same in both cases, and the work required differs substantially in favour of Python.  In my pragmatic little book, that's QED.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-110986488397780599?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/110986488397780599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=110986488397780599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/110986488397780599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/110986488397780599'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2005/03/python-and-vb.html' title='Python and VB'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-110919826210313547</id><published>2005-02-24T00:29:00.000+02:00</published><updated>2005-02-24T00:37:42.106+02:00</updated><title type='text'>SQL Server Bad Joke Of The Day</title><content type='html'>&lt;span style="font-family: courier new;"&gt;select&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;  case cast(cast(cast('2004-11-27 13:14:00' as datetime) as float) as int)&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;  when cast(cast(cast('2004-11-27 13:14:00' as datetime) as int) as int)&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;  then 'happy panda'&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;  else 'sad panda'&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;  end&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;br /&gt;Go ahead.  Try it.&lt;br /&gt;&lt;br /&gt;I'd love to hear from anyone who doesn't think this is a serious problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-110919826210313547?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/110919826210313547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=110919826210313547' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/110919826210313547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/110919826210313547'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2005/02/sql-server-bad-joke-of-day.html' title='SQL Server Bad Joke Of The Day'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-109956375639356737</id><published>2004-11-04T12:20:00.000+02:00</published><updated>2004-11-04T12:22:36.393+02:00</updated><title type='text'>Am I left-wing or right-wing?</title><content type='html'>Well, let's see.  The left favours political liberty and economic totalitarianism.  The right favours economic liberty and political totalitarianism.  I favour political liberty and economic liberty.  I am therefore fundamentally opposed to both wings.&lt;br /&gt;&lt;br /&gt;I stongly recommend that readers read the &lt;a href="http://www.fahayek.org/index.php?article=177"&gt;views of Friedrich Hayek&lt;/a&gt; in this regard.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-109956375639356737?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/109956375639356737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=109956375639356737' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/109956375639356737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/109956375639356737'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2004/11/am-i-left-wing-or-right-wing.html' title='Am I left-wing or right-wing?'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-108851074291193250</id><published>2004-06-29T10:43:00.000+02:00</published><updated>2004-06-29T14:05:42.913+02:00</updated><title type='text'>A Perilous Lack of Vision</title><content type='html'>&lt;a href="http://www.berkshirehathaway.com/"&gt;Warren Buffett&lt;/a&gt; has made passing reference to the unenviable position mutual-fund managers find themselves in.  They are constrained by the need to show short-term (often quarterly) results, which often means that they must prematurely exit from investments that, for various reasons, have taken a turn for the worse.  Conversely, they must often invest in what are clearly short-term upswings in order to make up the numbers.  This results in a kind of flocking behaviour ("follow the leader"), which leads to the observed erratic, manic-depressive behaviour in the stock market that has little basis in economic reality.&lt;br /&gt;&lt;br /&gt;This type of flocking is not limited to investors, of course.  Fundamentally, it represents a kind of risk-aversion that is endemic in modern capitalist systems.  This is the type of thinking that goes, "I may not achieve the best results in the long term, but at least I'll never suffer a major setback in the short term.  Or at any rate, I'll be no worse off than my competitors".  There is nothing wrong in principle with an avoidance of risk: I myself am one of the most risk-averse people I know.  However, it becomes a problem when it begins to strangle growth and the achievement of one's potential.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Operational Efficiency Chimera&lt;/h2&gt;&lt;br /&gt;The operational efficiency of a business can be measured by dividing its overhead costs by its gross profit.  The ratio can be improved either by increasing gross profitability, or by reducing overhead costs (usually by means of retrenchments -- although executives can occasionally be convinced to give up the corporate jet, too).  Since increasing profitability is usually extremely difficult, it's always tempting to focus exclusively on eliminating overhead.  In moderation, this is a good exercise; but cut too deeply into the fat, and you start to hit the muscle and the bone.  An amusing if not entirely valid extension to this analogy is that the fat often underlies the muscle.&lt;br /&gt;&lt;br /&gt;It is logical then that good managers should also be asking themselves: what can I do to increase gross profitability?  The answer to this varies from industry to industry.  In the 'commodity' industries (steel, agriculture, general manufacturing), the answer is unfortunately "not much".  Improved processes are about the only thing that will do the trick.  The conclusion we should draw is that these industries should invest heavily in R&amp;D, which can be viewed as a mini-industry in itself.  R&amp;D is more like a service industry.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Services are Different&lt;/h2&gt;&lt;br /&gt;In service industries, we run into an accounting convention that I believe is detrimental to efficient management.  The problem is that service industries rely almost entirely on &lt;em&gt;human&lt;/em&gt; capital to produce the goods.  However, the cost of salaries is still recorded as an overhead cost.  This makes accounting sense, but it can lead to bad decisions when managers try to treat services the same way they treat manufacturing.  Basically, overhead is seen as "bad", and since services typically operate at low or even zero gross marginal cost, there doesn't seem to be much improvement to be made at that end of the system.  Thus managers are compelled to cut overhead, even though this 'overhead' should properly be treated as a direct cost of production!&lt;br /&gt;&lt;br /&gt;This brings me to the crux of my argument.  The manufacturing model of accounting is inappropriate for service-type industries.  The salary costs of those actually performing the work are in fact a direct cost of sales.  However, the problem lies not in the accounting but in the way the figures are used to make decisions: humans providing services are assets, not expenses, and they should be treated as such.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Human Asset&lt;/h2&gt;&lt;br /&gt;The remarkable thing about these human assets is that they do not depreciate.  In fact, handled correctly, your people actually increase in value.  Yet we do not see nearly enough investment in human assets -- certainly not below executive level.  The trend I have noticed is that &lt;em&gt;positions&lt;/em&gt; are hired rather than &lt;em&gt;people&lt;/em&gt;.  The candidate should be able to do X, Y and Z, and that is the end of that.  This is a huge mistake.  A person hired to do a job that involves thinking is an investment.  You do not want such a person simply to perform mandated functions: you want them to contribute to the value of your business.&lt;br /&gt;&lt;br /&gt;This argument is eminently reasonable, and I have never heard anyone disagree with it.  Yet there is a reason why this theoretical ideal is not reflected in practice.  You guessed it: risk-aversion.  The problem with competent people is that you come to rely upon them.  This is a risk (one might reason).  What if the person leaves?  What if I have to compensate him in an extraordinary fashion for his extraordinary service?  Far better, surely, to rely only upon fungible minimum-standard employees, and not put my business at risk?&lt;br /&gt;&lt;br /&gt;This line of thinking is, if you'll forgive me, rubbish.  It's completely wrong-headed.  Yes, competent employees are a risk.  But that's what business is all about!  You take a risk by investing, and you reap the rewards.  If you don't invest, you'll never see a return.  Imagine what we would say if a steel mill owner decided only to purchase the cheapest furnaces, on the grounds that the premier models are expensive to run and expensive to rebuild if they crack.  False economy?  You bet.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;In Conclusion...&lt;/h2&gt;&lt;br /&gt;So what am I saying?  In service industries (and, importantly, service divisions of companies in other industries), people form the bulk of the assets that are missing from the balance sheet.  The money that is paid to them should be viewed as a cost of production rather than overhead cost.  As in any other business, the job of the managers of a service company is to select and maintain the appropriate assets for the work in question.  That means finding skilled people, and nurturing them.  The more competent the better!  It is absolutely a false economy to try to minimize the necessary skill levels.  Trying to create fungible employees is actually counter-productive.  When you attempt to treat skilled employees as interchangeable units, you are harming your business.&lt;br /&gt;&lt;br /&gt;There is vast untapped productivity in the human asset.  Ability should be allowed to flourish rather than supressed into conformity.  Managing a services company is extremely difficult, because it's a lot harder to measure the performance of people than it is to make similar measurements of machines.  It takes a different kind of manager, certainly, and a different kind of approach.&lt;br /&gt;&lt;br /&gt;Unfortunately, it's taking a long time for us to become aware of the fact that providing services is not like producing steel.  The attempts to fit services into the old manufacturing patterns represent a perilous lack of vision.  Too much attention is paid to things that are irrelevant (fixed assets), and too little is paid to things that most certainly are relevant (human capital).  This is an instance of experience letting us down: we're trying to apply a pattern that we're familiar with to a new subject, and it doesn't fit.  That is why service industries, and software in particular, are so inefficient and risky.  We're squeezing them in the wrong places.&lt;br /&gt;&lt;br /&gt;What if we were to start listing our employees on the balance sheet as assets?  What if their salaries were written up as costs of sales?&lt;br /&gt;&lt;br /&gt;If you're in services, do as Apple says, and "think different".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-108851074291193250?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/108851074291193250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=108851074291193250' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/108851074291193250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/108851074291193250'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2004/06/perilous-lack-of-vision.html' title='A Perilous Lack of Vision'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7380536.post-108781304334785724</id><published>2004-06-21T10:14:00.000+02:00</published><updated>2004-06-21T15:22:59.930+02:00</updated><title type='text'>Garbage Collection, RAII, and 'using'</title><content type='html'>If you fall exactly within the median range of computer programmers, then you've probably heard that "all modern languages use garbage collection", and you've taken to the idea with glee: you &lt;em&gt;like&lt;/em&gt; the idea of having your garbage collected for you.  However, you're probably also a little concerned that perhaps garbage collection is just a teensy bit less efficient than 'manual' memory management, although you'd never admit it in public (in case someone started forcing you to use malloc() and free() again).&lt;br /&gt;&lt;br /&gt;On the other hand, you've probably not heard of RAII.  If you have, you may know that it stands for "resource acquisition is initialization", although you're still not quite clear what that means.  If it means anything.&lt;br /&gt;&lt;br /&gt;If you do know about RAII, then you were probably extremely wary of the C# programming language - that is, until you discovered the 'using' statement.  It's all good now, right?&lt;br /&gt;&lt;br /&gt;To enlighten those who are at this point saying, "huh?", and to avoid (I hope!) a number of straw-man arguments, here's a brief summary of each of the terms in the title.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Garbage collection&lt;/h2&gt;&lt;br /&gt;Garbage collection is often referred to as "automatic memory management", although this can be a little misleading, as we'll see.  The purpose of a garbage collector is to 'collect' blocks of memory that won't be used again and recycle them.  The trick, of course, is knowing which blocks won't be used.  There are several strategies for doing this, which I won't go into here.  Generally, however, what happens is that allocated memory tends to stay allocated for a little longer than it otherwise would.  This can lead to several efficiencies in the memory allocation scheme: most particularly, the malloc() function (or its equivalent) can be simplified enormously, as it no longer has to consider fragmentation problems.  Generally speaking, this means that garbage collectors are more efficient for programs that allocate many small chunks of memory.  Of course, the downside is that at any given moment, more memory is in use than is actually necessary - but then we're no longer trying to squeeze code, data and scratch space into 16k, are we?&lt;br /&gt;&lt;br /&gt;Any actions carried out by an object at the point at which the garbage collector releases the memory allocated to it I will refer to as "finalization".&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;RAII&lt;/h2&gt;&lt;br /&gt;RAII is an idiom that has been floating around in C++ circles for some time now.  The essential idea is that a resource (memory, file handle, database connection...) is &lt;em&gt;acquired&lt;/em&gt; when an object is &lt;em&gt;initialized&lt;/em&gt; (i.e. in the object's constructor).  Conversely, the resource is &lt;em&gt;released&lt;/em&gt; when the object is &lt;em&gt;destroyed&lt;/em&gt;.  The point of destruction is the interesting bit, and we'll have more on that later.  However, suffice it to say that in C++, 'auto' or stack-allocated objects are destroyed as soon as they go "out of scope", meaning the variable that was bound to them when they were created is no longer accessible.&lt;br /&gt;&lt;br /&gt;Generally when C++ programmers talk about RAII they're talking about wrapping up a resource in an object in such a way as to make certain guarantees about the way in which the resource will be used.  In particular, they are used for exception safety:  C++ does not have a 'finally' block.  Bjarne Stroustrup explains why &lt;a href="http://www.research.att.com/~bs/bs_faq2.html#finally"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There is an interesting twist to this story.  It's possible to implement garbage collection using the RAII idiom (amongst other things).  In fact, if you look &lt;a href="http://www.codeproject.com/cpp/garbage_collect.asp"&gt;here&lt;/a&gt;, you'll find an example of just such a thing.  More commonly C++ programmers use a simpler reference-counting implementation often referred to as a "smart pointer".  You can find a good one &lt;a href="http://www.boost.org/libs/smart_ptr/smart_ptr.htm"&gt;here&lt;/a&gt;.  The good thing about a reference-counted implementation is that you can accurately predict when the object in question will be destroyed.  What about cycles, you say?  Consider weak references.  I've found that they clarify my thinking on a number of issues revolving around ownership, lifecycles, and authority.&lt;br /&gt;&lt;br /&gt;You can find out more about RAII &lt;a href="http://www.hackcraft.net/raii/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The 'using' statement&lt;/h2&gt;&lt;br /&gt;Here is where things get interesting.  In C#, as in Java, the garbage collector makes no guarantees about when an object will be collected.  C# supports 'destructors', but they're more accurately referred to as &lt;em&gt;finalizers&lt;/em&gt;, since they are associated with the release of the memory rather than with the end of an object's useful lifecycle.  This means that you can't use C# 'destructors' to manage resources as you can in C++.  However, the C# team were aware of this, and they were also aware that Java-like try/finally constructs were bad: they involve a lot of typing, they make the code less readable, they detract from the purpose or &lt;em&gt;intent&lt;/em&gt; of the code, and (and this is a big and) it's very easy for programmers -- even experienced ones -- to forget to use them.&lt;br /&gt;&lt;br /&gt;The C# solution was to introduce a new construct: the &lt;em&gt;using&lt;/em&gt; statement.  This is essentially just shorthand for try/finally.  When the scope of the using statement ends, the IDispose interface of the object that was 'used' is automatically called.  This approach has two weaknesses.  The first is minor: it limits the lifetime of the disposable object to the scope of a single statement.  This is often not what we want.  More serious, however, is the second objection: it still doesn't solve the problem of end-user forgetfulness.  We're all human.  We forget.  We don't read the documentation.  We often don't realise that we need to do anything other than just use the object we want to use.  There's no safety net.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Some inferences&lt;/h2&gt;&lt;br /&gt;Here is a list of some of the things we can conclude from the preceding paragraphs:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Garbage collection frees the programmer from having to use 'free'.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Garbage collection is often more efficient than malloc/free.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Garbage collection defers the point at which the memory is released, often indefinitely.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;What happens when the memory is released is called &lt;em&gt;finalization&lt;/em&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;RAII relies on the timely destruction of objects to manage resources.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;RAII leads to easy-to-read ("intentional") code, with no need for try/finally or using statements.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;RAII makes exception safety very much easier.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The using statement is really just try/finally in disguise.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The end-user still needs to be told when to use 'using'.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Now we can say something interesting about the relationships between these concepts.  Garbage collection (GC) solves the problem of memory management, whereas RAII solves the more general problem of resource management.  GC uses the concept of "finalization"; RAII uses "destruction".  "Using" is an attempt to bring the elegance and power of RAII into a GC context, but it's not much better than try/finally.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The problem, finally&lt;/h2&gt;&lt;br /&gt;Ideally, we would like to use both GC and RAII.  Why can't we?  Well, mostly because we can't be sure when a GC finalizer will run (if at all).  This rules out the use of RAII in contexts where it's most useful -- mutex locks, for example.  But why should we assume that the concepts of finalization and destruction are necessarily co-dependent?  Destruction is the controlled, predictable end-of-life of an object.  Finalization is the unpredictable point of memory-release.  Surely these concepts are orthogonal?&lt;br /&gt;&lt;br /&gt;Let's run with this a little further.  We want controlled destruction, but we want to avoid getting the end-user involved in the details of when this should happen.  One way of achieving these ends (in a language like Java or Python where [almost] all variables are by-reference) is through reference-counting.  Reference-counted objects are almost garbage collected (except when they're involved in cyclical reference graphs), and they allow deterministic destruction.  Since RAII objects tend not to refer to anything except the resource they represent, the problem of cycles is not really  a significant one.  Were objects with destructors implicitly subject to reference counting, and the destructor called when the reference count dropped to zero (the memory could be freed and the finalizer called at some later point), we'd have achieved the end of having both garbage collection and RAII in a single box.&lt;br /&gt;&lt;br /&gt;The great thing about this solution is that it allows the programmers who design libraries to ensure that their objects won't be abused [too much].  The end-user doesn't have to remember that this particular object should have Dispose() or Close() (or whatever it is) called -- he just writes what comes naturally:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;string[] getConfig() {&lt;br /&gt;    File f = new File("config.txt");&lt;br /&gt;    return f.readLines();&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;...and all is taken care of.&lt;br /&gt;&lt;br /&gt;There are some wonderful things that can be done once this technique is admitted; there are also some gritty technical problems that have to be overcome.  But that's a discussion for later.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7380536-108781304334785724?l=dkturner.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dkturner.blogspot.com/feeds/108781304334785724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7380536&amp;postID=108781304334785724' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/108781304334785724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7380536/posts/default/108781304334785724'/><link rel='alternate' type='text/html' href='http://dkturner.blogspot.com/2004/06/garbage-collection-raii-and-using.html' title='Garbage Collection, RAII, and &apos;using&apos;'/><author><name>David Turner</name><uri>http://www.blogger.com/profile/14738491011019732316</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_Ala3XWrpVZ0/R76nxsTZgaI/AAAAAAAAAAM/uqMXrwQw9sQ/S220/ProfilePic.jpg'/></author><thr:total>6</thr:total></entry></feed>
