<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Frans Bouma's blog</title><link>http://weblogs.asp.net/fbouma/default.aspx</link><description>Generator.CreateCoolTool();</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><creativeCommons:license>http://creativecommons.org/licenses/by-sa/3.0/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-sa/3.0/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/FransBouma" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Linq: Beware of the 'Access to modified closure' demon</title><link>http://feedproxy.google.com/~r/FransBouma/~3/kwkzYteoG2Q/linq-beware-of-the-access-to-modified-closure-demon.aspx</link><pubDate>Thu, 25 Jun 2009 08:32:21 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7133915</guid><dc:creator>FransBouma</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=7133915</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/06/25/linq-beware-of-the-access-to-modified-closure-demon.aspx#comments</comments><description>&lt;p&gt;If you're using Linq and Resharper, you've probably seen the warning Resharper shows when you use a foreach loop in which you use the loop variable in a Linq extension method (be it on IQueryable&amp;lt;T&amp;gt; or IEnumerable&amp;lt;T&amp;gt;). In case you don't know what it is or what damage it can do if you ignore the issue, I'll give you a database oriented query (so on IQueryable&amp;lt;T&amp;gt;, using &lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt;'s Linq provider) which creates a dynamic Where clause based on input, the typical scenario you should be careful with when it comes to this particular problem.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;pre class="c#" name="code"&gt;var customers = from o in metaData.Order
		join c in metaData.Customer on o.CustomerId equals c.CustomerId into oc
		from x in oc.DefaultIfEmpty()
		select new { CustomerId = x.CustomerId, CompanyName = x.CompanyName, Country = x.Country };

string searchTerms = &amp;quot;U A&amp;quot;;
var searchCriteria = searchTerms.Split(new string[] { &amp;quot; &amp;quot; }, StringSplitOptions.RemoveEmptyEntries);
foreach(var search in searchCriteria)
{
    customers = customers.Where(p =&amp;gt; p.Country.Contains(search));
}
var ids = (from c in customers select c.CustomerId).ToArray();&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The above code snippet has the demon embedded into itself, likely without you noticing it. Can you spot it? (Ok, I already gave it away a bit with the foreach loop hint). &lt;/p&gt;

&lt;p&gt;The problem with the above query is that it will produce a WHERE clause in the SQL query with two LIKE statements which both filter on %A%. How's that possible? The cause is in the 'Access to modified closure' problem: &lt;em&gt;search&lt;/em&gt; is a local variable. The first time the foreach is ran, &lt;em&gt;search&lt;/em&gt; will have the value &amp;quot;U&amp;quot;. The .Where() extension method will add a MethodCall expression with a call to Where(lambda) with inside the lambda among other things a ConstantExpression referring to the local variable &lt;em&gt;search&lt;/em&gt; for the value. And that's precisely the problem: when the foreach loop is looping again, &lt;em&gt;search&lt;/em&gt; will get &lt;em&gt;another value&lt;/em&gt;: namely &amp;quot;A&amp;quot;. As there are no more values, the loop ends and the query is executed. &lt;/p&gt;

&lt;p&gt;Well, &lt;em&gt;executed&lt;/em&gt; is more complex than it sounds: first, the expression tree has to be converted into SQL. When the linq provider runs into the two .Where() extension method calls, it evaluates the argument, which is a LambdaExpression which contains a ConstantExpression which refers to... a local variable called &lt;em&gt;search&lt;/em&gt;. It can't do anything else but reading that variable, which has the value ... &amp;quot;A&amp;quot; for both, as it reads the same variable. So it's not storing the constant value &lt;em&gt;search&lt;/em&gt; has when the call to Where and Contains is made, it's storing a reference to the local variable. &lt;/p&gt;

&lt;p&gt;How to fix this? It's pretty straight forward: create a new local variable:&lt;/p&gt;

&lt;pre class="c#" name="code"&gt;foreach(var search in searchCriteria)
{
	var searchTerm = search;
	customers = customers.Where(p =&amp;gt; p.Country.Contains(searchTerm));
}&lt;/pre&gt;

&lt;p&gt;With each iteration, it creates a new local variable, and thus each Contains call will refer to a &lt;em&gt;different&lt;/em&gt; variable and thus the SQL query will contain the two LIKE predicates the way it should, one with %U% and one with %A%. &lt;/p&gt;

&lt;p&gt;This subtle issue pops up with Linq to Objects as well, so beware when you pass the foreach loop variable to a Linq extension method: if the query doesn't run at that same spot, you likely will run into this problem and will have an obscure bug to track down. &lt;/p&gt;

&lt;p&gt;Happy hunting &lt;img border="0" src="http://www.xs4all.nl/~perseus/smileys/smileyregular.gif" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7133915" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=kwkzYteoG2Q:gluSUkpVaSU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=kwkzYteoG2Q:gluSUkpVaSU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=kwkzYteoG2Q:gluSUkpVaSU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=kwkzYteoG2Q:gluSUkpVaSU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=kwkzYteoG2Q:gluSUkpVaSU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/kwkzYteoG2Q" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Linq/default.aspx">Linq</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Linq+to+LLBLGen+Pro/default.aspx">Linq to LLBLGen Pro</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/06/25/linq-beware-of-the-access-to-modified-closure-demon.aspx</feedburner:origLink></item><item><title>Multi-value Dictionary C# source code (.NET 3.5)</title><link>http://feedproxy.google.com/~r/FransBouma/~3/EWN-NlP7hB8/multi-value-dictionary-c-source-code-net-3-5.aspx</link><pubDate>Mon, 18 May 2009 08:52:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7091895</guid><dc:creator>FransBouma</dc:creator><slash:comments>9</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=7091895</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/05/18/multi-value-dictionary-c-source-code-net-3-5.aspx#comments</comments><description>&lt;p&gt;By popular demand, I've &lt;a href="http://www.xs4all.nl/%7Eperseus/MultiValueDictionary_05182009.zip" target="_blank" mce_href="http://www.xs4all.nl/~perseus/MultiValueDictionary_05182009.zip"&gt;published the C# source code&lt;/a&gt; of my Multi-value Dictionary class, which can also merge dictionaries into itself and which implements ILookup&amp;lt;T, V&amp;gt; as well. It's part of Algorithmia, our upcoming data-structure and algorithm library which will ship with &lt;a href="http://www.llblgen.com" target="_blank" mce_href="http://www.llblgen.com"&gt;LLBLGen Pro&lt;/a&gt; v3.0 later this year. The code is released under the BSD2 license, see the enclosed readme.txt. The class comes with its own general purpose Grouping&amp;lt;T, V&amp;gt; class as well and of course its own ToMultiValueDictionary() extension method.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;I hope this is useful to others. &lt;img src="http://www.xs4all.nl/%7Eperseus/smileys/smileyregular.gif" mce_src="http://www.xs4all.nl/~perseus/smileys/smileyregular.gif" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Update: &lt;/strong&gt;it seems that if you run a Linq query (Linq to objects) over the MultiValueDictionary, the compiler and intellisense get confused as there are now two enumerators and both work with the linq operators, which means you either want to remove the ILookup code from the class (which is not that hard) or explicitly state the generic arguments. It's not a big problem, though in case you run into this problem, you know the reason. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7091895" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=EWN-NlP7hB8:ugtk5MRjKiQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=EWN-NlP7hB8:ugtk5MRjKiQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=EWN-NlP7hB8:ugtk5MRjKiQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=EWN-NlP7hB8:ugtk5MRjKiQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=EWN-NlP7hB8:ugtk5MRjKiQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/EWN-NlP7hB8" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/05/18/multi-value-dictionary-c-source-code-net-3-5.aspx</feedburner:origLink></item><item><title>The desperate quest for doing it 'right'</title><link>http://feedproxy.google.com/~r/FransBouma/~3/w80r8bg7sa4/the-desperate-quest-for-doing-it-right.aspx</link><pubDate>Mon, 04 May 2009 11:00:02 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7071762</guid><dc:creator>FransBouma</dc:creator><slash:comments>15</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=7071762</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/05/04/the-desperate-quest-for-doing-it-right.aspx#comments</comments><description>&lt;p&gt;This morning I ran into an interesting design decision. The problem at hand isn't that interesting, I've solved it a lot of times before. The interesting thing is that this problem isn't always solved the same way. It goes like this: do you tell an element which is inside a container (which can be inside another container) to exclude (remove) itself from its container or do you tell the container to exclude (remove) the element? This might sound simple enough, but what is &lt;em&gt;the right thing to do &lt;/em&gt;here? And if one is chosen, on what ground is that approach the right thing and is that always the case, no matter what the scenario might be? No, &amp;quot;It depends&amp;quot; doesn't cut it, for the sole reason that every single day probably millions of developers around the world are, in any state of desperation, searching for &lt;em&gt;the right thing to do, &lt;/em&gt;be it for this or other problems. Check the various Q&amp;amp;A sites, the various newsgroups and above all, the wide range of developer blogs, articles and twitter channels, and you'll see that a lot has been, is and will be discussed about that single concept: &lt;em&gt;the right thing&lt;/em&gt;. &lt;/p&gt;  &lt;p&gt;When I was confronted with the decision outlined above (more on that below), I wondered how a developer with decades of experience in the trenches like myself still has to wonder about this somewhat small decision and isn't capable of instantly choosing one over the other. Is it the big fear deep in all of us that if we make the wrong decision it might haunt us and eventually will bring us down? Looking at myself, with the massive code base this decision will be part of taken into account, it does bug my mind: if I pick the wrong decision, it might hurt the system, my company, and everyone depending on that. If I have these kind of questions, there must be others with the same question, wondering the same thing: what's &lt;em&gt;the right thing to do&lt;/em&gt;. Looking at all the blogs, articles, answers given to similar questions on various Q&amp;amp;A sites, indeed, there are many many people out there wondering that same thing: either showing that by giving advice how to do the &lt;em&gt;right thing&lt;/em&gt; (dear reader, if you now start to wonder if this is a recursive blog post, you're probably right), or by asking what it might be. &lt;/p&gt;  &lt;p&gt;So I wondered: isn't this quest to find what &lt;em&gt;the right thing &lt;/em&gt;is actually haunting our profession and why exactly is this? Why do we care so much? And more importantly: can we ourselves solve this?&lt;/p&gt;  &lt;p&gt;This post was partly triggered also by &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/05/03/can-we-avoid-tooling-to-prevent-spaghetti-code.aspx" target="_blank"&gt;a blog post&lt;/a&gt; I read this morning by &lt;a href="http://codebetter.com/blogs/patricksmacchia/default.aspx" target="_blank"&gt;Patrick Smacchia&lt;/a&gt;, where he shows that a toolkit written by &lt;a href="http://codebetter.com/blogs/jeremy.miller/" target="_blank"&gt;Jeremy D. Miller&lt;/a&gt; called &lt;a href="http://structuremap.sourceforge.net/Default.htm" target="_blank"&gt;StructureMap&lt;/a&gt; has cyclic dependencies between namespaces and Patrick tries to make a case that this kind of coupling is apparently not that great to have. Reading the post I wondered why anyone would give a hoot about such a thing. Don't get me wrong, I like solidly written software which allows great maintainability and extensibility without a lot of effort, but I couldn't help wondering who decides what's right and wrong and why we should care about these kind of 'rules'. A lot of these rules make sense simply because they are based on &lt;em&gt;common sense&lt;/em&gt;, however I still have the feeling that the vast majority of these rules only work in a given scenario, however in many situations the boundaries of these scenario's are omitted, be it deliberately or by mistake. The pitfall is that if these scenario boundaries aren't given, the rule at hand starts to look like a rule which can be applied &lt;em&gt;always&lt;/em&gt; as it apparently is a rule which is one of the ones based on &lt;em&gt;common sense&lt;/em&gt; and is &lt;em&gt;the right thing to do,&lt;/em&gt; as it has no boundaries/scenario given where it does work so it should work always.&lt;/p&gt;  &lt;p&gt;With the rewrite of &lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt;'s designer for v3.0 using .NET 3.5, I'm trying to do some things differently compared to what I did in v2.x. One of these things is a completely different set of data-structures to store meta-data. These data-structures give a lot of freedom to reason about the meta-data and as everything is event/observer controlled, it's very loosely coupled. However, I too ran into cyclic dependencies of namespaces (inside a common root namespace in the same assembly). When I detected this, I wondered... &amp;quot;should I correct this&amp;quot; ? But then I thought: &amp;quot;Why? Will the sky fall down if I leave these few cycles in?&amp;quot;. So I did what I always do in the case when I have to make a design decision: make a pro/con list and decide what's the better option based on that list, document that decision and why you took it (so you can always read back why a decision was made, the &lt;em&gt;most&lt;/em&gt; important thing about design documentation), move on. In this particular case, I didn't see any advantage of refactoring the code to obey some rule which is only important if you're going to split up assemblies (which I'm not planning to do in this case) so I left it in. &lt;/p&gt;  &lt;p&gt;You might wonder why I didn't present to you right away the pro/con list of the decision I started this post with. The main reason is that I wanted to show you that there is no such thing as &lt;em&gt;the right thing&lt;/em&gt; if there's no context given, or better: if &lt;em&gt;your&lt;/em&gt; situation isn't known. This is very important. Today, and in the years to come, you'll likely be exposed to articles, blog posts, books, lectures and what not, written by generous people who simply want to help you out, which will tell you what's &lt;em&gt;the right thing&lt;/em&gt; to do. I'd like you to keep one single thought in mind, whenever you read such an article, post etc.: Does the scenario this rule, this good advice, applies to actually match &lt;em&gt;my&lt;/em&gt; scenario? If not, be careful to apply that advice without proper thinking it through. Software engineering isn't an exact science: there's no such thing as a formula where you put something in and the result is calculated, our profession is about building an executable form of what's been described as the functionality of a system, however there are no turn-key solutions to make that possible: every situation &lt;em&gt;is&lt;/em&gt; different. &lt;/p&gt;  &lt;p&gt;Let's go back to the decision I started with and give it some context, a &lt;em&gt;scenario&lt;/em&gt;, the situation it occurred in. This might help you with what you thought instantly what the &lt;em&gt;right thing&lt;/em&gt; was when you read the first paragraph. In &lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; v3, the user can add meta-data obtained from multiple databases to a single project and choose which elements to obtain from these databases, e.g. which tables, which schemas etc. See the screenshot below for an impression. &lt;/p&gt;  &lt;p align="center"&gt;&lt;img border="0" alt="Database Meta Data retrieval wizard, step 2" src="http://www.xs4all.nl/~perseus/LLBLGenPro/sshots/LLBLGenProv3_ObtainMetaData.png" width="619" height="566" /&gt;     &lt;br /&gt;&lt;font size="1"&gt;LLBLGen Pro v3 alpha: Step 2 of meta-data retrieval wizard. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The screenshot above shows how the user obtains the meta-data, a simple click-through wizard with some fancy selection/filtering (not shown). The ability to select elements, also raises the question: &amp;quot;what if I selected a couple of tables I don't want to see anymore in my project?&amp;quot;. Or in other words: I want to be able to exclude elements (tables in this example) from the project later on without actually removing them from the database. In the scenario presented to the user this looks something like this:&lt;/p&gt;  &lt;p align="center"&gt;&lt;img border="0" alt="Context menu Catalog Explorer to exclude two tables" src="http://www.xs4all.nl/~perseus/LLBLGenPro/sshots/LLBLGenProv3_ExcludeItems.png" /&gt;     &lt;br /&gt;&lt;font size="1"&gt;LLBLGen Pro v3 alpha: Context menu (incomplete, not all features have been added yet!)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The above screenshot shows the ability to exclude the selected tables (Customer and Employee in this case) from the project. This means that the objects representing these two tables are removed from the meta-data data-structure of the Project (through a controller which asks the Project to exclude the elements at hand which will delegate the call further) and all mappings to these elements are cleared. This feature works, it removes the tables from the Tables collection in the schema object representing the schema the tables are in and as everything is observer-aware, events are raised which are picked up by mapping objects which clear themselves if they have the elements excluded as their target, all undo-able thanks to Algorithmia. &lt;/p&gt;  &lt;p&gt;When I wanted to implement the feature on the &lt;em&gt;Schema&lt;/em&gt; node I ran into a slight problem: a Schema isn't a &lt;em&gt;Schema Element&lt;/em&gt; like a table, view or stored procedure, it is a container, although it is contained in a Catalog. I had to refactor the code I had to also support these different elements (catalog, schema, database meta container, which all aren't a schema element). This gave me the hint that the whole setup might not be correct and I should simply create an interface like &lt;strong&gt;IExcludable&lt;/strong&gt; or something, implement that on all elements which are excludable and call an Exclude method on that. Sounds logical and feng shui-compliant with Common Sense Software Engineering (CSSE), don't you think?&lt;/p&gt;  &lt;p&gt;However this runs into a tiny problem: does every element know its container? Is the container of a table the schema (its logical container) or the Tables collection in the schema object (its physical container). To be able to work with meta-data, it's essential that a table knows its schema. However it doesn't need to know that it's in a Tables collection. A schema knows its parent catalog, but a catalog doesn't know it's parent container as it's not something it should be aware of (it doesn't have a logical container, although it has a physical container in the Project). Is it better to tell the element that it should remove itself from its parent's container, or is it better to tell the parent that a contained element has to be removed? Example: do you tell the schema that it should remove itself (which in turn will force the schema to tell its logical container (catalog) to remove the schema) or do you tell the catalog that a schema has to be removed? &lt;/p&gt;  &lt;p&gt;The interface idea sounds great, but requires that elements know their container (also for the catalog). It gives the freedom to implement the logic inside the elements which it is all about instead of in code outside the data-structures. On the other hand, code outside the data-structures and placed in a method in the Project class, which contains the meta-data, which controls the calls to the right parent is also tempting as it also knows the container of the catalog, something the catalog itself doesn't know. Yes, the Catalog owns the Schemas collection, but does it own the Schema elements inside the Schemas collection? &lt;/p&gt;  &lt;p&gt;So it comes down to:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font color="#000000"&gt;&lt;strong&gt;Interface route&lt;/strong&gt;. This route requires little code in Project, as an IExcludable is passed into a method on Project by the controller and the project simply calls the Exclude method on the object and the object has to take care of it being excluded (removed) from its parent. We've to make sure the Catalog knows its container as well which is outside its reach at the moment (other assembly) so logically not the right thing to do. Instead for the catalog, this requires some if/else code to call the container of the catalog as well. &lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;&lt;strong&gt;Manager code route&lt;/strong&gt;. This route uses some switch/case statement in Project and based on the element to exclude, it calls the proper container to exclude the element. This looks straight forward, but places knowledge what the parent of which element is, inside the Project class instead of the element itself. This could be less ideal when for example the parent type changes and you have to hunt for all the references to that parent and change that code everywhere. &lt;/font&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;One thing to note is that, as you can see in the second screenshot, multiple target database types can be in the same project. Telling a project to exclude a given table object isn't a matter of asking the single container of catalogs to remove the given table object, one first has to find the proper database specific store which contains the catalog with that table. A table itself doesn't have this knowledge of course, its parent schema's parent catalog does, at least the ID of the database. &lt;/p&gt;  &lt;p&gt;Still convinced what you picked as the right thing to do in the first paragraph is the right thing, or is it more complicated than what you initially thought? I know this scenario is very specific but that's &lt;strong&gt;precisely&lt;/strong&gt; the point: the question presented is very simple and likely you've made this same decision a lot of times before, as I have too. Yet, the specific scenario, the specific context the decision has to be made in makes things less trivial than it initially looked like. &lt;/p&gt;  &lt;p&gt;I don't believe in &lt;em&gt;do this and it will be all right&lt;/em&gt; kind of advice without a firm context description, so I'm not going to give you one. Instead, I'm giving you advice on how you yourself might be able to find the right decision in similar and other situations you will run into: make a pro/con list of each alternative, eventually prioritize these pro/con items if you will, and simply &lt;em&gt;look&lt;/em&gt; at the lists and make a decision based on them, make the decision which makes rationally the most sense, considering the pro/con lists. That's it. Make a decision, based on rational reasoning and cold hard facts and document it, implement that decision and move on. Don't let your decision be lead by what &lt;em&gt;looks like &lt;/em&gt;a turn-key 10-step process to get it &lt;em&gt;right&lt;/em&gt; which is applicable to any (and thus also yours) scenario/context. There's no such thing, every situation, every scenario is different, yours is too. Perhaps a guide tells you to componentize everything which will take you 2 weeks to complete and in the end 99% of the components are used by only one other component. Did you gain anything by that? It might be you actually made things more complex than the situation you had before you componentized everything. Who has to deal with that extra complexity? The people who gave you advice in a generic &amp;quot;Use ABC with XYZ and everything shall be great&amp;quot; article, or you? &lt;/p&gt;  &lt;p&gt;In the end, what matters is that you a) made &lt;em&gt;a&lt;/em&gt; decision and b) you documented the reason &lt;em&gt;why&lt;/em&gt; you made &lt;em&gt;that&lt;/em&gt; decision and didn't take one of the &lt;em&gt;the alternative(s)&lt;/em&gt;. If for example, after a year or two it turns out your decision wasn't the best, based on the knowledge you have &lt;em&gt;at that moment,&lt;/em&gt; you can always check the design decision documentation you've made of the decision, and conclude you did make the right decision back then, but based on other, perhaps incomplete (compared to the situation after two years) knowledge/information. That's life. As my wise mother always says: &amp;quot;If you'd know everything up front, it's not hard anymore to get rich&amp;quot;. &lt;/p&gt;  &lt;p&gt;What I decided? For this particular case I chose the interface route with the if/else for Catalog in the Project method. Yes, it's perhaps not that pretty due to the if-statement but the alternative isn't that great either and based on the pro/con items of both alternatives, the interface route seems the best choice. In this context, at this moment, with the information at hand. &lt;/p&gt;  &lt;p&gt;Should you do the same thing in the situation where you have to make the same decision? That's not a conclusion you should draw from this post, instead you should take my advice, make the pro/con list and decide for yourself what to do. It might be you make the same decision, it also might be you pick an alternative. That's ok, you have the pro/con list plus the reasoning to prove you made the right decision at that moment. That's what matters. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7071762" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=w80r8bg7sa4:TUKPrfK5JJ4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=w80r8bg7sa4:TUKPrfK5JJ4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=w80r8bg7sa4:TUKPrfK5JJ4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=w80r8bg7sa4:TUKPrfK5JJ4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=w80r8bg7sa4:TUKPrfK5JJ4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/w80r8bg7sa4" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/05/04/the-desperate-quest-for-doing-it-right.aspx</feedburner:origLink></item><item><title>inc(me.MVP)</title><link>http://feedproxy.google.com/~r/FransBouma/~3/4j7zXZgmGFU/inc-me-mvp.aspx</link><pubDate>Thu, 02 Apr 2009 08:03:03 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7022496</guid><dc:creator>FransBouma</dc:creator><slash:comments>6</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=7022496</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/04/02/inc-me-mvp.aspx#comments</comments><description>&lt;p&gt;Yesterday I received the MVP award for C# again, thanks Microsoft! &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileylaugh.gif" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7022496" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4j7zXZgmGFU:E9VGBHj4lI4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4j7zXZgmGFU:E9VGBHj4lI4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=4j7zXZgmGFU:E9VGBHj4lI4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4j7zXZgmGFU:E9VGBHj4lI4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=4j7zXZgmGFU:E9VGBHj4lI4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/4j7zXZgmGFU" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Community+News/default.aspx">Community News</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/04/02/inc-me-mvp.aspx</feedburner:origLink></item><item><title>The Undo-Redo paradox</title><link>http://feedproxy.google.com/~r/FransBouma/~3/sKr5kkLwOYQ/the-undo-redo-paradox.aspx</link><pubDate>Fri, 20 Mar 2009 14:10:31 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6981435</guid><dc:creator>FransBouma</dc:creator><slash:comments>21</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6981435</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/03/20/the-undo-redo-paradox.aspx#comments</comments><description>&lt;p&gt;In July 2008 I started development on &lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; v3's new designer. The first thing I realized was that I needed a good, solid, generic framework to base the new designer on, especially because v3 would introduce a new big feature: model-first entity model development. In short, model-first means that the user starts the designer and can build an entity model from scratch (so no meta-data available whatsoever) and create meta-data and mappings from that entity model, or modify an existing or reverse engineered model by adding new elements. So the user will edit, delete, and do other things which aren't based on any meta-data, but based on theory, thought processes and perhaps trial/error. In short: the user will make changes to a live model in memory and will try to undo and redo these changes during the process. Everywhere. Always. So undo/redo has to be present everywhere, and always in every situation. Removing an element, like an entity definition, should remove all its related and depending elements or at least make them update themselves and undo-ing that removal should restore the original state.&lt;/p&gt;  &lt;p&gt;The framework I had in mind would need to be able to undo any edit action, any change. I also needed a new set of data-structures to store the entity model in. In v2.x of LLBLGen Pro, the entity model is stored in an 'enclosed way': if an entity E has a relationship with entity F, it has a relationship object R which is stored inside E (if F also has a relationship with E, there's a relationship object representing that relationship and which is stored in F). While this might be a natural way of storing object graphs (the graph edges are the references between the vertices), it leads to a problem: you can't reason over the entire model, as it always requires traversal of the object tree in a way where you need to dig through an object (e.g. the EntityDefinition instance which contains the instance of the entity relationship) to get to other elements. A &lt;em&gt;graph&lt;/em&gt; object with vertices and edges (so the entities would be the vertices and the relationships would be the edges) would be easier to do reasoning over the model. &lt;/p&gt;  &lt;p&gt;To be able to undo any change to a model, you need to have some kind of mechanism to perform the change in the first place and then simply revert the action the mechanism performed. This is solved with the &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Command_pattern" target="_blank"&gt;Command pattern&lt;/a&gt;&lt;/em&gt;. In short, it describes a way to perform actions (the 'commands') onto a data-structure or other element and as you have described the action through a command, you can extend it to perform another action when the command action has to be 'undone' or better: rolled back. However, my v2.x code base of LLBLGen Pro doesn't use the command pattern to do its actions, as it never needed to: to get things done you call methods on objects which call other methods, set properties etc., the basic OO style of maintaining an object model in memory. Implementing everything through commands now seemed like a &lt;em&gt;lot&lt;/em&gt; of work: imagine &lt;em&gt;every&lt;/em&gt; property get/set action has to be done through commands so the change is undo-able, every method call made might change internal members and these changes have to be undoable as well.&lt;/p&gt;  &lt;h4&gt;Algorithmia&lt;/h4&gt;  &lt;p&gt;I decided to solve this properly and from the ground up so I started working on a separate project: &lt;strong&gt;Algorithmia&lt;/strong&gt;. Algorithmia started as a .NET 3.5 class library I wrote in my spare time to learn .NET 3.5's new lambda stuff and which contained some well-known algorithms and data-structures which weren't in the .NET 3.5 BCL (or not implemented in a useful manner). So I implemented in-place sort algorithms (so these sort a data-structure in-place, not like Linq's OrderBy() methods which return a new enumerable) as extension methods, a couple of priority queues and heaps like a full &lt;a href="http://en.wikipedia.org/wiki/Fibonacci_heap" target="_blank"&gt;Fibonacci Heap&lt;/a&gt;. Algorithmia seemed (and still is) perfect to add my general purpose algorithms and data-structures to, and the undo-redo algorithms and related classes are no exception. &lt;/p&gt;  &lt;p&gt;After some long, deep thinking I realized I needed two fundamental things to meet LLBLGen Pro v3 requirements: a general purpose undo/redo mechanism and a set of data-structures, like a graph structure which are undo/redo aware. The two separate areas should have 1 thing in common: undo/redo should be &lt;em&gt;transparent&lt;/em&gt; to the user (the developer). With transparent I mean:&lt;/p&gt;  &lt;pre class="c#" name="code"&gt;someObject.Name = &amp;quot;Some String&amp;quot;;&lt;/pre&gt;

&lt;p&gt;where the property set action in the statement above should be undoable (and redo-able). The traditional command pattern approach would have forced one to write such a simple statement with a command, so the action (setting the property) would be undoable by setting it again to the original value. I wanted it solved differently so I didn't need to write command calls &lt;em&gt;everywhere&lt;/em&gt; and I also could leverage databinding for example or events and other things build into the .NET framework.&lt;/p&gt;

&lt;h4&gt;Commands, Command queues and their overlord manager.&lt;/h4&gt;

&lt;p&gt;To understand what undo/redo really means and how complex it can get, let's look at an example. Say I have a graph with two entity definitions: Customer and Order, and a one to many relationship R between them. Furthermore I map a foreign key field onto R in Order (so it points to Customer's identifying fields, which happens to be CustomerID). All nice and dandy. I feel a bit bold today and I select Customer and hit the DEL key. Obviously, the Customer entity definition is deleted from the model. But that's not enough. To remove it from the model, I have to remove it from the graph and because I do that, I have a dangling relationship (R) which has to be removed from the graph as well. If R is removed, the foreign key field in Order also has to be removed as it's based on R. Pressing DEL sounds rather complex all of a sudden.&lt;/p&gt;

&lt;p&gt;The traditional command pattern approach suggests that you issue the action to remove Customer from the entity model graph through a command however that immediately gives a problem: what has to happen to the actions which follow immediately after the removal, like the removal of R and the foreign key field? Do we have to add these commands to the command which did the removal of Customer from the graph or not? If we don't, undo-ing the removal of Customer doesn't automatically undo the follow up actions as well, as these seem to be unrelated. But if we do add these commands to the initial command, it will create a complex piece of code which is also immediately unmaintainable as it has to know about all things which &lt;em&gt;could&lt;/em&gt; happen after we've removed Customer from the graph. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Command&lt;/strong&gt; 

  &lt;br /&gt;To &lt;em&gt;undo&lt;/em&gt; an action, you can take several approaches. For example, you could use the transactional approach where you make changes to a temporary space and finalize it when you commit the transaction. Another approach is to read the initial state right before the &lt;em&gt;Do&lt;/em&gt; action is performed and &lt;em&gt;Undo&lt;/em&gt; simply restores that state. I've taken the second approach as it is more flexible: there's no transaction to commit: a change is a change and it's final however, it's always undoable. What makes this easy is the introduction of lambda's in .NET 3.5. Do and Undo are simply lambda's. The command has support for lambdas which read the state before the Do lambda is called and the Undo action is simply passing in the original state into the Undo lambda and the action is undone. There are various bells and whistles added to that of course, but that's the basic idea.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Command Queue&lt;/strong&gt; 

  &lt;br /&gt;To be able to manage when to undo what, commands are placed in stack-like data-structures: the last command placed into the data-structure is the first to undo. However, that's a 1-dimensional data-structure. In my example above, undo-ing the removal of Customer requires the undo-ing of the removal of R and the removal of the foreign key field. So I created a &lt;em&gt;Command Queue&lt;/em&gt;. A Command Queue is internally a Linked List (with a more flexible implementation than BCL's as concatenating these Linked Lists takes O(1) as it should instead of BCL's LinkedList class) with a simple pointer where the last command is. Commands are placed in a Command Queue, one after the other. This gives the flexibility of undo-ing and redo-ing them by simply moving a pointer along the Linked List inside the Command Queue. &lt;/p&gt;

&lt;p&gt;To be able to undo a command which &lt;em&gt;spawned&lt;/em&gt; other commands, I placed a Command Queue inside every Command. This gives the advantage that when I undo a command, it first calls Undo on all commands in its own queue and then it performs the Undo of itself. Undo-ing a command inside its queue could mean that &lt;em&gt;that&lt;/em&gt; command also will perform an Undo action on several other commands first. And here we have our multi-dimensional structure we needed for the situation of our example. However it of course gives another problem: how do we get all these commands neatly nested into each other without any hassle?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Command Queue manager&lt;/strong&gt; 

  &lt;br /&gt;I created a thread-safe singleton class which manages the command queues, the CommandQueueManager. This manager is fairly straight forward and it's the interface for the developer to undo/redo anything, to enqueue and execute commands and to keep everything working in the right order. There are some static helper methods on the Command class to easily enqueue itself, but in general the manager is the one to talk to (ain't that always the case? &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileywink.gif" /&gt;) &lt;/p&gt;

&lt;p&gt;The bare-bones mechanism comes down to this: it has an active stack of Command queues and a command which comes in to be executed is simply placed in the command queue at the top of the stack. If a command is executed its queue is placed on top of this stack and every command that gets created while this command is executed is thus placed inside the queue of the command which originated it. When the command is done with its Do method, its queue is popped and the previous queue is now at the top of the stack, which can be the queue of the previous command or the main queue of the manager. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scopes and threads&lt;/strong&gt; 

  &lt;br /&gt;Singletons have the side-effect that there's just one instance at runtime, which is nice because that's the reason they're there. The downside is of course that multi-threaded applications have to deal with a shared resource and that's always a sign trouble is ahead if you're not careful. The manager is thread-safe, which means only one thread can queue and work with commands at any given time. Per thread there's also one stack, so different threads can't add commands to each other's command queues. In a way, per thread there's a unique &lt;em&gt;scope&lt;/em&gt;. Such a scope consists of a command queue stack. It might be handy in some cases in single-threaded approaches as well: what if you want to create a boundary in which a user can undo/redo actions but when the user closes the form for example the actions are final? That requires a unique scope for that edit form. The Command Queue manager can deal with that, you simply ask for a scope with a new ID and you get it. If you ask for the scope of an ID which was already known, the scope of that ID becomes active. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Back to our example...&lt;/strong&gt; 

  &lt;br /&gt;So let's go back to our Customer, Order, R and the foreign key field. The user selected Customer and pressed DEL. The UI controller calls into the main system and asks the Project to remove entity Customer. The Project then starts working, but what exactly does it have to do? Remember that I needed a graph to be undo/redo aware. The Entity Model is implemented using Algorithmia's graph class where entity definitions are vertices and relationships are edges (non-directed edges). The graph is undo-redo aware, it manages itself through commands. So removing the Customer entity definition from the Project is as simple as telling the graph to get rid of the Customer instance it has inside itself as a vertex. The UI controller called the single Project method through a command. That command's Command Queue was placed onto the stack of the current scope and its Do lambda was executed. All commands added to the Command Queue Manager will end up in this queue or in a nested queue, so undo-ing the removal will undo all these commands as well. &lt;/p&gt;

&lt;p&gt;The graph removes the vertex Customer from itself through a command, which is placed inside the UI call command's queue. The graph notices a dangling edge, R. It removes it too, also through a command, and this command is also placed in that same queue. And now things start to get interesting: when R was removed from the graph, the graph called a method on the edge which raised the edge's event ElementRemoved. Is anyone listing to that? Yes, the object which is used inside the foreign key field inside Order. As the relationship has been removed (as been told through the event), the foreign key field has no purpose anymore, and has to remove itself as well. As it is placed inside a command-aware list, called CommandifiedList&amp;lt;T&amp;gt;, it simply removes itself from its container though that container does the actual removal through a command. &lt;em&gt;That&lt;/em&gt; command ends up in... the queue of the removal of R, as that was the active command in progress and that command's queue is on the stack. &lt;/p&gt;

&lt;p&gt;So after all this, we have a nested set of commands which we can undo, in the right order, and also which we can redo, in the right order, &lt;em&gt;without&lt;/em&gt; the complexity of requiring command creation everywhere, being aware of which command is spawned from where... none of that at all: it's straight-forward .NET code like you and I are used to write. &lt;/p&gt;

&lt;p&gt;Undo-ing this Customer removal starts by calling the Undo method on that command. As that command contains a queue with two commands (removal of Customer from the graph and removal of R from the graph). It starts with the last command, which is the removal of R and calls Undo on that. The removal of R command has also commands in its queue, namely the removal of the foreign key field, and starts undo-ing that command first. This makes sure everything is played back in the right order. &lt;/p&gt;

&lt;p&gt;But what about that simple property setter example we started with? Let's look at the logic behind that simple statement and how things are made transparently undoable.&lt;/p&gt;

&lt;h4&gt;The little worker class under the hood: CommandifiedMember&lt;/h4&gt;

&lt;p&gt;The following code snippet shows a simple test class used in some unit-tests for the command functionality:&lt;/p&gt;

&lt;pre class="c#" name="code"&gt;public class HelperClass
{
    private enum HelperChangeType
    {
        Name
    }

    private readonly CommandifiedMember&amp;lt;string, HelperChangeType&amp;gt; _name;

    public HelperClass()
    {
        // create a new commandifiedmember instance and set the default value to empty string
        _name = new CommandifiedMember&amp;lt;string, HelperChangeType&amp;gt;(&amp;quot;Name&amp;quot;, 
                      HelperChangeType.Name, string.Empty);
    }

    public string Name
    {
        get { return _name.MemberValue; }
        set { _name.MemberValue = value; }
    }
}&lt;/pre&gt;

&lt;p&gt;To combine a lot of functionality around a single member which was needed in a lot of cases I created a class called CommandifiedMember. CommandifiedMember does a lot of things: it sets the value of the member using commands, so setting the value is undo-able. It checks whether the value to set is equal to the current value of the member, so it doesn't issue unnecessary commands. It raises events when the value changes so observers can subscribe on these changes and act accordingly. It has awareness of interfaces which might be implemented on values set as the member value. This is important in the case of the foreign key field of our example: if the identifying field's type changes, the foreign key field's type also changes. To be aware of that, it needs a signal from the identifying field it relates to. Simply changing the identifying field's type will raise an event which will end up in the foreign key field's member which notices this as it automatically subscribed to the event as it recognized it. The member then simply raises an event so the foreign key field notices this and can act accordingly. Similar to removing the relationship R for example: R is removed, so it raises an event that it's been removed. Observers, like CommandifiedMember instances which refer to it, can now act accordingly and set themselves to null or raise an event for example. &lt;/p&gt;

&lt;p&gt;The code snippet above doesn't show it, but there's more built in: it is also IDataErrorInfo aware. This is done through an object which is pluggable into a CommandifiedMember and which is also part of Algorithmia, called ErrorContainer. CommandifiedMember is aware of validation and calls a virtual method before it continues to call the Do action. It takes care of logging the error in the ErrorContainer and if a correct value is accepted, it clears the error accordingly. The code snippet above also shows the usage of an enum which is used for the change-type specification. This is useful if you want to use undo/redo to its full potential and implement a lot of logic through events using the Observer pattern: HelperClass could sport an ElementChanged event which propagated the HelperChangeType to its subscribers, which could then easily determine &lt;em&gt;what&lt;/em&gt; exactly changed in HelperClass without the necessity for a lot of events and also avoiding string-based approaches like INotifyPropertyChanged. &lt;/p&gt;

&lt;p&gt;So with the CommandifiedMember in place, I can create the following, undo/redo aware code:&lt;/p&gt;

&lt;pre class="c#" name="code"&gt;HelperClass h = new HelperClass();
h.Name = &amp;quot;Foo&amp;quot;;&lt;/pre&gt;

&lt;p&gt;By setting the property, I indirectly create a command which sets the actual member, compile time checked. I can undo this action by simply asking the Command Queue Manager to undo the last command. However, I'm not even aware that setting the property is an undo/redo aware affair nor do I care. I simply write code like I used to do, without the hassle of creating commands to make sure things are undoable later on: missing one spot makes some things suddenly not undoable, with the CommandifiedMember, that's not possible. As it's transparent, I can bind the Name property of an instance of HelperClass to a control and have undo/redo awareness without even writing any code: if the control sets the value of Name, it will be undoable. Of course, to make the control become aware of the fact that Name has been rolled back, I have to implement INotifyPropertyChanged on HelperClass, but that's pretty easy to do: I get an event when _name changes so I can anticipate on the change by a simple event handler:&lt;/p&gt;

&lt;pre class="c#" name="code"&gt;public class BindableHelperClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private enum HelperChangeType
    {
        Name
    }

    private readonly CommandifiedMember&amp;lt;string, HelperChangeType&amp;gt; _name;

    public BindableHelperClass()
    {
        _name = new CommandifiedMember&amp;lt;string, HelperChangeType&amp;gt;(&amp;quot;Name&amp;quot;, HelperChangeType.Name, string.Empty);
        _name.ValueChanged += new EventHandler&amp;lt;MemberChangedEventArgs&amp;lt;HelperChangeType, string&amp;gt;&amp;gt;(_name_ValueChanged);
    }

    private void OnPropertyChanged(string propertyName)
    {
        if(this.PropertyChanged!=null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private void _name_ValueChanged(object sender, 
            MemberChangedEventArgs&amp;lt;HelperChangeType, string&amp;gt; e)
    {
        switch(e.TypeOfChange)
        {
            case HelperChangeType.Name:
                OnPropertyChanged(&amp;quot;Name&amp;quot;);
                break;
        }
    }

    public string Name
    {
        get { return _name.MemberValue; }
        set { _name.MemberValue = value; }
    }
}&lt;/pre&gt;

&lt;p&gt;I introduced a switch for checking on the change type, which is a little overkill as there's just 1 member, but you get the idea. It's not really more code than one would write in the case of a simple normal class, however you get value checking, event raising, undo/redo etc. all for free. Binding the Name property of an instance of this class to a control, say a TextBox, will make it possible to edit this instance with undo/redo awareness. &lt;/p&gt;

&lt;p&gt;So where does this 'Paradox' of the title come into play exactly? Well I think you now know enough information to understand the following example of it. &lt;/p&gt;

&lt;h4&gt;The Undo/Redo 'Paradox'&lt;/h4&gt;

&lt;p&gt;The Undo/Redo 'paradox' as I dubbed it (probably a bad name, so forgive me), is the contradiction between what the user thinks what's being undone and what the system thinks the user means that should be undone. I've specified 'paradox' in quotes as sometimes people call things a paradox while they clearly aren't a paradox and I'm not yet sure if this is a true paradox, though I have a feeling it unfortunately is. &lt;/p&gt;

&lt;p&gt;I've created a real-life example of the paradox in the following screenshot. It's a screenshot of a part of the LLBLGen Pro v3 GUI (where I moved everything close together so it fits in a tiny area): &lt;/p&gt;

&lt;p&gt;&lt;img height="541" src="http://www.xs4all.nl/~perseus/LLBLGenPro/sshots/v3_undoredoparadox.png" width="705" /&gt;

  &lt;br /&gt;

  &lt;br /&gt;There's a lot of info in this tiny screenshot and I'll describe briefly what's important to understand the problem. The project shown is a dummy test project with a couple of random entities. At the left you'll see the Project Explorer which shows the groups, the entities, the value types and the typed lists (some elements are still not there, in the case you're missing something. It's not done yet &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileywink.gif" /&gt;). At the right of the Project Explorer you see the editor for the Customer entity which is a subtype of Person, and below it a debug panel for the command queue manager where I can see which commands are in the queue and inside which other commands they're stored. As you can see, after I've loaded the project, I created a typed list called Test which spawned one command, the addition of adding a new item to a CommandifiedList. The arrow suggests it's the current command, so pressing cntrl-Z or clicking Undo in the toolbar will undo that command. &lt;/p&gt;

&lt;p&gt;So, what's the problem? Well, it's at the top: I typed a space in the entity name and tabbed away from the textbox. The validator plugged into the CommandifiedMember kicked in and denied the value and reported an error: names can't have spaces. So the cursor stays in that textbox. &lt;/p&gt;

&lt;p&gt;What will happen if I press cntrl-Z or click Undo? Will that undo the change I made inside the textbox by undoing the insertion of the space, or will it undo the last command it knows, creating the typed list?&lt;/p&gt;

&lt;p&gt;The 'paradox' is that the system isn't aware of any command setting the Entity Name to an invalid value (as that would make the project become erroneous: what if I entered a name which is already taken?) however the user is. The textbox has a cntrl-Z mechanism, where pressing cntrl-Z will undo the changes in the textbox, which in the case above would remove the inserted space and everything would be normal. However, what does the user mean: local undo or global undo when issuing the undo command and when are local undo's all of a sudden global undo's?&lt;/p&gt;

&lt;p&gt;In general: there's a global undo/redo system with a global access mechanism (cntrl-Z/cntrl-Y) and there are two different scopes in play: the local editor scope and the global model scope: issuing an Undo action raises the question: do you want to undo a local action which might not be propagated to the global model scope (e.g. the change hasn't been processed yet) or do you want to undo the last change at the global model scope level? This isn't an easy question to answer, as I hope to illustrate in the explanations below.&lt;/p&gt;

&lt;p&gt;A perhaps more well-known example of this problem is the issue you run into with the Windows Forms designer and after that when you change code in the form class: after you've made some changes to a form in design view, you switch to the class and add some code, like a member declaration. Then press cntrl-Z a couple of times till you've undone all your changes to the code and you'll likely see a message box pop up which tells you that you can undo one last thing which can't be redone. Why is that? &lt;/p&gt;

&lt;p&gt;It's the same issue: suddenly the local scope you were working in (the code editor) has no more commands to undo and pressing cntrl-Z again then raises the question: does the user want to undo more commands in the editor (though there aren't any left) or does the user want to undo things on a model /global scale, like the changes made to the design view of the form? That's unclear and can't be solved by the undo/redo system by itself: perhaps the user simply only wants to undo/redo the changes in the editor (like the textbox or code editor) and stop undo-ing commands if there aren't any left, &lt;em&gt;in that scope&lt;/em&gt;. However, perhaps the user wanted to undo things on a global scale &lt;em&gt;after&lt;/em&gt; all commands in the local scope are undone and to do that the user has to &lt;em&gt;leave&lt;/em&gt; the editor to signal that the undo action is not for a local scope. This is of course confusing and unclear for a user as the user isn't aware of the length of command queues or even local / global scopes. &lt;/p&gt;

&lt;p&gt;In the specific situation of the screenshot above, there are a couple of obvious things which one might want to try to solve this paradox, like disabling the global undo/redo mechanism when an error occurs, however that doesn't solve the situation where I don't create an error but simply append a couple of characters to the name and then press cntrl-Z. One could think of introducing a scope used only for the textbox, but it then gets tricky to get rid of that scope once the value is indeed valid as that action has to be in the global scope to be able to be undone on a global scale (so I don't have to go back to the textbox to undo the name change). Another solution might be to store the invalid value in the model and simply use the mechanism available so pressing cntrl-Z will undo the change which caused the error. The downside is that if the user presses cntrl-S after the change, the erroneous value is saved which could cause a problem, for example if the file format is in an XML format and elements are referenced by name, so what happens if I specify a name which is already in use, which is an error trapped by the validator, however I still save the project?&lt;/p&gt;

&lt;p&gt;I can't find a simple solution for this 'paradox', and I fear there isn't one either, but perhaps some solution pops up soon. &lt;/p&gt;

&lt;p&gt;LLBLGen Pro v3.0 is slated for release later this summer/autumn, with support for LLBLGen Pro Runtime Framework, Entity Framework, NHibernate and Linq to Sql,&amp;#160; and Algorithmia is shipped with LLBLGen Pro v3, very likely in sourcecode form and a flexible license so you can use it in your own applications as well. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6981435" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=sKr5kkLwOYQ:EAgDX_NzRcI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=sKr5kkLwOYQ:EAgDX_NzRcI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=sKr5kkLwOYQ:EAgDX_NzRcI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=sKr5kkLwOYQ:EAgDX_NzRcI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=sKr5kkLwOYQ:EAgDX_NzRcI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/sKr5kkLwOYQ" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/03/20/the-undo-redo-paradox.aspx</feedburner:origLink></item><item><title>[Dutch] Devnology Code Fest</title><link>http://feedproxy.google.com/~r/FransBouma/~3/AW9Up4KzYzI/dutch-devnology-code-fest.aspx</link><pubDate>Tue, 17 Mar 2009 12:47:54 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6970180</guid><dc:creator>FransBouma</dc:creator><slash:comments>7</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6970180</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/03/17/dutch-devnology-code-fest.aspx#comments</comments><description>&lt;p&gt;(Sorry English speaking visitor, this post is in Dutch, as it's about a Dutch user group meeting)&lt;/p&gt;  &lt;p&gt;In Nederland hebben we een aantal gebruikersgroepen die op gezette tijden meetings organiseren voor developers. Aan dit aantal is een nieuwe toegevoegd, Devnology (&lt;a href="http://www.devnology.nl"&gt;http://www.devnology.nl&lt;/a&gt;). Devnology is niet zozeer gericht op het houden van meetings waarbij 1 persoon een praatje houdt en de rest poogt niet in slaap te sukkelen, het is meer gericht op discussie en interactie tussen developers, samen bezig zijn met code, software engineering en andere aan ons vak gerelateerde zaken. Ook is Devnology niet gelimiteerd tot .NET alleen maar zijn andere talen en platforms even welkom. Het gaat tenslotte om software engineering en niet om de laatste truuks voor een random MS product.&lt;/p&gt;  &lt;p&gt;Op 1 april houdt Devnology &lt;a href="http://devnology.nl/volgende-bijeenkomst/details/4-code-fest-game-of-life" target="_blank"&gt;haar eerste meeting&lt;/a&gt;, een Code Fest: je krijgt vooraf een opdracht en wie de beste implementatie maakt wint. De opdracht deze keer is: programmeer de Game of Life, een bekend concept, en de keuze van platform en taal is vrij. Deze opzet komt me bekend voor van vroeger uit de &lt;a href="http://www.scene.org" target="_blank"&gt;demoscene&lt;/a&gt;, waar op demo-parties ook dit soort compo's gehouden werden. Het leuke aan dit soort dingen is dat enerzijds de competitie je toch dwingt je best te doen en anderzijds de discussies met mede-developers ter plaatse altijd wel wat nieuwe kennis en info opleveren waar je wat aan hebt.&lt;/p&gt;  &lt;p&gt;De opdracht van Game of Life is op het eerste gezicht wellicht wat een dood spoor maar je kunt op zoveel manieren dit probleem aanpakken dat het nadenken daarover, het uitpuzzelen welke benadering juist die originele oplossing oplevert, juist je tot ideeen kan brengen waar je als software engineer baat bij hebt, in je vak en dus in je dagelijks werk. &lt;/p&gt;  &lt;p&gt;Devnology gaat in juni ook een Open Spaces meeting houden en daar kijk ik nu al naar uit. &lt;/p&gt;  &lt;p&gt;Ik ben van de partij op 1 april. Zie jullie daar!&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6970180" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=AW9Up4KzYzI:bFqlpa1gRkU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=AW9Up4KzYzI:bFqlpa1gRkU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=AW9Up4KzYzI:bFqlpa1gRkU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=AW9Up4KzYzI:bFqlpa1gRkU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=AW9Up4KzYzI:bFqlpa1gRkU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/AW9Up4KzYzI" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Community+News/default.aspx">Community News</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/03/17/dutch-devnology-code-fest.aspx</feedburner:origLink></item><item><title>Choose .Concat() over .Union() if possible</title><link>http://feedproxy.google.com/~r/FransBouma/~3/gBRNZjXEaY4/choose-concat-over-union-if-possible.aspx</link><pubDate>Wed, 04 Mar 2009 10:25:28 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6937265</guid><dc:creator>FransBouma</dc:creator><slash:comments>10</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6937265</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/03/04/choose-concat-over-union-if-possible.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I've reworded a sentence as it was too vague. Sorry for that.&lt;/p&gt;  &lt;p&gt;Here's a simple performance tip which can benefit you without doing any effort. Linq to Objects has two methods to combine two sequences together, both with different characteristics: Union() and Concat(). The difference in characteristics makes it possible to gain performance without doing anything difficult. Let's look at a simple example first:&lt;/p&gt;  &lt;p&gt;Say we have two lists of integers: A: {1, 2, 3, 4} and B: {1, 2, 5, 6}. When using A.Union(B), a set union is executed, which results in { 1, 2, 3, 4, 5, 6}. When A.Concat(B) is used, the sequences are simply concatenated and { 1, 2, 3, 4, 1, 2, 5, 6} is the result. Pretty straight forward stuff. If you do not want duplicates in the second sequence to appear in the resulting sequence, Union() is necessary. However, in the case where it's impossible to have duplicates in the second sequence or you don't care if duplicates in the second sequence appear in the resulting sequence, Concat() is a better choice. &lt;/p&gt;  &lt;p&gt;It seems obvious that Union() is more performance intensive than Concat(): Contact() simply makes sure the enumerator returned enumerates over the two sequences, Union() filters out duplicates in the second sequence. If your sequences have a lot of elements, using Union() will make the operation become significantly slower.&lt;/p&gt;  &lt;p&gt;In the past 8 months I've written a lot of Linq to Objects queries and today I saw:&lt;/p&gt;  &lt;pre class="c#" name="code"&gt;/// &amp;lt;summary&amp;gt;
/// Gets the entity mapping targets in this meta-data store
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;all tables/views, ordered by catalogname/schemaname/tablename unioned with 
/// all views ordered by catalogname/schemaname/viewname&amp;lt;/returns&amp;gt;
internal IEnumerable&amp;lt;IEntityMapTargetElement&amp;gt; GetEntityMappingTargets()
{
    return from c in this.PopulatedCatalogs
           from s in c.Schemas
           from e in s.Tables.Cast&amp;lt;IEntityMapTargetElement&amp;gt;()
                     .Union(s.Views.Cast&amp;lt;IEntityMapTargetElement&amp;gt;())
           orderby c.CatalogName ascending, s.SchemaOwner ascending, e.Name ascending
           select e;
}&lt;/pre&gt;

&lt;p&gt;It turned out I happened to have used Union() in many cases in the code where two sequences had to be merged into one sequence, however it was impossible to have duplicates in the second sequences in these queries. Must be an old strain of SQL-itis, I think: &amp;quot;Oh I have two sets to combine to one set: UNION&amp;quot;. However, in the query above, it's not possible to have duplicates in the second sequence: there aren't views in the set of Tables and vice versa. So this same query could be written with a Concat(), saving performance as the second set doesn't have to be filtered from duplicates. &lt;/p&gt;

&lt;p&gt;If you too have the habit to use .Union() to combine sequences, pay attention to that second sequence: if it can't have duplicates (make sure it also doesn't contain duplicates in the future!), it's better to use Concat() instead of Union().&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6937265" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=gBRNZjXEaY4:gISmpx_Fc3U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=gBRNZjXEaY4:gISmpx_Fc3U:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=gBRNZjXEaY4:gISmpx_Fc3U:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=gBRNZjXEaY4:gISmpx_Fc3U:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=gBRNZjXEaY4:gISmpx_Fc3U:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/gBRNZjXEaY4" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/03/04/choose-concat-over-union-if-possible.aspx</feedburner:origLink></item><item><title>Winforms Gotcha: Form.Close() doesn't always call Dispose()</title><link>http://feedproxy.google.com/~r/FransBouma/~3/VhsUkMOhBhU/winforms-gotcha-form-close-doesn-t-always-call-dispose.aspx</link><pubDate>Fri, 27 Feb 2009 17:06:18 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6931057</guid><dc:creator>FransBouma</dc:creator><slash:comments>12</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6931057</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/02/27/winforms-gotcha-form-close-doesn-t-always-call-dispose.aspx#comments</comments><description>&lt;p&gt;I just ran into a weird issue. During profiling I saw that controls on a form which was already closed were still reacting to events. I checked whether the Dispose() routine of the particular Form was called, but it wasn't. However, the Dispose() routine of other forms was called after it was closed, as in: immediately. &lt;/p&gt;  &lt;p&gt;The difference between the two situations was that if I used Form.ShowDialog(parentForm), a call to Close() on the particular form &lt;em&gt;didn't&lt;/em&gt; call Dispose. Checking the Form.Close() documentation describes this behavior: &lt;/p&gt;  &lt;blockquote&gt;The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.&lt;/blockquote&gt;  &lt;p&gt;I never knew that. It's easy to overlook, as opening a form with Show() will result in a call to Dispose when Close() is called. Not calling Dispose (or better: wrap the Form usage in a using block) will lead to a memory leak and worse: could lead to hard-to-find bugs because event handlers aren't cleaned up. &lt;/p&gt;  &lt;p&gt;So just in case you use ShowDialog() or ShowDialog(form) to show modal dialogs in winforms, be aware that you've to call Dispose() yourself. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6931057" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=VhsUkMOhBhU:4AkwpCXSYIw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=VhsUkMOhBhU:4AkwpCXSYIw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=VhsUkMOhBhU:4AkwpCXSYIw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=VhsUkMOhBhU:4AkwpCXSYIw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=VhsUkMOhBhU:4AkwpCXSYIw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/VhsUkMOhBhU" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/WinForms/default.aspx">WinForms</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Windows+Forms/default.aspx">Windows Forms</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/02/27/winforms-gotcha-form-close-doesn-t-always-call-dispose.aspx</feedburner:origLink></item><item><title>Soft-deletes are bad, m'kay?</title><link>http://feedproxy.google.com/~r/FransBouma/~3/PVYE6CFMTPY/soft-deletes-are-bad-m-kay.aspx</link><pubDate>Thu, 19 Feb 2009 10:09:20 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6916703</guid><dc:creator>FransBouma</dc:creator><slash:comments>39</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6916703</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/02/19/soft-deletes-are-bad-m-kay.aspx#comments</comments><description>&lt;p&gt;Have you ever ran into database tables with a field which is used to mark if a row has been 'deleted' ? Probably. These fields are used to implement 'soft-deletes'. For the soft-delete impaired, a quick introduction. Soft-deletes are row deletes which are not really happening: instead of removing the row from the database table, a field in the row is set to a value which signals that the row is officially 'deleted'. Every &lt;em&gt;SELECT&lt;/em&gt; statement on that table is then filtering on that field's value so only rows which aren't marked as 'deleted' are returned (as the deleted data is not there anymore, semantically).&lt;/p&gt;  &lt;p&gt;If this sounds rather awkward, it is. However, there are people who insist in having soft-deletes instead of real deletes, because it allows them to go back in time, to look back at the data that was deleted, as all data is, well... , still there. A small group of those people even believes that soft-deletes allows them to roll-back to deleted data, a kind of 'undo' facility. &lt;/p&gt;  &lt;p&gt;The truth is, soft-deletes using status fields in rows is a bad solution to the real problem. Fortunately there are alternatives. &lt;/p&gt;  &lt;p&gt;First let's have to look at &lt;em&gt;why&lt;/em&gt; people would want soft-deletes. In general there are two reasons, which are already mentioned above: to be able to look at deleted data and to be able to roll-back to deleted data. Let's discuss the second reason first: rolling back to deleted data. &lt;/p&gt;  &lt;h4&gt;Roll-back to deleted data is hard.&lt;/h4&gt;  &lt;p&gt;Let's use Northwind as our example database. Let's say we don't delete rows from that database, but flag them as 'deleted' using a new field, &lt;em&gt;IsDeleted (bit)&lt;/em&gt;, added to every table. If you want to roll-back a deleted Order row, it looks as simple as setting the 'IsDeleted' field to 0, right? Though, what if that Order row refers to a deleted Customer row using its CustomerID foreign key? For the RDBMS, it's OK, as the 'deleted' Customer row is still in the Customers table, it just has its IsDeleted field set to 1. However, executing a SELECT statement which fetches the just recovered Order row with its Customer row will run into a problem: the Customer isn't &lt;em&gt;technically&lt;/em&gt; there: the mandatory IsDeleted filter prohibits that the Customer row is showing up. The only solution to this is to also recover the deleted Customer row. Order might have had OrderDetail rows as well, which requires the OrderDetail rows to be recovered as well. &lt;/p&gt;  &lt;p&gt;In short, recovering a row is not what's this is all about, it's about recovering a &lt;em&gt;graph&lt;/em&gt;. Recovering graphs instead of table rows is much more complicated, due to the dependencies between the involved entity instances (rows). Writing roll-back code for this is therefore likely a complex affair, especially if you want to make sure the data-integrity of the working set is still 100% correct (so all rows involved in the recovered graph indeed have their IsDeleted flag set to 0 and are part of the working set). In the end you'll run into issues where rows have to be merged, similar to source-control systems (e.g. in the situation where a row becomes deleted several times in different graphs). So rolling back graphs is not likely going to be implemented in the average system, it's therefore not the main reason for soft-deletes.&lt;/p&gt;  &lt;p&gt;On to the first reason, looking back at old data. &lt;/p&gt;  &lt;h4&gt;Old data is old for a reason.&lt;/h4&gt;  &lt;p&gt;When a system deletes rows from a table, it's hopefully done inside a transaction, so when something goes wrong, the delete is 'undone'. When the transaction completes, the delete is final, and the data is gone. If you ever would want to look at the old data (the data you just deleted) again, you can't, it's gone. Let's ignore that some people can't throw anything away (&amp;quot;I might want to look at it in 2 years, then what!? &amp;lt;&lt;em&gt;wild panic&lt;/em&gt;&amp;gt;&amp;quot;) and focus on what 'delete' actually means: it means that the data is considered 'no longer needed' and therefore removed from the &lt;em&gt;working set&lt;/em&gt;. If the data was necessary after the delete, don't execute the delete in the first place, it's the same with your file system really. &lt;/p&gt;  &lt;p&gt;However, when 'data is no longer needed' doesn't mean it is totally worthless in all situations: there's a situation where old data could be useful: for reports on history of an entity, when happened what, etc.. Though when will those reports be ran? Every 5 minutes? Will the average user of the system look at historic data all day long or work with the actual working set? The answer to these questions is likely the same: functionality consuming historic (deleted) data is rarely used compared to the functionality consuming working set (not deleted) data.&lt;/p&gt;  &lt;p&gt;Let it be clear that it sometimes is &lt;em&gt;required&lt;/em&gt; for legal reasons not to toss away data, however in other situations the same requirement actually lead to different solutions: old email is archived in archives and not kept in the in-box. Is that solution useful for this situation as well?&lt;/p&gt;  &lt;h4&gt;Implications of using soft-deletes&lt;/h4&gt;  &lt;p&gt;So the main reasons why some people want this is clear, however what are the implications when soft-deletes are used? Below I've mentioned a couple, though I'm sure there are more, though I think the list below is already convincing enough to look at another solution instead.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Queries become very complex. &lt;/strong&gt;Make no mistake, once you introduce a field to signal if a row has been deleted, you have to make sure &lt;em&gt;every &lt;/em&gt;table reference is accompanied by a filter on that &lt;em&gt;IsDeleted&lt;/em&gt; status field. &lt;em&gt;Every table reference&lt;/em&gt;. If you forget one, it's over: your data is then officially not correct. Maintainability will become more cumbersome, and as most time on a software project is spend on maintenance, it's something which will hurt the project, hard.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Queries become slower over time.&lt;/strong&gt; Every 'deleted' row is still there, and for the database system the row is just an ordinary row like any other. This means that DML operations on the rows will become slower, but especially SELECT statements will become slower over time: the percentage of rows which are 'live' of the total number of rows in the table is getting smaller, as more and more rows will become 'deleted'. This baggage could hurt in the long run, especially in tables with a lot of inserts/deletes: the working set might stay the same (e.g. 10K rows) but the total set of rows grows every day so the total number of rows might be millions. When you have millions of rows in the table while the actual set of rows which are 'not deleted' is a small percentage of that, it will influence the performance of queries dramatically. Compare that to a table with the actual set of rows you've to work with. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Using constraints (UC, FK) is impossible&lt;/strong&gt;. Using a unique constraint (UC) is not really possible, as the RDBMS will take into account the rows which are 'deleted' as well. So a value might be unique for the rows in the &lt;em&gt;working set&lt;/em&gt;, but for the total set of rows in the table it doesn't have to be unique and the update or insert fails. In our example above with Customer and Order, we've seen that foreign key constraints are not really working anymore either, as they don't protect us from 'deleting' a PK side while keeping the FK side: for the RDBMS, both rows are still there and everything is fine (which is not the case)&lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;A better solution to these requirements&lt;/h4&gt;  &lt;p&gt;There's a better solution, and I've already mentioned it briefly: archiving. RDBMS's (I assume you're using a proper, professional, solid ACID compliant database, not some toy RDBMS) usually sport a system called &lt;em&gt;triggers&lt;/em&gt;. Triggers are neat things: they get called when something happens. You can compare them to event handlers really: an event occurs (e.g. a row gets deleted from a table) and the trigger responsible for handling that event is called. Additionally, the trigger is called in the same transaction as the code which triggered the trigger. So all actions taken inside a trigger are rolled back when the transaction containing the code which triggered the trigger is rolled back. &lt;/p&gt;  &lt;p&gt;If you look closely at the two main reasons for soft-deletes, you'll recognize that both can be satisfied with simply keeping the data around which is deleted by DELETE statements: looking back at old, deleted data is possible wherever the old data is located and rolling back deleted data is not going to be less complex when the data is located elsewhere, as the complexity is in the graph rollback mechanism, not the location of the data to rollback to. &lt;/p&gt;  &lt;p&gt;This leads to the solution of an archiving database. An archiving database is a catalog (or schema if you wish) which contains the same table definitions as the real database, with perhaps no UC or FK constraints, as data integrity is implied by the data integrity of the source data (after all, it's just for archiving data consistent data). Every table of which you want to keep deleted data around in the real database now gets a DELETE trigger which simply grabs the row(s) deleted and inserts them in the same table in the archiving database. If the transaction fails, the inserted rows in the archiving database roll back too, if the transaction succeeds, the data is successfully archived and still available. Additionally, you could add date/time fields to the rows in the archiving database to store exact dates and times when the row was deleted, the trigger can insert these values when the deleted row is inserted. &lt;/p&gt;  &lt;p&gt;This makes sure the data is still available, so the reasons why people want this are still met, though it doesn't pollute the working set for the application anymore, and the implications of soft-deletes are gone. The only thing you've to be sure of is that the triggers and the archive database are maintained together with the real database (so schema changes in the real database are applied to the archive database as well, or you could go overboard and add a new archive database!). However, that's a small price to pay compared to the overly complicated queries one has to write (even with O/R mappers) and work with, queries which also have to be maintained and documented for the length the application is in use. Using the triggers and the archive database, the application can be written normally, can be tested normally, and no data is thrown away. Ever. One could extend this system with an UPDATE trigger as well, so updates are also tracked, so value deletes on the field level could be tracked as well. &lt;/p&gt;  &lt;p&gt;So do yourself a favor, next time someone tells you to use soft-deletes, discuss the implications and offer this alternative solution. Everyone will be better off: you, the customer, and the group of people who will maintain the system for the next 20 years. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6916703" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=PVYE6CFMTPY:-wdKN2394ww:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=PVYE6CFMTPY:-wdKN2394ww:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=PVYE6CFMTPY:-wdKN2394ww:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=PVYE6CFMTPY:-wdKN2394ww:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=PVYE6CFMTPY:-wdKN2394ww:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/PVYE6CFMTPY" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Database+_2F00_+SQL+Server/default.aspx">Database / SQL Server</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/02/19/soft-deletes-are-bad-m-kay.aspx</feedburner:origLink></item><item><title>Happy 2009!</title><link>http://feedproxy.google.com/~r/FransBouma/~3/ZIXQ2rfMto8/happy-2009.aspx</link><pubDate>Thu, 01 Jan 2009 14:27:20 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6811044</guid><dc:creator>FransBouma</dc:creator><slash:comments>8</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6811044</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2009/01/01/happy-2009.aspx#comments</comments><description>&lt;p&gt;To all my readers, and everyone else: I hope you all have a great, productive, healthy, awesome 2009!&lt;/p&gt;  &lt;p&gt;For me personally, 2009 will be a big year with the release of &lt;a href="http://www.llblgen.com/" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; v3, which I think will be a serious milestone in my vision about how people should approach the generic problem of Data Access in software. It will be a while before I can show anything, but I'm sure it will be worth the wait. &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileyregular.gif" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6811044" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=ZIXQ2rfMto8:i85FlG58dvU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=ZIXQ2rfMto8:i85FlG58dvU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=ZIXQ2rfMto8:i85FlG58dvU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=ZIXQ2rfMto8:i85FlG58dvU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=ZIXQ2rfMto8:i85FlG58dvU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/ZIXQ2rfMto8" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Community+News/default.aspx">Community News</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2009/01/01/happy-2009.aspx</feedburner:origLink></item><item><title>Small interview with me about blogging</title><link>http://feedproxy.google.com/~r/FransBouma/~3/ldiU69a96Xc/small-interview-with-me-about-blogging.aspx</link><pubDate>Wed, 03 Dec 2008 13:54:56 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6763932</guid><dc:creator>FransBouma</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6763932</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2008/12/03/small-interview-with-me-about-blogging.aspx#comments</comments><description>&lt;p&gt;
&lt;a href="http://thecodejunkie.blogspot.com" target="_blank"&gt;Andreas H&amp;aring;kansson&lt;/a&gt; did a couple of interviews with various people from the .NET blog community about... blogging &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileyregular.gif" border="0"&gt;. The &lt;a href="http://thecodejunkie.blogspot.com/2008/03/moment-with-frans-bouma-on-subject-of.html" target="_blank"&gt;interview with me is now available here&lt;/a&gt;. 
&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6763932" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=ldiU69a96Xc:TXmLp4EcsKQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=ldiU69a96Xc:TXmLp4EcsKQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=ldiU69a96Xc:TXmLp4EcsKQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=ldiU69a96Xc:TXmLp4EcsKQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=ldiU69a96Xc:TXmLp4EcsKQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/ldiU69a96Xc" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Community+News/default.aspx">Community News</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2008/12/03/small-interview-with-me-about-blogging.aspx</feedburner:origLink></item><item><title>If the Chief-Architect doesn't decide... who does?</title><link>http://feedproxy.google.com/~r/FransBouma/~3/g4d5pJ1usQQ/if-the-chief-architect-doesn-t-decide-who-does.aspx</link><pubDate>Fri, 21 Nov 2008 10:04:12 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6749210</guid><dc:creator>FransBouma</dc:creator><slash:comments>10</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6749210</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2008/11/21/if-the-chief-architect-doesn-t-decide-who-does.aspx#comments</comments><description>&lt;p&gt;
Yesterday I read this &lt;a href="http://blogs.msdn.com/ricom/archive/2008/11/18/the-visual-studio-tech-roadmap-starring-visual-studio-2010.aspx" target="_blank"&gt;great article about VS.NET's technical roadmap&lt;/a&gt;, posted by &lt;a href="http://blogs.msdn.com/ricom" target="_blank"&gt;Rico Mariani&lt;/a&gt;. Rico is the Chief Architect of Visual Studio, and he explains what that title means as follows:
&lt;blockquote&gt;I am the Chief Architect but I'm also *only* the Chief Architect, I don't make the final decisions about what goes in the product, not even combined with the other architects.  Jointly we come up with the long term technology roadmap, it indicates key problems that need to be solved for the long-term health of the product among other things, but these things cannot usually be mapped directly in to features in a particular release.  So, while it's true that I have a significant effect on what we do, it is inadvisable to take any of what I write as some kind of commitment to deliver particular features; rather I talk about examples of things that we might do that are in line with the roadmap. &lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
If Rico doesn't decide what's in the package, then... who does? And more importantly: how can a person who's &lt;i&gt;not&lt;/i&gt; the chief architect, decide what's included in a version? Aren't decisions about what's in a version fundamentally important for the architecture of a version? I think it is, despite the fact that everything is done as modular as possible. 
&lt;/p&gt;
&lt;p&gt;
Of course, another question arises: &lt;i&gt;why&lt;/i&gt; is the chief architect not given the right to decide what's in the version of VS.NET? Interesting team management, if you ask me. For example: if for feature group X, the system itself (the VS.NET framework) has to get a new subsystem, and X isn't included, the new subsystem is unnecessary. I wonder if Eclipse, with its relatively small team works the same way...
&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6749210" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=g4d5pJ1usQQ:TlWpeeIFYtU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=g4d5pJ1usQQ:TlWpeeIFYtU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=g4d5pJ1usQQ:TlWpeeIFYtU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=g4d5pJ1usQQ:TlWpeeIFYtU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=g4d5pJ1usQQ:TlWpeeIFYtU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/g4d5pJ1usQQ" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2008/11/21/if-the-chief-architect-doesn-t-decide-who-does.aspx</feedburner:origLink></item><item><title>Baby-sitter Framework 2.0: Change tracking in the EF v2, it's still your problem</title><link>http://feedproxy.google.com/~r/FransBouma/~3/s4Lo1B0UPjw/baby-sitter-framework-2-0-change-tracking-in-the-ef-v2-it-s-still-your-problem.aspx</link><pubDate>Fri, 21 Nov 2008 09:52:46 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6749207</guid><dc:creator>FransBouma</dc:creator><slash:comments>9</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6749207</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2008/11/21/baby-sitter-framework-2-0-change-tracking-in-the-ef-v2-it-s-still-your-problem.aspx#comments</comments><description>&lt;p&gt;
More than 1.5 year ago (!) I wrote an &lt;a href="http://weblogs.asp.net/fbouma/archive/2007/04/03/why-change-tracking-has-to-be-part-of-an-entity-object.aspx" target="_blank"&gt;article about why change tracking of changes of an entity should really be inside an entity object&lt;/a&gt;. Change tracking is the concern of the O/R mapper and the entity object, not the developer &lt;i&gt;using&lt;/i&gt; the  entity object and the O/R mapper. Imagine using an entity object a .NET application and &lt;b&gt;you&lt;/b&gt; are in charge of taking care of what changes happened inside the entity object when it was used by some routine so you can decide which routine to call: the InsertNewEntity() routine or the UpdateExistingEntity() routine. Isn't that the concern of the framework you're using? I.o.w.: why do you need to &lt;i&gt;baby-sit&lt;/i&gt; the changes of an entity and make sure these changes are propagated along the same path over which the entity travels?
&lt;/p&gt;
&lt;p&gt;
The Entity Framework (EF) v1.0 has a non-existing answer to the 'n-tier problem' or better: how to deal with changes on an entity that's not directly connected to a live context. This obviously lead to a lot of negative feedback on the EF, and Microsoft replied as much as that they would seriously look into this problem for v2.0 of the EF and would try to solve it properly. Well, yesterday, the &lt;a href="http://blogs.msdn.com/efdesign/archive/2008/11/20/n-tier-improvements-for-entity-framework.aspx" target="_blank"&gt;EF team posted a proposal of the v2.0 'solution' to this problem&lt;/a&gt;: &lt;b&gt;you&lt;/b&gt; solve it. They give you the API, and you, the framework &lt;i&gt;user&lt;/i&gt;, the person who is paid to write code &lt;i&gt;on top of&lt;/i&gt; the used frameworks, not &lt;i&gt;for&lt;/i&gt; the used frameworks, will write code to solve the change tracking problem. 
&lt;/p&gt;
&lt;p&gt;
Honestly, with their &lt;i&gt;council of wise men&lt;/i&gt; in charge of telling them what to do, who came up with this 'solution' ? With a few exceptions, in general developers aren't paid to write frameworks, they're paid to write applications for the customer: the sooner they're done, the more they can build on top of proven technology which is used by many people, the less bugs they'll create and the less problems the customer will have. If the developer is forced to invent a change tracking strategy, thus spend time on how to solve a framework-related problem, the developer will spend time on plumbing code, which will have to be designed, debugged and tested. 
&lt;/p&gt;
&lt;p&gt;
And how are all those dataset-using developers now going to be convinced the EF is the right way to go? When the DataSet has solved this problem since... oh well, the beginning? Not to mention as well as a lot of the &lt;a href="http://www.llblgen.com" target="_blank"&gt;competing O/R mapper frameworks&lt;/a&gt; out there? The core problem of all this is, I think, the mistake of designing the framework from the perspective of the framework developer: when you write a framework there are two kinds of 'correct': from the framework developer's point of view (POV) and from the framework user's POV. The core mistake is in the assumption that these two kinds of 'correct' are really the same, or worse: it's assumed that the framework developer's concept of what's 'correct' is actually what the framework &lt;i&gt;user&lt;/i&gt; wants. 
&lt;br&gt;&lt;br&gt;
That's not the case. A framework user doesn't give a **** about how many different patterns the framework is using and how great and awesome it's internally and how it will ultimately evolve in the bringer of world peace. A framework user is interested in whether the framework takes care of things the framework user &lt;i&gt;can't afford&lt;/i&gt; to spend time on. After all, the framework user can't afford to spend time paid by the customer on plumbing, on writing infrastructure code. The framework user is paid to write code directly related to the problem at hand: the application for the customer. No customer should accept that the team hired for writing the line-of-business application has spend time on writing a report-control or for example a grid control. So why should a customer accept to pay for time spend on other plumbing code? Just because the customer doesn't know any better? If so, isn't that erm... taking advantage of the inability of the customer to judge what the 'software guys' did was correct? 
&lt;/p&gt;
&lt;p&gt;
Yes, it's that extreme. The software industry should grow up and realize that it shouldn't be acceptable anymore to write frameworks and framework code, plumbing code etc. paid by the customer, just because the customer doesn't know any better. And we, the software developers, should grow up and accept that the job many of us have isn't to write plumbing code and infrastructure code, but to write code &lt;i&gt;using&lt;/i&gt; the plumbing available. If the plumbing at the place where you work is broken, it's very likely that someone will call a plumber to fix it. So why accept that if the plumbing used for a project is broken, one has to fix it themselves? With all the bugs, loss of time, focus and ultimately: money, as a result? 
&lt;/p&gt;
&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6749207" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=s4Lo1B0UPjw:_oKe1ynsClw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=s4Lo1B0UPjw:_oKe1ynsClw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=s4Lo1B0UPjw:_oKe1ynsClw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=s4Lo1B0UPjw:_oKe1ynsClw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=s4Lo1B0UPjw:_oKe1ynsClw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/s4Lo1B0UPjw" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2008/11/21/baby-sitter-framework-2-0-change-tracking-in-the-ef-v2-it-s-still-your-problem.aspx</feedburner:origLink></item><item><title>Designing a language is hard, and M won't change that</title><link>http://feedproxy.google.com/~r/FransBouma/~3/j4YSDspRlzU/designing-a-language-is-hard-and-m-won-t-change-that.aspx</link><pubDate>Wed, 05 Nov 2008 11:36:28 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6721490</guid><dc:creator>FransBouma</dc:creator><slash:comments>13</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6721490</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2008/11/05/designing-a-language-is-hard-and-m-won-t-change-that.aspx#comments</comments><description>&lt;p&gt;
I was a bit surprised about the large scale of the positive hype around 'M' in Oslo. Fortunately, &lt;a href="http://rogeralsing.com" target="_blank"&gt;Roger Alsing&lt;/a&gt; wrote a &lt;a href="http://rogeralsing.com/2008/11/04/i-call-bs-on-the-oslo-m-language/" target="_blank"&gt;'Back to reality' post about M&lt;/a&gt; which stood out as a single critical remark against the sea of positivism. I like it when someone chooses to be the more sceptical voice in the crowd: this way an outsider gets a better chance to see the whole picture instead of just one side. This post is written in that light, to give my two cents in line with what Roger said and to give some more background in what I think he meant. 
&lt;br&gt;&lt;br&gt;
What's the idea of 'M', the codename for the textual language in Oslo? It's supposed to make it easy to write DSLs. A DSL is a '&lt;a href="http://en.wikipedia.org/wiki/Domain_Specific_Language" target="_blank"&gt;Domain Specific Language&lt;/a&gt;', which in short is a name for a language (in any shape or form!) to express behavior, data structures, data and what have you, for a &lt;i&gt;specific&lt;/i&gt;, narrow, well defined domain. So if you want your application to have a custom set of rules, definable by the user, a DSL might be a good mechanism to formulate these rules in. Make no mistake about what a DSL is though: a grid, form, text in a textfile, can be a representation of a DSL. It's a concept, not a physical toolkit. 
&lt;/p&gt;
&lt;p&gt;
Everyone who has ever written a parser for a grammar, defined a grammar for a language or designed a language, has probably read or heard about the 'Dragon book', or more officially: &lt;a href="http://www.amazon.com/Compilers-Principles-Techniques-Alfred-Aho/dp/0201100886" target="_blank"&gt;Compilers: Principles, Techniques, and Tools, by Aho, Sethi and Ullman&lt;/a&gt;. In that book, it's explained in all detail what's needed to define a language, to recognize elements in texts containing elements defined in the grammar of the language, parse it and do something with that parse result. It's not a book for the hobby programmer, and for a reason: computer languages, and thus also DSLs, are complex beasts to handle. The domain of computer languages has been studied a lot in the past decades and it's one of the few fields in Computer Science which can be considered a bit more mature than the rest: today, the aspects of computer languages, grammars, lexers, parsers and friends are well understood and documented in many papers and books.
&lt;/p&gt;
&lt;p&gt;
One of the nice things of a relatively mature field is that the techniques to work with the material are fairly mature as well. This means that if you want to define a grammar, look for a way to understand texts defined in that grammar, the solutions are available to you in mature formats, with tooling which has proven its value for many years. The question that arises often is of course: with all this tooling and knowledge, is it possible for a less educated / hobby programmer (or a non-programmer) to define a language for a given domain so the domain's complexity is easier to handle? (because that's the main purpose of DSLs). The answer is sadly: no, it's not. As the M toolset is too a toolset for producing a parser and do something with the input, it too doesn't make things easier. I'll explain why below.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;The L(AL)R(k) vs. LL(k) difference&lt;/b&gt;&lt;br&gt;
If you already wonder what &lt;a href="http://en.wikipedia.org/wiki/LALR_parser" target="_blank"&gt;LALR&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/LR_parser" target="_blank"&gt;LR&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/LL_parser" target="_blank"&gt;LL&lt;/a&gt; stand for, I've proven my point. I've linked them to the Wikipedia articles, so if you're not familiar with the terms you can read up and follow the rest of the argument. LALR and LR are so called 'Rightmost derivation' parsers, which can be seen as 'bottom up': it uses a stack and a state machine to recognize &lt;a href="http://en.wikipedia.org/wiki/Nonterminal" target="_blank"&gt;Non-Terminals&lt;/a&gt; in the input so it can in the end, understand the complete input. 
&lt;br&gt;&lt;br&gt;
When an LR parser understands it has seen a Non-Terminal N, it will replace the elements in the input stream (Terminals and / or Non-Terminals) with the Non-Terminal it just recognized. This is called 'Reduce', and it's typical an event which is used to trigger handler code outside the parser, e.g. to build up the &lt;a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_blank"&gt;Abstract Syntax Tree (AST)&lt;/a&gt;. This process continues till it has reduced the whole input stream to a single Non-Terminal, the start symbol. As the Wikipedia article describes, writing a parser for LR(k) grammars by hand is hard, as you have to produce tables with data for the parser engine which is a state machine. A generator can help there. A good example of such a generator is the &lt;a href="http://www.devincook.com/goldparser/" target="_blank"&gt;Gold Parser&lt;/a&gt; or YACC. The Gold Parser comes with a visual toolkit which allows you to test and debug your grammars. 
&lt;br&gt;&lt;br&gt;
The main problem with LALR/LR languages is that grammars can lead to conflicts, in the form of reduce/reduce conflicts or shift/reduce conflicts or even shift/shift conflicts. The conflicts all arise inside the parser's state machine where it is in state S and the path to get there with the current input decides which state will follow. Reduce/reduce conflicts occur when the parser sees an input element E and on the stack are a group of elements which together with E form a match for two (or even more!) Non-Terminals: it can't decide, based on E and the stack contents, which Non-Terminal should replace the set of elements on the stack + E. A shift/reduce conflict arises when the parser sees an element E and it has to decide whether replace the set of elements on the stack + E with Non-Terminal N1, or push E onto the stack (shift) to try to form the required elements for Non-Terminal N2. Shift/shift conflicts occur when the parser can't decide for which Non-Terminal to push onto the stack (shift) the input element E. 
&lt;br&gt;&lt;br&gt;
These conflicts should be resolved to have a proper language which doesn't contain a bug by itself. It's sometimes sufficient to pick one over the other (e.g. shift instead of reduce in a shift/reduce conflict) but it's in general not adviced to do so. Add to that that as soon as a language is ambiguistic, (like C# and VB.NET are for example), it's harder to solve these conflicts: the parser has to 'look ahead' to see what's coming to decide what to do. LALR parsers therefore are less suffering from these conflicts, yet it's something one has to deal with in a lot of cases. Though to be able to solve these conflicts, one has to understand how the parsing process works. 
&lt;/p&gt;
&lt;p&gt;
There's another type of parser, the LL(k) parser. An LL(k) parser is a Leftmost derivation parser, which means that it's a top-down parser. It doesn't use shift/reduce tables and a stack, instead it simply looks at the input and calls a handler for the Non-Terminal the input symbol is the start symbol of and leaves the handling to that handler. So instead of waiting for the parser to see the complete 'If' expression for the 'If' Non-Terminal to reduce it and call the handler for the 'If' Non-Terminal, it calls the 'If' Non-Terminal handler after it sees a Terminal 'if' and expects the If Non-Terminal handler to take care of it. LL(k) parsers can be seen as state machines similar to LR/LALR parsers, yet the state machine is less visible: it's inside the handler code. 
&lt;br&gt;&lt;br&gt;
As the handling of a Non-Terminal is done in a process you have every control over, as you're there along the way, it's much easier to handle errors: if you expect a ')' and it's not there, you can report the error and act as if you've seen that bracket and move on, to handle more errors (or to even ignore the error, if the language has to be very flexible). An LR/LALR parser can't do that easily because it simply has to give up: it sees an element E which combined with the stack contents can't be used to either shift or reduce. This makes LL(k) easier to handle ambiguistic languages and parse along when errors occur. Of course generators for LL(k) are available as well, a good example is the widely known &lt;a href="http://www.antlr.org/" target="_blank"&gt;ANTLR&lt;/a&gt;, which despite its name might suggest is an LL(k) toolkit. 
&lt;/p&gt;
&lt;p&gt;
One core difference between LL(k) and LALR/LR is that code to build the AST is &lt;i&gt;inside&lt;/i&gt; the grammar for LL(k) and &lt;i&gt;outside&lt;/i&gt; the grammar for LALR/LR(k). This is logical, because LL(k) is handled with custom handlers for the grammar's Non-Terminals, so the code which handles Non-Terminal N is custom made for N, containing the code to build the AST node for N along the way (of course using re-usable classes/methods, but the structure of the handler is unique for that Non-Terminal). To be able to do that, the custom code is specified inside the grammar which is fed to the generator which produces a proper parser for the grammar, including the custom code. For LALR/LR grammars, the code can be outside the grammar because the generator doesn't generate any code, it generates data, which is the input for the state machine to make sure the parser knows what to do when a given input is seen. 
&lt;/p&gt;
&lt;p&gt;
My experience with both LALR/LR and LL is that with LL, it's easier to write a grammar but harder to produce custom code for the final parser: it's very hard to debug code which is inside a grammar which is used to generate a parser which task it is to build an AST from the input which in turn is used to &lt;i&gt;do&lt;/i&gt; something with the input. For LALR/LR it's hard(er) to get the grammar right, harder to get good error recovery, but writing the handling code to build the AST is relatively easy: you just fill in the blanks for every Non-Terminal in your grammar. I know that in one of the Oslo presentations, it was shown that the language could be debugged. The ANTLR tools can do that too (for Java), though does what the M tools can do, make things less complex than the complexitiy level of the ANTLR tools? One still has to know what's on the screen, what everything means and what's handled by what at what moment.
&lt;/p&gt;
&lt;p&gt;
So when I look at M's elements, I can only conclude that it too has the same aspects as the well known tooling and building blocks for parsers, grammars and the like available to everyone today: it's complex. With 'complex' I mean: you need proper knowledge about computer languages, parsers and grammars to understand what's going on and how to use the tools available properly. There's &lt;i&gt;nothing wrong&lt;/i&gt; with that: if something is hard, well... that's life, deal with it by understanding the concepts which makes a hard problem manageable. Though to me it's impossible that all crucial aspects of writing computer languages are suddenly not important anymore with M's elements on the table. Sure, people will write DSLs with M's elements, but today you can do that too with ANTLR or Gold Parser, use a visual toolkit to design, test and debug the language, and you're likely up and running in a day or two. That doesn't mean a person who has no clue what LL(k) means, what an AST is, can create a language for a given domain with ANTLR, some knowledge about parsers, grammars etc. is required. And with M's elements, this isn't any different at all. 
&lt;br&gt;&lt;br&gt;
That's not bad, not at all. It's however to me a different reality than the picture Microsoft tried to paint with the Oslo material provided through the PDC, and therefore I fully agree with what Roger said in his blogpost. 
&lt;/p&gt;
&lt;p&gt;
The core issue is that to be able to write a succesful DSL, you have to be able to &lt;i&gt;create&lt;/i&gt; a grammar, within the restrictions of the system in which you have to specify the grammar. With the restrictions, rules and aspects of the various parsing techniques as the guideline of what you can do inside the grammar, it's still very hard to define a grammar for a DSL, because not only has the DSL to be expressive enough and compact enough, it also has to work on &lt;i&gt;all valid&lt;/i&gt; input and be able to produce a proper result in the form expected. If you want to experience how complex this is, try to write a very simple business rule grammar, in &lt;a href="http://en.wikipedia.org/wiki/EBNF" target="_blank"&gt;EBNF&lt;/a&gt;, which for example allows you to specify validation rules for objects. The difficulty is for example in 'all valid input'. What's valid input for your language? How do you determine that? You do that by defining rules, which will eventually become your grammar. An initial start is probably easy, though it gets out of hand pretty quickly if you want to add another couple of Non-Terminals, or want to re-use a Terminal inside multiple Non-Terminals, which might all of a sudden lead to an ambiguistic language and thus either lead to conflicts or more complex code in your handlers. 
&lt;/p&gt;
&lt;p&gt;
I appreciate Microsoft for making the effort in this direction, and future will tell what the M toolbox will become. I truly hope it can meet the expectations of many people around, though I seriously doubt it will be a set of tools used by what looks like one of the big parts of the target audience: the group of people who lack the knowledge of grammars, parsers, languages and the like, as to me it doesn't lower the bar of complexity one bit. While that's not something to worry about in general, it is an aspect we have to be careful about: there's already enough complexity in our field: we need elements to make things more understandable, to make complexity more manageable, not to muddy the waters as if it's all of a sudden easy as tic-tac-toe to write a grammar, language, parser and AST interpreter code and every non-programmer can create DSLs. 
&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6721490" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=j4YSDspRlzU:2CgUsEcs6ic:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=j4YSDspRlzU:2CgUsEcs6ic:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=j4YSDspRlzU:2CgUsEcs6ic:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=j4YSDspRlzU:2CgUsEcs6ic:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=j4YSDspRlzU:2CgUsEcs6ic:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/j4YSDspRlzU" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2008/11/05/designing-a-language-is-hard-and-m-won-t-change-that.aspx</feedburner:origLink></item><item><title>from el in world.ExtensionMethodsLibraries group el by el.Method into g select g;</title><link>http://feedproxy.google.com/~r/FransBouma/~3/i7YMK9O_rHU/from-el-in-world-extensionmethodslibraries-group-el-by-el-method-into-g-select-g.aspx</link><pubDate>Wed, 22 Oct 2008 10:27:48 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6697680</guid><dc:creator>FransBouma</dc:creator><slash:comments>24</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=6697680</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2008/10/22/from-el-in-world-extensionmethodslibraries-group-el-by-el-method-into-g-select-g.aspx#comments</comments><description>&lt;p&gt;
Everyone who's doing .NET 3.5 development these days will likely run into the same problem I ran into this morning: your set of extension methods grows beyond the level of a single file and you need to group them into separate sets of files or worse: you discover you have several distinct projects which all have extension methods and it's better to group them into a single library. 
&lt;/p&gt;
&lt;p&gt;
So I started VS.NET 2008 and began with a new solution and a new class library project. Right at the spot when I was thinking how to name the darn thing (you must know I'm very good at cooking up catchy names &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileywink.gif" border="0"&gt;), I realized it might perhaps be possible that someone else has had that same idea and already started such a library. It would be useless to have two extension method libraries for the BCL, so I went to &lt;a href="http://www.codeplex.com" target="_blank"&gt;CodePlex&lt;/a&gt; and searched for &lt;a href="http://www.codeplex.com/Project/ProjectDirectory.aspx?ProjectSearchText=Extension%20Methods" target="_blank"&gt;&lt;i&gt;Extension Methods&lt;/i&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
The query returned &lt;b&gt;56&lt;/b&gt; projects &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileyshocked.gif" border="0"&gt;! Not all of them BCL extension methods, but all of them more or less libraries with extension methods. That's simply too much, people. The fragmentation shows: most of them are hardly used, downloaded perhaps 50-100 times. This is a bit sad, because some contain valuable extension methods, though to find these is a bit of a struggle: they're often buried in piles of useless filler methods or rewrites of existing extension methods. Besides that, it's still not that convenient to have to reference a group of libraries to have them all at your disposal. 
&lt;/p&gt;
&lt;p&gt;
For our own code, it's best if we have all BCL related extension methods into a single library so we have to reference just a single class library and I think that's true for most of you out there. Still, some of my extension methods aren't in any of the libs out there, though I'm undecided to which library to give them to and use that one: I don't want to base our code on a library which is perhaps already dead, and I definitely don't want to use a library which has a lot of code which is really redundant (e.g. it's already in the BCL) or silly or very project (but not my project) specific. 
&lt;/p&gt;
&lt;p&gt;
It's tempting to just dump the code on codeplex and be done with it, though in general that's not going to bring the .NET community forward: more fragmentation is not going to lead to more usage of the libraries already out there. However, not doing anything isn't good either: I'm sure a lot of developers out there have written the same RaiseEvent extension methods as I have done and have perhaps a few handy helpers which could be a valuable tool in everyone's toolbox, like the better DataRow.Field&amp;lt;T&amp;gt;(name) I wrote this morning so I don't get cast exceptions anymore. Having these methods grouped into a &lt;i&gt;single&lt;/i&gt; library which is open source and free (i.e. uses a flexible license so no GPL-ed stuff) is what the community needs, if we all don't want to drown in extension method libraries.
&lt;/p&gt;
&lt;p&gt;
Anyone out there who has thought about this already and has a solution for this? If so, please post in the comments below. In the meantime I'll group my extension methods in a separate lib so if nothing comes out of this, it will be project 57 &lt;img src="http://www.xs4all.nl/~perseus/smileys/smileywink.gif" border="0"&gt;.
&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6697680" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=i7YMK9O_rHU:dJj4V40_afA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=i7YMK9O_rHU:dJj4V40_afA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=i7YMK9O_rHU:dJj4V40_afA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=i7YMK9O_rHU:dJj4V40_afA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=i7YMK9O_rHU:dJj4V40_afA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/i7YMK9O_rHU" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Community+News/default.aspx">Community News</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2008/10/22/from-el-in-world-extensionmethodslibraries-group-el-by-el-method-into-g-select-g.aspx</feedburner:origLink></item></channel></rss>
