<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;DUMBRXs9fip7ImA9WxBWE0o.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981</id><updated>2010-02-05T14:44:14.566+01:00</updated><title>Coding Instinct</title><subtitle type="html">creating maintainable software using .NET (trying at least...)</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>79</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/codinginstinct" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="codinginstinct" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;D0IARHw-eip7ImA9WxNUEUk.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-3988605960613390732</id><published>2009-11-01T20:37:00.001+01:00</published><updated>2009-11-02T08:05:45.252+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-02T08:05:45.252+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NHibernate" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>NHibernate feature: SaveOrUpdateCopy &amp; Merge</title><content type="html">&lt;p&gt;One of NHiberantes features that I haven’t seen mentioned in the documentation or in blogs concerns the the two methods on &lt;em&gt;&lt;strong&gt;ISession&lt;/strong&gt; SaveOrUpdateCopy &lt;/em&gt;and &lt;em&gt;Merge. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Lets say we have an backend (i.e. application server) that has an operation called UpdateOrder. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/Su3jiL8IVmI/AAAAAAAAAso/g86OWRAfmpc/s1600-h/image%5B8%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="355" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/Su3jiazX__I/AAAAAAAAAss/Bawx917JSUY/image_thumb%5B6%5D.png?imgmax=800" width="460" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The UpdateOrder message contains a complete order. The normal scenario here is that the backend translate the order contained in the message to a domain model that is then persisted to the database via NHibernate. The problem with an update scenario like this is that the order that is coming in from the client could have missing order lines. If you use the normal ISession SaveOrUpdate method the order line that was removed on the client and therefore missing in the UpdateOrder message will not be deleted in the database. &lt;/p&gt;  &lt;p&gt;Why won’t the missing order line be deleted from the db? Well consider this normal update scenario:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_TU8pT7DhyWk/Su3ji9SjqxI/AAAAAAAAAsw/aCrFhbmRO7A/s1600-h/image%5B15%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="201" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/Su3jjALShGI/AAAAAAAAAs0/WSNVyCqUF9s/image_thumb%5B11%5D.png?imgmax=800" width="384" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here the order line is removed on the instance that is already attached to an open NHiberante session. In this case &lt;em&gt;SaveOrUpdate &lt;/em&gt;will work perfectly because NHiberante can track the removal of the order line. &lt;/p&gt;  &lt;p&gt;Consider this case (that represents the client –&amp;gt; backend scenario I mentioned above)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/Su3jjUiCplI/AAAAAAAAAs4/Yntz-L95ZRk/s1600-h/image%5B25%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="174" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/Su3jjlTEUuI/AAAAAAAAAs8/ZFflMbDEgZA/image_thumb%5B17%5D.png?imgmax=800" width="413" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Here we try to save a detached instance which means that NHibernate’s dirty tracking and tracking of collection removals will not work. &lt;/p&gt;  &lt;p&gt;How do you solve this problem? One approach is to fetch the order from the db and do a manual merge of the changes.&amp;#160; The current system that I am working on has a data access layer that is using LinqToSql and there are many, many update scenarios as described above. The amount of code to manually merge and figure out what has happened with all relations (added / removed order lines for example) is quite substantial. &lt;/p&gt;  &lt;p&gt;For the last month we have been bit by bit migrating the data access layer to NHibernate. First I thought that this issue of updating detached objects would be a problem that we still needed to solve manually but then I discovered &lt;em&gt;SaveOrUpdateCopy&lt;/em&gt; and &lt;em&gt;Merge&lt;/em&gt;. These two functions does exactly what the old DAL did manually, that is before the update it fetches the persisted object from the db and then merges all changes from the detached instance into the persisted instance automatically, including orphaned child deletions!&lt;/p&gt;  &lt;p&gt;Ex:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/Su3jjyVccWI/AAAAAAAAAtA/rqrJPiCSdJc/s1600-h/image%5B35%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="196" alt="image" src="http://lh3.ggpht.com/_TU8pT7DhyWk/Su3jkcOkEjI/AAAAAAAAAtE/Fe_VBIJ7bTc/image_thumb%5B23%5D.png?imgmax=800" width="363" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the above code I modify an order line and remove another. Both operations are on a detached object. Then using SaveOrUpdateCopy we get this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/Su3jksY2nFI/AAAAAAAAAtI/JMhaa1AYK8I/s1600-h/image%5B30%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="171" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/Su3jk-i9D6I/AAAAAAAAAtM/JbFENXzUixs/image_thumb%5B20%5D.png?imgmax=800" width="616" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;NHibernate fetches the order (in one statement by joining in the order lines), then performs the merge, figures out that one order line is updated and one is removed and issues the correct database calls. Is it just me but isn’t this great??? This will literally save thousands of lines of code!&amp;#160; &lt;/p&gt;  &lt;p&gt;The &lt;em&gt;ISession.Merge&lt;/em&gt; function basically does the same (from what I can tell). I am not sure really what separates them, except that there is cascade option named “merge” that you can set on relations to control how cascades should be propagated during merge operations. &lt;/p&gt;  &lt;p&gt;Here is the API doc for Merge:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;Copy the state of the given object onto the persistent object with the same        &lt;br /&gt;identifier. If there is no persistent instance currently associated with         &lt;br /&gt;the session, it will be loaded. Return the persistent instance. If the         &lt;br /&gt;given instance is unsaved, save a copy of and return it as a newly persistent         &lt;br /&gt;instance. The given instance does not become associated with the session.         &lt;br /&gt;This operation cascades to associated instances if the association is mapped         &lt;br /&gt;with cascade=&amp;quot;merge&amp;quot;. The semantics of this method are defined by JSR-220.&lt;/em&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I think SaveOrUpdateCopy is something that has exited in NHiberante for all time and Merge is something added in 2.1 (clearly something ported from the hibernate). Anyway I am very glad that NHibernate has this ability because writing and handling the merge operation manually is very boring code to write!&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-3988605960613390732?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=HwEAcHVdhA8:yL2eWd4saZw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=HwEAcHVdhA8:yL2eWd4saZw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=HwEAcHVdhA8:yL2eWd4saZw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/3988605960613390732/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=3988605960613390732" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3988605960613390732?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3988605960613390732?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/11/nhibernate-feature-saveorupdatecopy.html" title="NHibernate feature: SaveOrUpdateCopy &amp;amp; Merge" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;A0EEQ308fSp7ImA9WxNVF0g.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-3917083988347975322</id><published>2009-10-28T20:53:00.001+01:00</published><updated>2009-10-28T20:53:22.375+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-28T20:53:22.375+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>WPF and databinding to dynamic properties</title><content type="html">&lt;p&gt;One useful feature in WPF 4.0 is the ability to databind to dynamic (runtime generated) properties using the &lt;strong&gt;&lt;em&gt;DynamicObject&lt;/em&gt;&lt;/strong&gt; as a base class or implementing the &lt;strong&gt;&lt;em&gt;IDynamicMetaObjectProvider &lt;/em&gt;&lt;/strong&gt;interface. I am currently working on a WPF application and this ability to bind to runtime generated properties would have been very useful in a previous story we implemented two weeks ago. &lt;/p&gt;  &lt;p&gt;The story concerned merging two object graphs and then visualizing what properties that were changed/conflicted in the UI (for example with a different color). &lt;/p&gt;  &lt;p&gt;In order to not add “XXX_HasMergeChange” for every property in the presentation model we solved this by using a value converter and some WPF binding magic that some might call a HACK. The solution was only partial as it only worked in the Grid and not on everything else. &lt;/p&gt;  &lt;p&gt;If we had WPF 4.0 we could have solved this like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_TU8pT7DhyWk/SuihLBaP_gI/AAAAAAAAAsY/uL2yH8u4Jho/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/SuihLUqrYbI/AAAAAAAAAsc/UZ-yj2_bgwE/image_thumb%5B5%5D.png?imgmax=800" width="633" height="203" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the above style trigger the data trigger is binding to a property that doesn’t exist on the presentation model. How does WPF then get the value for this property? By calling the TryGetMember method:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_TU8pT7DhyWk/SuihL28njJI/AAAAAAAAAsg/bfW5Sdk_rKA/s1600-h/image%5B14%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SuihMRxwnbI/AAAAAAAAAsk/yJm9Mnm48NY/image_thumb%5B8%5D.png?imgmax=800" width="693" height="337" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;WPF will call the TryGetMember and that will check if the property ends with “_HasMergeChange”, if that is the case it will try to look up the property in the MergeChanges dictionary. &lt;/p&gt;  &lt;p&gt;The above is just a simple proof of concept, if I would go forward with this I would have to figure out a more generic way to define the style and data trigger to be able to reuse the xaml style markup for example, but that shouldn’t be a big problem. I also tested property change notifications using the &lt;strong&gt;&lt;em&gt;INotifyPropertyChanged&lt;/em&gt;&lt;/strong&gt; interface and they work for dynamic properties as well. &lt;/p&gt;  &lt;p&gt;To learn more about the new features in WPF 4.0 read ScottGu’s &lt;a href="http://weblogs.asp.net/scottgu/archive/2009/10/26/wpf-4-vs-2010-and-net-4-0-series.aspx"&gt;recent post&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-3917083988347975322?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=EtGXD78NJ7k:7zox7eXemBI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=EtGXD78NJ7k:7zox7eXemBI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=EtGXD78NJ7k:7zox7eXemBI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/3917083988347975322/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=3917083988347975322" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3917083988347975322?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3917083988347975322?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/10/wpf-and-databinding-to-dynamic.html" title="WPF and databinding to dynamic properties" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUcCQXc5eCp7ImA9WxNQGE8.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-2874770108751652513</id><published>2009-09-24T22:08:00.001+02:00</published><updated>2009-09-24T22:11:00.920+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-24T22:11:00.920+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>A Bug in Except?</title><content type="html">&lt;p&gt;Among the Linq extensions methods that came with .NET 3.5 is one called &lt;em&gt;Except. &lt;/em&gt;This method takes two lists (first and second)&lt;/p&gt;  &lt;p&gt;The MSDN docs say:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;This method returns those elements in first that do not appear in second. It does not also return those elements in second that do not appear in first.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This appears to be a lie. Review the code below and guess the output:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_TU8pT7DhyWk/SrvRrgPK84I/AAAAAAAAAsI/ouSbFg0FoSo/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/SrvRsrVrPdI/AAAAAAAAAsM/oSJfAzSZr_o/image_thumb%5B4%5D.png?imgmax=800" width="384" height="650" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;   &lt;p&gt;The &lt;em&gt;User&lt;/em&gt; object has overridden the &lt;em&gt;Equals&lt;/em&gt; and &lt;em&gt;GetHashCode&lt;/em&gt; methods which the &lt;em&gt;Except&lt;/em&gt; method use to determine equality. Since there is only one object in list2 that is also “equal” to an object in list1 I would expect (granted the MSDN docs are correct) that list3 would contain three users with the id zero. &lt;/p&gt;    &lt;p&gt;The actual result? list3 will only contain ONE user object (with id zero). When I debug I see that Equals is called to compare objects in list1 with each other. &lt;/p&gt;    &lt;p&gt;Using reflector I can see why, &lt;em&gt;Except&lt;/em&gt; is implemented using the internal class &lt;em&gt;System.Linq.Set:&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/SrvRs2RShtI/AAAAAAAAAsQ/IibRVdOoOeQ/s1600-h/image%5B17%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_TU8pT7DhyWk/SrvRtGwj7eI/AAAAAAAAAsU/bH22QkAUOO4/image_thumb%5B9%5D.png?imgmax=800" width="470" height="254" /&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;It starts by adding all items from list2 into the set class then for each item from list1 that &lt;u&gt;&lt;strong&gt;can&lt;/strong&gt;&lt;/u&gt; be added to the set it yield returns. This filters all items from list1 that are equal to an item in list2 BUT it &lt;u&gt;&lt;strong&gt;also&lt;/strong&gt;&lt;/u&gt; filters all items in list1 that are equal any other item in list1! &lt;/p&gt;    &lt;p&gt;Maybe not such a common usage scenario, and I don’t recommend overriding &lt;em&gt;Equals&lt;/em&gt; and &lt;em&gt;GetHashCode&lt;/em&gt; in this manner. Anyway frustrated by this because I burnt an hour on debugging before figured out it that what was to blame.&amp;#160; &lt;/p&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-2874770108751652513?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=bELpmSsLNug:r4bqHr-f6TA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=bELpmSsLNug:r4bqHr-f6TA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=bELpmSsLNug:r4bqHr-f6TA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/2874770108751652513/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=2874770108751652513" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2874770108751652513?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2874770108751652513?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/09/bug-in-except.html" title="A Bug in Except?" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;DkMCRHkzfyp7ImA9WxNSEkU.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-6273369386065350584</id><published>2009-08-26T12:55:00.001+02:00</published><updated>2009-08-26T13:01:05.787+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-26T13:01:05.787+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NHibernate" /><title>Profiling NHibernate Batching</title><content type="html">&lt;p&gt;NHibernate has pretty good support for batching, something that can significantly increase performance when inserting or updating large number of objects. &lt;/p&gt;  &lt;p&gt;Example: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SpUUe1RJbEI/AAAAAAAAArw/RdzH4cgkQi8/s1600-h/nh_batching%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="nh_batching" border="0" alt="nh_batching" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SpUUfRz7a0I/AAAAAAAAAr0/2_rlHxcNfZQ/nh_batching_thumb%5B3%5D.jpg?imgmax=800" width="400" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In the above example you can see that the order lines are created in one statement. In a recent mail conversation with &lt;a href="http://blog.lowendahl.net/"&gt;Patrik Löwendahl&lt;/a&gt; he asked for assistance in getting batching to work. The first thing to check is what id generator you are using, you cannot use native (sql identity) id generator and expect batching to work for inserts. The reason for this that for identity inserts NHibernate issues a &amp;quot;select SCOPE_IDENTITY()&amp;quot; statement after each insert statement to fetch the generated ID. If you want to use batching for inserts you need to use the guid or hilo id generator. &lt;/p&gt;  &lt;p&gt;Another issue i came across was that batching does not work as you would hope for associations. For example if you want to save a thousands orders and each order has five order lines, this would result in six thousands calls if batching was disabled and two thousands calls with batching enabled. As you see in the screenshot above, batching is only done on the order lines and not for everything. &lt;/p&gt;  &lt;p&gt;You can optimize further by using the stateless session. However inserting entities using nhibernate’s stateless session ignores associations. But by looping through all orders and calling session.Insert(order), and then doing a nested loop to do the same for all order lines you can insert all orders and order lines in just two calls to the database. &lt;/p&gt;  &lt;p&gt;The problem Patrik had was very weird and confusing. To verify that batching was actually happening he used SQL Profiler, while I used NHProfiler. The weird thing is that they show a very different picture. NHProfiler shows order lines as being issued in one command while SQL Profiler shows them as separate RPC calls.&lt;/p&gt; +   &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SpUUgOQ05sI/AAAAAAAAAr4/dmLqt0YowUg/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SpUUghUy__I/AAAAAAAAAr8/hfMmFu_dI5w/image_thumb%5B3%5D.png?imgmax=800" width="535" height="159" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This result left me very confused. The NHProfiler result clearly indicates that batching is being used but SQL Profiler shows the same results as when batching is off. However when batching is enabled the performance is significantly better, what is going on here?? After some Googling on SQL Profiler and batching I found this comment on &lt;a href="http://stackoverflow.com/questions/970473/batch-sql-inserts-in-net"&gt;stackoverflow&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;On MS SQL Server, SQL Profiler shows each insert statement seems to be on it's own. After reviewing your comment, I viewed a TCP Dump of the conversation and do see that it is batching multiple commands together. SQL Profiler shows each insert as a &amp;quot;RPC Completed&amp;quot; event which was confusing me. Thanks for your help. &lt;/blockquote&gt;  &lt;p&gt;I appears that batching &lt;em&gt;IS&lt;/em&gt; being done but not like I thought it would be (for example a Batch Starting command in SQL Profiler). The difference, when batching is turned on, is that all the statements are sent to the database in one go without waiting to listen for a response. That explains the SQL Profiler result, however I still find the NHProfiler result puzzling as it indicates that the order lines are created using a single call to sp_executesql.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/SpUUhFyfF7I/AAAAAAAAAsA/u9002S5y7sg/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_TU8pT7DhyWk/SpUUhkF3iLI/AAAAAAAAAsE/SJiEG4ujr3g/image_thumb%5B5%5D.png?imgmax=800" width="240" height="158" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Ayende care to explain? :) &lt;/p&gt;  &lt;p&gt;Some links on NHibernate batching:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://davybrion.com/blog/2008/10/bulk-data-operations-with-nhibernates-stateless-sessions/"&gt;Bulk Data Operations With NHibernate’s Stateless Sessions&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://ayende.com/Blog/archive/2009/08/22/nhibernate-perf-tricks.aspx"&gt;NHibernate Perf Tricks&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-6273369386065350584?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=m0corQGcBrw:42rQBZv0C48:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=m0corQGcBrw:42rQBZv0C48:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=m0corQGcBrw:42rQBZv0C48:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/6273369386065350584/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=6273369386065350584" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/6273369386065350584?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/6273369386065350584?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/08/profiling-nhibernate-batching.html" title="Profiling NHibernate Batching" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;A0AAQnszeSp7ImA9WxJbEUg.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-2004820729618830271</id><published>2009-07-21T09:02:00.001+02:00</published><updated>2009-07-21T09:02:23.581+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-21T09:02:23.581+02:00</app:edited><title>NHibernate 2.1 Released</title><content type="html">&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_TU8pT7DhyWk/SmVn_cdM0rI/AAAAAAAAAro/75iVfcjgesM/s1600-h/image%5B10%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SmVn_lvO4uI/AAAAAAAAArs/rw_t6UB5lUo/image_thumb%5B6%5D.png?imgmax=800" width="300" height="112" /&gt;&lt;/a&gt; There is a new release of NHibernate available, &lt;a href="http://sourceforge.net/projects/nhibernate/files/"&gt;download it now&lt;/a&gt;. It contains a host of great new features, like support for Dependency Injection for entities using an inversion of control container of your choosing. There is also a new ANTLR based HQL parser that has allowed for some HQL improvements, like the &lt;a href="http://nhforge.org/blogs/nhibernate/archive/2009/05/17/nhibernate-2-1-0-hql-with-clause.aspx"&gt;with clause&lt;/a&gt;.&amp;#160; The new ANTLR based HQL parser is also central to the forthcoming LINQ support and is the result of some great work by&amp;#160; &lt;a href="http://blogs.imeta.co.uk/sstrong/Default.aspx"&gt;Steve Strong&lt;/a&gt; and &lt;a href="http://fabiomaulo.blogspot.com/"&gt;Fabio&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;This release also includes the long sought after support for &lt;a href="http://ayende.com/Blog/archive/2009/05/28/nhibernate-ndash-executable-dml.aspx"&gt;executable bulk queries&lt;/a&gt;. This is a feature that the java (Hibernate) version has had for some time and is now fully ported to NHibernate. &lt;/p&gt;  &lt;p&gt;For a complete list of new features: &lt;a href="http://zvolkov.com/blog/post/2009/07/20/Whats-new-in-NHibernate-21.aspx"&gt;link&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-2004820729618830271?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=BpBOmuJXr8Y:y5FrAqN490c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=BpBOmuJXr8Y:y5FrAqN490c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=BpBOmuJXr8Y:y5FrAqN490c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/2004820729618830271/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=2004820729618830271" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2004820729618830271?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2004820729618830271?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/07/nhibernate-21-released.html" title="NHibernate 2.1 Released" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;Dk8NR348fip7ImA9WxJREkQ.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-3989050977810047181</id><published>2009-05-14T11:54:00.001+02:00</published><updated>2009-05-14T11:54:56.076+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-14T11:54:56.076+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Presentations" /><title>Presentation &amp; Code Demo Tips</title><content type="html">&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/SgvqbarQnZI/AAAAAAAAArg/BP8Mp9i214A/s1600-h/image%5B5%5D.png"&gt;&lt;img title="image" style="border-right: 0px; padding-right: 5px; border-top: 0px; display: inline; padding-left: 5px; padding-bottom: 5px; margin-left: 0px; border-left: 0px; margin-right: 0px; padding-top: 5px; border-bottom: 0px" height="206" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/Sgvqb7InmcI/AAAAAAAAArk/9RhLnVjZPIQ/image_thumb%5B3%5D.png?imgmax=800" width="300" align="right" border="0" /&gt;&lt;/a&gt; I have been doing more and more talks lately. I am not a natural speaker I usually need to practice a few times before in order to talk more fluently. But practice has made me more comfortable with it and I feel that I am getting better at it. Two days ago I held a long (3.5 hour) talk on ASP.NET MVC which was both my longest talk and my most successful, at least considering the positive response a got, which was very encouraging. &lt;/p&gt;  &lt;p&gt;The talk was mostly a long code demo. One thing that can often kill code demos are that they can slow down the tempo of a presentation when there is too much typing of unimportant text/code. Like creating a new class, constructor, etc and then later getting to the really important part of a particular function. &lt;/p&gt;  &lt;p&gt;In this MVC code demo I tried to have as much prepared as possible. I started with a standard MVC template project, but had hidden (excluded from the project) controllers and views which I included as the code demo progressed. These controllers/views included some existing functionality which I then expanded upon. That way I did not need to type class definitions defining simple controller actions and views before getting to the interesting bits. &lt;/p&gt;  &lt;p&gt;I did the same with many other parts of the presentation, for example when explaining how to unit test controller actions I already had an almost empty test method already written, and only needed to show how to unit test the controller actions and how to assert on the result.&lt;/p&gt;  &lt;p&gt;I also had code snippets in the toolbox for some of the tricky parts of the code demo that I could use if something did not work or I felt that it took to long to write. Never let a problem in the code demo completely halt the presentation, have a backup plan or just move a long if you cannot fix the problem on the first 2 tries. &lt;/p&gt;  &lt;p&gt;I feel that I still have much to work on when it comes to presentation technique. I often talk a little to fast, need to focus on keeping calm and talking in a slow and articulate manner.&amp;#160; It doesn’t matter how nice your powerpoint or code demo is if the audience can’t hear what you are saying! &lt;/p&gt;  &lt;p&gt;Next up is trying keynote, nice to see how it compares to powerpoint. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-3989050977810047181?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=iM7qLe7DuUg:0QVDHN8kFbE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=iM7qLe7DuUg:0QVDHN8kFbE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=iM7qLe7DuUg:0QVDHN8kFbE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/3989050977810047181/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=3989050977810047181" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3989050977810047181?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3989050977810047181?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/05/presentation-code-demo-tips.html" title="Presentation &amp;amp; Code Demo Tips" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;D0YARXk7cSp7ImA9WxJREkQ.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-1327913798940842906</id><published>2009-05-13T19:20:00.001+02:00</published><updated>2009-05-14T11:59:04.709+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-14T11:59:04.709+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NHibernate" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="Design" /><title>The never ending stored procedure debate</title><content type="html">&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_TU8pT7DhyWk/SgsBWFMgoXI/AAAAAAAAArY/IKmWS2l7fQo/s1600-h/image%5B4%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; padding-right: 5px; display: inline; padding-left: 5px; border-left-width: 0px; border-bottom-width: 0px; padding-bottom: 5px; margin-left: 0px; margin-right: 0px; padding-top: 5px; border-right-width: 0px" height="222" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/SgsBWn7eJjI/AAAAAAAAArc/lxGuo4nfOmo/image_thumb%5B2%5D.png?imgmax=800" width="240" align="right" border="0" /&gt;&lt;/a&gt; I listened to the panel discussion on the &lt;a href="http://www.msteched.com/online/view.aspx?tid=1fd917e2-e451-44c2-b515-c778325846fe"&gt;pros and cons of stored procedures&lt;/a&gt; from the currently ongoing TechEd09 today. It was not what I hoped for, the panel consisted almost exclusively of pro stored procedure people with the exception of Jeffrey Palermo who for an NHibernate guy appeared very pro stored procedure. &lt;/p&gt;  &lt;p&gt;I was hoping for a more balanced debate. The arguments were to much focused on the real vs. perceived benefits of stored procedures in terms of performance, database coupling, vendor coupling, security etc. &lt;/p&gt;  &lt;p&gt;The really big issues I have personally with stored procedures (sprocs from now on) were never fully brought up. Especially when you compare sprocs and a manually coded DAL (which I find is the most common) with NHibernate.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Code duplication&lt;/strong&gt;     &lt;br /&gt;In my experience systems which rely heavily on sprocs also show a large amount of code duplication, for example duplication of SQL queries in the same sprocs in the case of dynamic queries that filter on different columns based on input. I have seen sprocs that feature the same basic query duplicated 12 times with small variation in the where/order clause. Also duplication between different sprocs can usually be very high. And the final point is the sad fact that sprocs usually contain some business logic, logic that sometimes also exist in the application itself. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Productivity &amp;amp; Lines of code&lt;/strong&gt;     &lt;br /&gt;This topic was also not really touched upon. Data access layers which use sprocs often feature massively more amount of code to deal with calling the sprocs and mapping them to entities. The amount of TSQL you need to write for the basic CRUD sprocs is also a huge time waster and possible maintenance nightmare. &lt;/p&gt;  &lt;p&gt;Some of these issues could be argued that it is just incompetent programmers/DBAs and sprocs are not to blame. Maybe it is not fair to compare sprocs with an ORM like NHibernate. But I think you can compare having to write and maintain sprocs compared to letting NHibernate generate adhoc SQL. Sure I think sprocs still have their usage in specific and relatively rare scenarios but the panel discussion too often concluded on the wishy washy &amp;quot;it depends&amp;quot;. Of course it depends, context is everything (as Scott Bellware always says), but that does not mean that one method shouldn't be the preferred &amp;quot;best practice&amp;quot; choice. &lt;/p&gt;  &lt;p&gt;Sorry for the rant. Kind of frustrated with a current legacy system (which uses sprocs) :) &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-1327913798940842906?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=6rDNYiRez_Y:GBO3zUuVyp4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=6rDNYiRez_Y:GBO3zUuVyp4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=6rDNYiRez_Y:GBO3zUuVyp4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/1327913798940842906/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=1327913798940842906" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/1327913798940842906?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/1327913798940842906?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/05/never-ending-store-procedure-debate.html" title="The never ending stored procedure debate" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">13</thr:total></entry><entry gd:etag="W/&quot;A0UDRnY5eip7ImA9WxVaEkU.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-5535131447843960167</id><published>2009-04-07T22:02:00.001+02:00</published><updated>2009-04-09T17:01:17.822+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-09T17:01:17.822+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Graphics" /><category scheme="http://www.blogger.com/atom/ns#" term="Misc" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>4D Mental Challange</title><content type="html">&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SduxPB1KKII/AAAAAAAAAqw/s3ggT51wUdw/s1600-h/507px-Right_hand_rule_cross_product%5B6%5D%5B5%5D.gif"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="507px-Right_hand_rule_cross_product[6]" border="0" alt="507px-Right_hand_rule_cross_product[6]" align="right" src="http://lh3.ggpht.com/_TU8pT7DhyWk/SduxPkd1HlI/AAAAAAAAAq0/rqgln5wtn6g/507px-Right_hand_rule_cross_product%5B6%5D_thumb%5B3%5D.gif?imgmax=800" width="270" height="244" /&gt;&lt;/a&gt;The picture to the right shows a hand that illustrates how the &lt;a href="http://en.wikipedia.org/wiki/Cross_product"&gt;cross product&lt;/a&gt; of two vectors (&lt;em&gt;&lt;strong&gt;a&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;b&lt;/strong&gt;&lt;/em&gt;) generate a vector that is &lt;a href="http://en.wikipedia.org/wiki/Orthogonal"&gt;perpendicular&lt;/a&gt; to both &lt;strong&gt;&lt;em&gt;a&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;b&lt;/em&gt;&lt;/strong&gt;. Now try to imagine four vectors that are all perpendicular to each other. This is kind of tricky, mainly because it is impossible for four 3-dimensional vectors to all be perpendicular to each other. &lt;/p&gt;  &lt;p&gt;But it is not impossible if the vectors are 4-dimensional, however that creates another problem: it is (at least for me) not possible to mentally picture a 4-dimensional space. Luckily I don’t have to the math works anyway :) The reason I post this is that I am porting an old &lt;a href="http://www.codinginstinct.com/2008/11/raytracing-4d-fractals-visualizing-four.html"&gt;4D Julia Raytracer&lt;/a&gt; from C++ to C# and was just struck by this magic function:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// Calculates a quaternion that is perpendicular to three other quaternions. &lt;/span&gt;
&lt;span class="rem"&gt;/// Quaternions are handled as vectors in 4d space&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="type"&gt;Quaternion&lt;/span&gt; Cross4D(&lt;span class="type"&gt;Quaternion&lt;/span&gt; q1,&lt;span class="type"&gt;Quaternion&lt;/span&gt; q2,&lt;span class="type"&gt;Quaternion&lt;/span&gt; q3)
{
  &lt;span class="kwrd"&gt;double&lt;/span&gt; b1c4=q2.r*q3.k-q2.k*q3.r;
  &lt;span class="kwrd"&gt;double&lt;/span&gt; b1c2=q2.r*q3.i-q2.i*q3.r;
  &lt;span class="kwrd"&gt;double&lt;/span&gt; b1c3=q2.r*q3.j-q2.j*q3.r;
  &lt;span class="kwrd"&gt;double&lt;/span&gt; b2c3=q2.i*q3.j-q2.j*q3.i;
  &lt;span class="kwrd"&gt;double&lt;/span&gt; b2c4=q2.i*q3.k-q2.k*q3.i;
  &lt;span class="kwrd"&gt;double&lt;/span&gt; b3c4=q2.j*q3.k-q2.k*q3.j;

  var r = -q1.i*b3c4+q1.j*b2c4-q1.k*b2c3;
  var i =  q1.r*b3c4-q1.j*b1c4+q1.k*b1c3;
  var j = -q1.r*b2c4+q1.i*b1c4-q1.k*b1c2;
  var k =  q1.r*b2c3-q1.i*b1c3+q1.j*b1c2;

  &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Quaternion&lt;/span&gt;(r, i, j, k);
}&lt;/pre&gt;

&lt;p&gt;This is a function that calculates a cross product for a 4-dimensional vector (the Quaternion class is used as a 4-dimensional vector in imaginary space). The reason for the naming of variables in the calculation relates to how the cross product formula is derived (as the determinant of a matrix). Anyway, I just found it funny that no matter how hard I try I cannot picture what this function actually generates. This is probably nothing new for mathematicians or physicist who I guess daily has to fight against the limitations of the human mind. &lt;/p&gt;

&lt;p&gt;But the math works, I can position the camera in 4D space and render pictures of the 4-dimensional Julia Set :) &lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SduxRSB5uCI/AAAAAAAAAq4/ClZQLhWgEQs/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SduxS_ifWZI/AAAAAAAAAq8/42NLUlyJurk/image_thumb%5B3%5D.png?imgmax=800" width="550" height="385" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;On a side note this app was MUCH easier to parallelize (using Parallel.For from the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=348F73FD-593D-4B3C-B055-694C50D2B0F3"&gt;Parallel Extensions Library&lt;/a&gt;) than &lt;a href="http://www.codinginstinct.com/2009/03/genart-wpf.html"&gt;GenArt&lt;/a&gt;. Because the algorithm works like a raytracer the outer ray casting loop is easily implemented using Parallel.For which instantly gave a 4x performance increase on my quad core CPU. &lt;/p&gt;

&lt;p&gt;I took some time to upload some of the old animations to youtube, they were rendered many years ago using the C++ version.&lt;/p&gt;

&lt;p&gt;Here is an animation of a camera move around the Julia set, the camera is moving in the second (i) and fourth (k) imaginary dimension.&lt;/p&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/uKzHudhFvHM&amp;amp;hl=sv&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/uKzHudhFvHM&amp;amp;hl=sv&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Here is another one, which I really like, the Julia constant is moving in a small circle in the first and second dimension. It gives me a strange impression of something organic and fluid. When I and my friend presented this rendering technique the first slide had this animation in a loop :) &lt;/p&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/GtrO6jPbbUo&amp;amp;hl=sv&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/GtrO6jPbbUo&amp;amp;hl=sv&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;

&lt;p&gt;You can see an interesting artifact of the rendering algorithm in the video above. The Julia Set actually hits the camera plane. The camera has a near plane where we start traversing the rays and a far plane where we stop, what happens is that the middle expands beyond the near plane, creating a flat surface. &lt;/p&gt;

&lt;p&gt;Here are some other rendered animations that I uploaded to youtube:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=Du-yJGCqebo"&gt;4D Julia Fractal - 4D Camera Move 2&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=L1myVXYZxzo"&gt;4D Julia Fractal - Constant Walk&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=etzYDQSABd8"&gt;4D Julia Fractal - Rotation of standard Julia&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-5535131447843960167?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=wvwSty_NDlc:AYFu2ukwsoI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=wvwSty_NDlc:AYFu2ukwsoI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=wvwSty_NDlc:AYFu2ukwsoI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/5535131447843960167/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=5535131447843960167" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5535131447843960167?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5535131447843960167?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/04/4d-mental-challange.html" title="4D Mental Challange" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;CkMFQ3g6eyp7ImA9WxVbFE8.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-369043139366741317</id><published>2009-03-30T10:42:00.001+02:00</published><updated>2009-03-30T15:40:12.613+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-30T15:40:12.613+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Design" /><title>Readability Is Number One</title><content type="html">&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="120" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SdCGCA5hK6I/AAAAAAAAAqs/qber8bxbW50/image_thumb%5B2%5D.png?imgmax=800" width="240" align="right" border="0" href="&amp;quot;$image[4].png&amp;quot;&amp;gt;&amp;lt;img" /&gt;   &lt;p&gt;How do you grade how well an application is written? &lt;/p&gt;  &lt;p&gt;There are many factors that will play a role in such an evaluation, for example (in no particular order):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Does the design follow object-oriented principles? &lt;/li&gt;    &lt;li&gt;Does it work? (i.e. few bugs) &lt;/li&gt;    &lt;li&gt;Does the code have unit tests? &lt;/li&gt;    &lt;li&gt;Is the code clean (easy to read, small functions) &lt;/li&gt;    &lt;li&gt;How much code duplication is there? &lt;/li&gt;    &lt;li&gt;Is there valuable code comments? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Of all those qualities I will have to say readability is the most important quality, I don’t care how procedural the code is so long as the functions are small and the conditional logic written in a such a way that it is easy to follow. Don’t get me wrong I value object-orientation, the S.O.L.I.D principles and unit tests a great deal. But the majority of existing systems I have been tasked to maintain and develop new functions in seldom exhibited any those qualities. &lt;/p&gt;  &lt;p&gt;What is usually found is a mess of procedural code where most of the code is located in the codebehind and with some common code moved to static methods on helper classes).&amp;#160; &lt;/p&gt;  &lt;p&gt;What constantly surprises me is how competent and intelligent developers can create complex and functioning systems but fail to grasp the simplest of methodologies of writing readable code.&lt;/p&gt;  &lt;p&gt;Here is some really bad code which has some of the characteristics that constantly frustrates me:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;
System.Web.UI.HtmlControls.&lt;span class="type"&gt;HtmlInputFile&lt;/span&gt; objFile =
  (System.Web.UI.HtmlControls.&lt;span class="type"&gt;HtmlInputFile&lt;/span&gt;)objControl;

&lt;span class="kwrd"&gt;try&lt;/span&gt;
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt;(System.IO.&lt;span class="type"&gt;Directory&lt;/span&gt;.Exists(strDir)==&lt;span class="kwrd"&gt;false&lt;/span&gt; ||
     Request[&lt;span class="str"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;] != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; Request[&lt;span class="str"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;] == &lt;span class="str"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &amp;amp;&amp;amp; isTpActive)
  {
    System.IO.&lt;span class="type"&gt;Directory&lt;/span&gt;.CreateDirectory(strDir);
    
    MyApp.Business.Entities.&lt;span class="type"&gt;Order&lt;/span&gt; order = 
      MyApp.DataAccess.&lt;span class="type"&gt;Production&lt;/span&gt;.GetOrder((&lt;span class="kwrd"&gt;int&lt;/span&gt;)Request[&lt;span class="str"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;]);
  }
  
}
&lt;span class="kwrd"&gt;catch&lt;/span&gt;(&lt;span class="type"&gt;Exception&lt;/span&gt; ex)
{
  error = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
  MyApp.Business.Logging.&lt;span class="type"&gt;ErrorLog&lt;/span&gt;.Append(ex);
}&lt;/pre&gt;

&lt;p&gt;The code above is not real, I actually wrote it just show what I mean. I am having a hard time understanding how people can write code like above. Why include the namespaces in everything? This is something I constantly see and I have never understood the reason for it. Then there are the classics, like complicated conditionals that don't contain any information as what the intent of the condition is. Exception handling is also misunderstood and misused. I often find excessive capturing of exceptions, it’s like try/catch is used like guard clauses, this is very frustrating because it makes debugging and troubleshooting very painful. &lt;/p&gt;

&lt;p&gt;Anyway, this post was not supposed to be a rant on bad code but about my realization that readability is the quality that I value most. Sure you get frustrated with procedural code that could have been so much simplified and reduced if some object orientation principles where applied but at least you don’t get a headache when trying to decipher code that is readable :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-369043139366741317?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=76JqItsaD6Y:Q5sWFR3R0ys:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=76JqItsaD6Y:Q5sWFR3R0ys:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=76JqItsaD6Y:Q5sWFR3R0ys:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/369043139366741317/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=369043139366741317" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/369043139366741317?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/369043139366741317?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/03/readability-is-number-one.html" title="Readability Is Number One" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;DUAARHY7fip7ImA9WxVUEko.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-1228925099176941108</id><published>2009-03-16T19:48:00.001+01:00</published><updated>2009-03-17T09:15:45.806+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-17T09:15:45.806+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Lambdas &amp; Performance implications</title><content type="html">&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/Sb6fAosZ0HI/AAAAAAAAAqk/ea0HeKJAnb8/s1600-h/image%5B5%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="82" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/Sb6fBHcXaRI/AAAAAAAAAqo/eBgslYfoEsU/image_thumb%5B3%5D.png?imgmax=800" width="300" align="right" border="0" /&gt;&lt;/a&gt; I have spent the last couple of days trying to find ways to parallelize &lt;a href="http://www.codinginstinct.com/2009/03/genart-wpf.html"&gt;GenArt WPF&lt;/a&gt; using Parallel.For (from the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=348F73FD-593D-4B3C-B055-694C50D2B0F3"&gt;Parallel Extensions Library&lt;/a&gt;). In the process I stumbled upon a scenario where using Lambdas/anonymous delegates can have pretty substantial performance implications. &lt;/p&gt; The code in question looked something like this:   &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Mutate(&lt;span class="type"&gt;EvolutionContext&lt;/span&gt; context)
{
    context.IfMutation(&lt;span class="type"&gt;MutationType.AddPoint&lt;/span&gt;, () =&amp;gt;
    {
        AddPoint(context);
    });
        
    &lt;span class="rem"&gt;///...&lt;/span&gt;
}&lt;/pre&gt;

&lt;p&gt;The function above was called in a while loop until a mutation hit was generated. I was not seeing the CPU utilization I was expecting. I was expecting 100% but got around 80% which I found strange, there was nothing that I could see that would cause a thread lock. To find the cause I started commenting out code. It was when I commented out the code above that I immediately saw the CPU utilization jump 100%. It must have been the garbage collector that caused the decrease in CPU utilization. Why the garbage collector? Well the code above will actually compile to something very different. &lt;/p&gt;

&lt;p&gt;Something like this (reconstructed approximation of the generated IL): &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;c__DisplayClass1&lt;/span&gt;
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="type"&gt;GeneticPolygon&lt;/span&gt; __this;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="type"&gt;EvolutionContext&lt;/span&gt; contex;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Mutate__0()
    {
        __this.AddPoint(contex);
    }
}

&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Mutate(&lt;span class="type"&gt;EvolutionContext&lt;/span&gt; context)
{
    &lt;span class="kwrd"&gt;var&lt;/span&gt; lambdaClass = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;c__DisplayClass1&lt;/span&gt;();
    lambdaClass.__this = &lt;span class="kwrd"&gt;this&lt;/span&gt;;
    lambdaClass.contex = context;

    context.IfMutation(&lt;span class="type"&gt;MutationType.AddPoint&lt;/span&gt;, lambdaClass.Mutate__0);
    
    &lt;span class="rem"&gt;///...&lt;/span&gt;
}&lt;/pre&gt;

&lt;p&gt;As you see the C# compiler actually creates a separate class to hold the lambda method body, a class that it will be instantiated every time the Mutate method is called. The reason for this is that it needs to capture the local variables (this is was makes lambdas/anonymous delegates true closures). I was well aware that this was happening but I have never encounter a situation where this has had any noticeable performance implications, until now that is. &lt;/p&gt;

&lt;p&gt;The fact that lambda methods that use local variables will result in an instantiation of a new object should not be a problem 99% of the time, but as this shows it is worth being aware of because in some cases it can matter a great deal. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-1228925099176941108?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=75_Bn7AdeEw:s8kKSydCbj8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=75_Bn7AdeEw:s8kKSydCbj8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=75_Bn7AdeEw:s8kKSydCbj8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/1228925099176941108/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=1228925099176941108" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/1228925099176941108?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/1228925099176941108?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/03/lambdas-performance-implications.html" title="Lambdas &amp;amp; Performance implications" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0EBQ3c7cCp7ImA9WxVVEks.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-7937853146560048455</id><published>2009-03-05T15:00:00.001+01:00</published><updated>2009-03-05T15:00:52.908+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-05T15:00:52.908+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Presentations" /><title>Developer Summit 2009</title><content type="html">&lt;p&gt;&lt;a href="http://www.cornerstone.se/sv/ExpertZone/developersummit/2009/"&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/Sa_bED49xjI/AAAAAAAAAqc/HP8u0q83Z5I/s1600-h/image%5B4%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; margin-left: 0px; border-left: 0px; margin-right: 0px; border-bottom: 0px" height="103" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/Sa_bE1cSvXI/AAAAAAAAAqg/7wg3ceyPch0/image_thumb%5B2%5D.png?imgmax=800" width="240" align="right" border="0" /&gt;&lt;/a&gt;Developer Summit&lt;/a&gt; is a great developer conference held in Stockholm each year. This time it is being held in April spread over 3 days with two conference days between 15-16 April and one workshop day on the 17th. I am going to have talk about Dependency Inversion (the pattern/principle) and how this pattern can help you create more loosely coupled applications. The talk will also be about what Inversion of Control containers are good for and how to use them effectively.&lt;/p&gt;  &lt;p&gt;I will also host a workshop about test driven development with ASP.NET MVC. A workshop that will be focusing on the testability aspects of ASP.NET MVC. Lab assignments could for example start with an empty controller test. I will go into scenarios where you need to use mocking/stubbing and scenarios where the MVC framework cleverly avoids mocking (by passing FormCollection to the action for example). There is also going to be lab assignments and examples that show how to use &lt;a href="http://watin.sourceforge.net/"&gt;WatiN&lt;/a&gt; for integration testing. &lt;/p&gt;  &lt;p&gt;Other interesting talks:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Good Test, Better Code by Scott Bellware&lt;/li&gt;    &lt;li&gt;A Technical Drilldown into “All Things M” by Brian Loesgen&lt;/li&gt;    &lt;li&gt;RESTful Enterprise Integration with Atom and AtomPub by Ian Robinson&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There are many more &lt;a href="http://www.cornerstone.se/sv/ExpertZone/developersummit/2009/"&gt;interesting talks&lt;/a&gt;, so be sure the sign up if you can. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-7937853146560048455?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=rhVajV6YQEs:q_ZJgEWeyyQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=rhVajV6YQEs:q_ZJgEWeyyQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=rhVajV6YQEs:q_ZJgEWeyyQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/7937853146560048455/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=7937853146560048455" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/7937853146560048455?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/7937853146560048455?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/03/developer-summit-2009.html" title="Developer Summit 2009" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEIMQHc9eCp7ImA9WxVVEUg.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-4473118818296431030</id><published>2009-03-03T15:55:00.001+01:00</published><updated>2009-03-04T08:43:01.960+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-04T08:43:01.960+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><title>GenART WPF</title><content type="html">&lt;p&gt;I have been playing with the WPF framework &lt;a href="http://www.codinginstinct.com/2009/02/wpf-action-dispatch-with-caliburn.html"&gt;Caliburn&lt;/a&gt; and just to have something fun to work on I ported &lt;a href="http://rogeralsing.com/"&gt;Roger Alsings&lt;/a&gt; &lt;a href="http://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-mona-lisa/"&gt;&amp;quot;EvoLisa&amp;quot;&lt;/a&gt; to WPF (from WinForms). &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://lh4.ggpht.com/_TU8pT7DhyWk/Sa1E8ZJRZZI/AAAAAAAAAqU/NE3UzbpjGdY/s1600-h/genArt_WPF%5B5%5D.png"&gt;&lt;img title="genArt_WPF" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="379" alt="genArt_WPF" src="http://lh3.ggpht.com/_TU8pT7DhyWk/Sa1E9fzA0cI/AAAAAAAAAqY/X2HjEqCLY9E/genArt_WPF_thumb%5B3%5D.png?imgmax=800" width="500" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I have preciously ported this app to Direct3D, and to Silverlight, these ports did not work out as I had hoped (although the native C++ Direct3D port was pretty fast). The application UI architecture was inspired by &lt;a href="http://www.nhprof.com"&gt;NHibernate Profiler&lt;/a&gt; (I took a sneak peek at the code via reflector, I hope &lt;a href="http://ayende.com/blog"&gt;ayende&lt;/a&gt; don’t mind). It was the fact that NHibernate Profiler uses Caliburn that got me interested in Caliburn in the first place. &lt;/p&gt;  &lt;p&gt;To checkout the code (Subversion): &lt;a title="http://tlo.googlecode.com/svn/trunk/GenArtWPF/" href="http://tlo.googlecode.com/svn/trunk/GenArtWPF/"&gt;http://tlo.googlecode.com/svn/trunk/GenArtWPF/&lt;/a&gt; (This is just a experimental spike to learn wpf/caliburn so no unit tests)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-4473118818296431030?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=ddTWoJOm2UY:HwFaCAw8Yy0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=ddTWoJOm2UY:HwFaCAw8Yy0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=ddTWoJOm2UY:HwFaCAw8Yy0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/4473118818296431030/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=4473118818296431030" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/4473118818296431030?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/4473118818296431030?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/03/genart-wpf.html" title="GenART WPF" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;A0ADRn87cSp7ImA9WxVXF0Q.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-1682658943458671919</id><published>2009-02-16T16:38:00.001+01:00</published><updated>2009-02-16T16:56:17.109+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-16T16:56:17.109+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><title>Review of CODE by Charles Petzold</title><content type="html">&lt;p&gt;&lt;a href="http://www.amazon.co.uk/Code-Language-DV-Undefined-Charles-Petzold/dp/0735611319/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1234792026&amp;amp;sr=8-1"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" align="right" src="http://www.chrismasto.com/delicious/images/255" width="179" height="265" /&gt;&lt;/a&gt;I recently read &lt;em&gt;CODE – The Hidden Language of Computer Hardware and Software &lt;/em&gt;by Charles Petzold. It was a great read and a book that I can recommend to anyone who whishes to understand how computers really works at the most basic level. The book goes into great detail on how binary systems work, and how computers use binary numbers to encode things like positive and negative numbers, alphabet characters, fractions, etc. But the main part of the book is about how to solve logical problems using simple relays (i.e. transistors) connected in different ways. &lt;/p&gt;  &lt;p&gt;During the different chapters Petzold&amp;#160; is building a more and more complex logical machine that ultimately resembles how a real modern computer work. He starts out with building simple logical gates (AND, NAND, OR, etc) out of relays, he then combines these into more complex units, for example a 1-bit adder and a 1-bit latch. &lt;/p&gt;  &lt;p&gt;Most of the stuff in the book was not really news to me but it was interesting non the less. I had forgotten how computers actually perform subtraction by using addition for example. It is pretty neat trick. The trick is to convert the number you are subtracting into &lt;a href="http://en.wikipedia.org/wiki/Two's_complement"&gt;two’s complement&lt;/a&gt;. Here is an example showing how you can calculate 7 – 5 with only using NOT and ADD operators. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SZmIVqi-MyI/AAAAAAAAAqM/g0IQmt7D4M4/s1600-h/image%5B17%5D.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/SZmIWHZWuuI/AAAAAAAAAqQ/ZC6CiLFw15Q/image_thumb%5B11%5D.png?imgmax=800" width="635" height="514" /&gt;&lt;/a&gt; An easier way to understand how this works is to try it with the number range 0-59.&lt;/p&gt;  &lt;pre&gt;  59
-  5
====
  54
+  1
====
  55
+  7
====
   2&lt;/pre&gt;

&lt;p&gt;Here we actually have to use subtraction to calculate the complement, the nice thing about twos' complement is that it can be calculated using the binary NOT operator. &lt;/p&gt;

&lt;p&gt;Ok, back to the book. The last chapters cover how computers are programmed, he describes in great detail how for example the stack work, how you call and pass parameters to subroutines and how interrupts are used to respond to hardware events like a button being pressed on a keyboard. Again nothing new to someone who has worked with assembly language or taken some basic classes in computer science, but it was nice to to refresh the knowledge and fill in some gaps. &lt;/p&gt;

&lt;p&gt;I first bought this book to give to my father who has trouble understanding and working with computers. He is constantly frustrated by the simplest things so I thought that it would help to have some understanding of how computers work. However I am not going to give this book to my farther, after the first couple of chapters the book quickly becomes very technical and tedious for someone who isn't that interested. But for any programmer who doesn't already know the fundamentals of computer hardware and software or just want to refresh their knowledge it is a great read. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-1682658943458671919?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=LgK4UXkzHAQ:cTyJHxf2q74:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=LgK4UXkzHAQ:cTyJHxf2q74:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=LgK4UXkzHAQ:cTyJHxf2q74:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/1682658943458671919/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=1682658943458671919" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/1682658943458671919?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/1682658943458671919?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/02/review-of-code-by-charles-petzold.html" title="Review of CODE by Charles Petzold" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEUESXs-fCp7ImA9WxVXFE4.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-5120881398733751811</id><published>2009-02-12T10:48:00.001+01:00</published><updated>2009-02-12T10:50:08.554+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-12T10:50:08.554+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Agile" /><category scheme="http://www.blogger.com/atom/ns#" term="Design" /><title>Ferengi &amp; Chess Rules</title><content type="html">&lt;p&gt;In Atwood's latest post &lt;a href="http://www.codinghorror.com/blog/archives/001225.html"&gt;The Ferengi Programmer&lt;/a&gt;, he argues that the OOP design guidelines and specifically Robert C Martin's &lt;a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;S.O.L.I.D&lt;/a&gt; principles are rules that hinder critical thinking and can be dangerous. It is a complete straw man argument, there is no one who advocate that these principles should be viewed as absolute rules that should be followed blindly without critical thinking. &lt;/p&gt;  &lt;p&gt;The most interesting and scary thing with Jeff's post are the comments, like: &lt;/p&gt;  &lt;blockquote&gt;&amp;quot;I'll tell you one thing, the Gang of Four book is probably one of my most disappointing programming reads of all time. Completely useless to me. Strange that I can have a successful programming career without understanding that book...&amp;quot; &lt;/blockquote&gt; Anyway, in Rob Conerey's &lt;a href="http://blog.wekeroad.com/blog/patterns-purists-and-sinkholes/"&gt;response&lt;/a&gt; post there was this great comment by David Nelson in which he makes an analogy with chess rules:   &lt;blockquote&gt;   &lt;p&gt;&amp;quot;In chess there are a set of rules that are taught to every beginning player: a queen is worth three minor pieces, develop knights before bishops, always castle, etc. But as a player improves, he learns that these are not actually rules, they are generalities. Over the course of analyzing many hundreds of thousands of games, good players have discovered certain strategies that are more likely to lead to a winning position. But just because they are more likely to be better, doesn't mean they will always be better. &lt;/p&gt;    &lt;p&gt;As a young player, I would often see an opportunity that I thought would lead to a quickly won game, by trying something other than what the &amp;quot;rules' would indicate. More often than not, I discovered that I was falling into a trap. Had I only followed the rules, I would have been better off. A player has to get very good before he can reliably understand when the rules don't apply. &lt;/p&gt;    &lt;p&gt;The point is that just because I know that the rules don't always apply, doesn't mean that I should ignore them and go my own way. I have to factor in both my own experience, and the &amp;quot;rules&amp;quot;, which are derived from the experience of thousands of players before me who were better than I am. And I have to weigh each of those factors appropriately. The better I get, the higher I can value my own experience. But even grandmasters work from a standard opening book. &lt;/p&gt;    &lt;p&gt;I know of no other industry in the world where the craftsman are so strongly resistant to learning from the mistakes and lessons of those who have come before. I think that it is mostly the result of the technological boom in the last two decades; we haven't had time to develop the educational process to teach programmers what they need to know, but we need the warm bodies, so we will take anybody who will sign up. Even those who are ignorant and unwilling to actually learn what they're doing.&amp;quot; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It is a great analogy, not that I know much about chess. I did read a book about chess strategy many years ago but can't say I remember much from it.&amp;#160; What I like about the analogy is the way it pictures guidelines and principles as a way to turn novice chess players into masters and how experience will eventually let you know the scenarios where the principles don’t apply. I also like the line “But even grandmasters work from a standard opening book” :)&lt;/p&gt;  &lt;p&gt;For more comments, read Justin Etheredge &lt;a href="http://www.codethinked.com/post/2009/02/11/Today-Ive-Realized-How-Far-We-Have-To-Go.aspx"&gt;response&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-5120881398733751811?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=9x3oiH0S5Us:PSA6J1hxgKA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=9x3oiH0S5Us:PSA6J1hxgKA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=9x3oiH0S5Us:PSA6J1hxgKA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/5120881398733751811/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=5120881398733751811" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5120881398733751811?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5120881398733751811?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/02/ferengi-chess-rules.html" title="Ferengi &amp;amp; Chess Rules" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUADQHo9eyp7ImA9WxVQFUU.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-5790216224279594840</id><published>2009-02-02T16:13:00.001+01:00</published><updated>2009-02-02T16:16:11.463+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-02T16:16:11.463+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>WPF Action Dispatch with Caliburn</title><content type="html">&lt;p&gt;I have been working with a WPF app on my spare time. I decided to use the WPF application framework called &lt;a href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt;. Caliburn is a lightweight framework that aids WPF and Silverlight development considerably. &lt;/p&gt;  &lt;p&gt;Caliburn Goals:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Support building WPF/SL application that are TDD friendly. &lt;/li&gt;    &lt;li&gt;Implement functionality for simplifying various UI design patterns in WPF/SL. These patterns include MVC, MVP, Presentation Model (MVVM), Commands, etc. &lt;/li&gt;    &lt;li&gt;Ease the use of a dependency injection container with WPF/SL. &lt;/li&gt;    &lt;li&gt;Simplify or provide alternatives to common WPF/SL related tasks. &lt;/li&gt;    &lt;li&gt;Provide solutions to common UI architecture problems. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;How does Caliburn work? A big part of WPF is it’s strong data binding functionality, however WPF control event handlers are normally defined in the control or view code behind. Caliburn lets you route using a declarative syntax control events to normal methods on your data bound presentation model. &lt;/p&gt;  &lt;p&gt;Example:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;UserControl&lt;/span&gt; &lt;span class="x_attr"&gt;x:Class&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;GenArt.Client.Views.TargetImageView&amp;quot;&lt;/span&gt;
    &lt;span class="x_attr"&gt;xmlns&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt;
    &lt;span class="x_attr"&gt;xmlns:x&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt;
    &lt;span class="x_attr"&gt;Action&lt;/span&gt;.&lt;span class="x_attr"&gt;Target&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;{Binding}&amp;quot;&lt;/span&gt;
    &lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;Grid&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;RowDefinition&lt;/span&gt; &lt;span class="x_attr"&gt;Height&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt; &lt;span class="x_kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;RowDefinition&lt;/span&gt; &lt;span class="x_attr"&gt;Height&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;*&amp;quot;&lt;/span&gt; &lt;span class="x_kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;Border&lt;/span&gt; &lt;span class="x_attr"&gt;Style&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;{StaticResource TargetImageBorder}&amp;quot;&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;Image&lt;/span&gt; &lt;span class="x_attr"&gt;x:Name&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;TargetImage&amp;quot;&lt;/span&gt; &lt;span class="x_attr"&gt;Source&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;..\Resources\Images\ml.bmp&amp;quot;&lt;/span&gt; &lt;span class="x_attr"&gt;Grid&lt;/span&gt;.&lt;span class="x_attr"&gt;Row&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="x_attr"&gt;MinHeight&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;150&amp;quot;&lt;/span&gt; &lt;span class="x_attr"&gt;MinWidth&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;150&amp;quot;&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;Image&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;            
        &lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;Border&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;Grid&lt;/span&gt; &lt;span class="x_attr"&gt;Grid&lt;/span&gt;.&lt;span class="x_attr"&gt;Row&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;                            
            &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;StackPanel&lt;/span&gt; &lt;span class="x_attr"&gt;HorizontalAlignment&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span class="x_attr"&gt;VerticalAlignment&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;Center&amp;quot;&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;Button&lt;/span&gt; &lt;span class="x_attr"&gt;Height&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt; &lt;span class="x_attr"&gt;Message&lt;/span&gt;.&lt;span class="x_attr"&gt;Attach&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;[Event Click] = [Action BrowseForTargetImage] : TargetImage.Source&amp;quot;&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;Select Target Image&lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;Button&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;Button&lt;/span&gt; &lt;span class="x_attr"&gt;Height&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt; &lt;span class="x_attr"&gt;Message&lt;/span&gt;.&lt;span class="x_attr"&gt;Attach&lt;/span&gt;&lt;span class="x_attr_v"&gt;=&amp;quot;[Event Click] = [Action StartPainting] : &amp;quot;&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;Start Painting&lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;Button&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;StackPanel&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;Grid&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;Grid&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;UserControl&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The first interesting Caliburn part is the attribute &lt;strong&gt;Action.Target=&amp;quot;{Binding}&amp;quot;&lt;/strong&gt; set on the top UserControl. This tells Caliburn that the action target is the current data binding instance (that is a presentation model). The second is the attribute &lt;strong&gt;Message.Attach=&amp;quot;[Event Click] = [Action StartPainting]”&lt;/strong&gt; set on the last Button Control. This two is a Caliburn WPF extension to declaratively attach the button click event to the method StartPainting. &lt;/p&gt;

&lt;p&gt;The StartPainting method is defined on the class named ApplicationModel (this is the top, root data bound class for the entire WPF app).&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;ApplicationModel&lt;/span&gt; : &lt;span class="type"&gt;PropertyChangedBase&lt;/span&gt;, &lt;span class="type"&gt;IApplicationModel&lt;/span&gt;
{
  &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="type"&gt;DrawingStatsModel&lt;/span&gt; stats;
  &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="type"&gt;PaintingCanvasModel&lt;/span&gt; paintingCanvas;

  &lt;span class="kwrd"&gt;public&lt;/span&gt; ApplicationModel(&lt;span clas="type"&gt;GenArtDispatcher&lt;/span&gt; dispatcher) : &lt;span class="kwrd"&gt;base&lt;/span&gt;(dispatcher)
  {
      stats = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;DrawingStatsModel&lt;/span&gt;(&lt;span class="kwrd"&gt;this&lt;/span&gt;, dispatcher);
      paintingCanvas = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;PaintingCanvasModel&lt;/span&gt;(&lt;span class="kwrd"&gt;this&lt;/span&gt;, dispatcher);      
  }

        
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="type"&gt;ImageSource&lt;/span&gt; BrowseForTargetImage()
  {    
    &lt;span class="rem"&gt;//...&lt;/span&gt;
  }

  [&lt;span class="type"&gt;AsyncAction&lt;/span&gt;(BlockInteraction = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; StartPainting()
  {
      &lt;span class="rem"&gt;///...&lt;/span&gt;
  }

}&lt;/pre&gt;
As you can see Caliburn can route WPF control events to normal methods, methods can have arguments taken from other WPF controls, methods can return values that Caliburn can use to update control properties (as in the case of the BrowseForTargetImage that returns a ImageSource). This is very powerful as it almost allows for an MVC like separation between UI and the underlying presentation behavior. 

&lt;h2&gt;Threading&lt;/h2&gt;

&lt;p&gt;Caliburn also makes async actions dead simple, if you need to have a WPF event handled in a background thread (so that it doesn't lock the UI) you only need to add a AsyncAction attribute. When the BlockInteraction parameter is set to true Caliburn will disable the WPF control that initiated the event and re-enable it when the action completes. &lt;/p&gt;
Almost all logic in a WPF app should be handled in a background threads however all UI interactions need to be done on the main UI thread. This can be handled easily by using a Dispatcher and a base class PropertyChangedBase. 

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;PropertyChangedBase&lt;/span&gt; : &lt;span class="type"&gt;INotifyPropertyChanged&lt;/span&gt;
{
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="type"&gt;GenArtDispatcher&lt;/span&gt; dispatcher;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span clas="type"&gt;PropertyChangedBase&lt;/span&gt;(&lt;span class="type"&gt;GenArtDispatcher&lt;/span&gt; dispatcher)
    {
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.dispatcher = dispatcher;
    }

    &lt;span class="preproc"&gt;#region&lt;/span&gt; &lt;span class="type"&gt;INotifyPropertyChanged&lt;/span&gt; Members

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; &lt;span class="type"&gt;PropertyChangedEventHandler&lt;/span&gt; PropertyChanged;

    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;

    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RaisePropertyChanged(&lt;span class="kwrd"&gt;string&lt;/span&gt; propertyName)
    {
        &lt;span class="kwrd"&gt;var&lt;/span&gt; &lt;span class="type"&gt;ChangeEvent&lt;/span&gt; = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span clas="type"&gt;ChangeEvent&lt;/span&gt;();
        &lt;span clas="type"&gt;ChangeEvent&lt;/span&gt;.PropertyName = propertyName;
        &lt;span clas="type"&gt;ChangeEvent&lt;/span&gt;.Source = &lt;span class="kwrd"&gt;this&lt;/span&gt;;
        dispatcher.Invoke(&lt;span clas="type"&gt;ChangeEvent&lt;/span&gt;);
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RaisePropertyChangedEventImmediately(&lt;span class="kwrd"&gt;string&lt;/span&gt; propertyName)
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (PropertyChanged != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            PropertyChanged(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyChangedEventArgs(propertyName));
    }
}&lt;/pre&gt;
This class is very important if you want your data bound WPF presentation model to be able to automatically update the UI by just raising a PropertyChanged event. The WPF infrastructure will subscribe to this event for all data bound classes. The dispatcher part is used so that the event is always raised on the UI thread, this is powerful as you can set presentation model properties without having to think about which thread you are in. Example: 

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; UpdateStats()
{
    Fitness = &lt;span class="type"&gt;Math&lt;/span&gt;.Max(0, MaxFitness - model.EvolutionProcess.CurrentFitness);
    Generations = model.EvolutionProcess.Generations;
    SelectedGenerations = model.EvolutionProcess.SelectedGenerations;
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; Fitness
{
    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; fitness; }
    set
    {
        fitness = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
        RaisePropertyChanged(&lt;span class="str"&gt;&amp;quot;Fitness&amp;quot;&lt;/span&gt;);
    }
}&lt;/pre&gt;
I was very impressed with Caliburn and how it makes WPF development easier. It allows you to move some of the code you would normally write in a code behind class or in a presenter directly into the presentation model and at the same time making this code easier to unit test. There are still scenarios that would require presenters but I think a majority of UI interactions could be handled using Caliburn in this way. There are more to Caliburn than I have mentioned in this post, so be sure to &lt;a href="http://www.codeplex.com/caliburn"&gt;check it out yourself&lt;/a&gt;!&amp;#160;   &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-5790216224279594840?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=ZmwTMJTo5-U:s7WnvfIMe8c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=ZmwTMJTo5-U:s7WnvfIMe8c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=ZmwTMJTo5-U:s7WnvfIMe8c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/5790216224279594840/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=5790216224279594840" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5790216224279594840?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5790216224279594840?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/02/wpf-action-dispatch-with-caliburn.html" title="WPF Action Dispatch with Caliburn" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;CEUAQH4_cCp7ImA9WxVQE00.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-755182520637380032</id><published>2009-01-29T16:29:00.001+01:00</published><updated>2009-01-30T08:57:21.048+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-30T08:57:21.048+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ALT.NET" /><title>ALT.NET Stockholm Unconference 7/2</title><content type="html">&lt;p&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" align="right" src="http://www.hanselman.com/blog/images/RWS2-Big3.png" width="176" height="240" /&gt;&lt;/p&gt;  &lt;p&gt;Next Saturday there will be another ALT.NET unconference in Stockholm. As before this is an open conference by developers for developers. This time we will open with some lightning talks.&lt;/p&gt;  &lt;p&gt;There are 8 lightning talks currently booked:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Develop for IPhone, perspectives from a .NET developer – Christian Libardo &lt;/li&gt;    &lt;li&gt;Fight code rot – Petter Wigle &lt;/li&gt;    &lt;li&gt;Should we stop mocking – Emil Gustafsson &lt;/li&gt;    &lt;li&gt;OpenTK – Olof Bjarnason &lt;/li&gt;    &lt;li&gt;Context/Specification with MSpec – Joakim Sundén &lt;/li&gt;    &lt;li&gt;Object databases for .NET – Peter Hultgren &lt;/li&gt;    &lt;li&gt;Continues Integration a case study – Helen Toomik &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The last ALT.NET conference was a great success so if you have a chance to attend be sure to &lt;a href="http://altdotnet.se/unconference.htm"&gt;sign up&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-755182520637380032?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=tRXmIY_wSWQ:Dcr3PR940uQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=tRXmIY_wSWQ:Dcr3PR940uQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=tRXmIY_wSWQ:Dcr3PR940uQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/755182520637380032/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=755182520637380032" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/755182520637380032?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/755182520637380032?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/01/altnet-stockholm-unconference-72.html" title="ALT.NET Stockholm Unconference 7/2" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUUCRng5fyp7ImA9WxVSFU0.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-2847925596184358407</id><published>2009-01-09T13:09:00.001+01:00</published><updated>2009-01-09T13:14:27.627+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-09T13:14:27.627+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>Silverlight and Pixel Level Graphics</title><content type="html">&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SWc-gz__JOI/AAAAAAAAAok/kqnmIGwFexc/s1600-h/image%5B6%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="303" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/SWc-hYY8H_I/AAAAAAAAAoo/PqbRvcRhR1I/image_thumb%5B4%5D.png?imgmax=800" width="350" align="right" border="0" /&gt;&lt;/a&gt;I have been playing with Silverlight the last few evenings, trying to port &lt;a href="http://rogeralsing.com/"&gt;Roger Alsings&lt;/a&gt;&amp;#160;&lt;a href="http://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-mona-lisa/"&gt;&amp;quot;EvoLisa&amp;quot;&lt;/a&gt; application to Silverlight. This application is very cool, it uses a genetic algorithm to create an image composed of polygons that resembles a target image (that you can choose). I have been thinking of doing something like that for some time. I am very interested in artificial life and evolution simulations, especially after reading so many books on evolution by Richard Dawkins and others. &lt;/p&gt;  &lt;p&gt;The EvoLisa application is written in WebForms and uses the GDI Graphics object to draw polygons to a bitmap surface, it then does pixel level comparisons to check how close this generated image is to the target image. This proved to be very difficult to port to Silverlight as it was not possible access the pixel buffer of Silverlight WPF controls and surfaces. After hours of googling for 2D or 3D graph&amp;#237;cs libraries for Silverlight I gave up and implemented a standard scan line polygon fill algorithm. It is not the simplest of algorithms, especially if you want to support complex polygons. &lt;/p&gt;  &lt;p&gt;Another issue was to to display the generated pixel buffer, this is also not possible. The only way to currently do it is through the Image control and encode you pixel buffer as a binary PNG stream which the Image control can then display.&amp;#160; Luckily Joe Stegman had already &lt;a href="http://blogs.msdn.com/jstegman/archive/2008/04/21/dynamic-image-generation-in-silverlight.aspx"&gt;figured this out&lt;/a&gt;, so I did not need to write my own png encoder. &lt;/p&gt;  &lt;p&gt;The last issue was also surprising, there is currently no way to read an image (client side) and access the pixels of that image. This is very easy to do server side with the Bitmap class, so instead of writing my own jpg/png decoder I send the target image to the server do the decoding there using the Bitmap class and&amp;#160; then return the pixels as an array of bytes. This is only required once so there is no significant performance penalty for doing this. Hopefully Silverlight 3 will add more low level graphics APIs.&lt;/p&gt;  &lt;p&gt;You can see a screenshot to the right, this is just after two evenings of hacking, so the GUI is still very ruff. The performance is not completely on par with the WinForms version, probably because of the scan line polygon renderer is not as optimised as the GDI version (I think GDI is not hardware accelerated, right?). &lt;/p&gt;  &lt;p&gt;Last night I took a break from the Silverlight version because I just had to try to do the same but using WPF and Direct3D to render the polygons, I got something working but I don't know the performance benefit yet as it is currently only rendering at the monitor refresh rate. You clearly notice how the Silverlight version slows down as more polygons are added, this is something that I hope the Direct3D version will eliminate.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-2847925596184358407?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=-dJn6-TdfAs:AvPgfFpsE38:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=-dJn6-TdfAs:AvPgfFpsE38:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=-dJn6-TdfAs:AvPgfFpsE38:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/2847925596184358407/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=2847925596184358407" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2847925596184358407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2847925596184358407?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2009/01/silverlight-and-pixel-level-graphics.html" title="Silverlight and Pixel Level Graphics" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;CUEHQX0-fSp7ImA9WxRaFkQ.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-8682843417950965138</id><published>2008-12-19T14:33:00.001+01:00</published><updated>2008-12-19T14:33:50.355+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-19T14:33:50.355+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Misc" /><title>Best of 2008 and some reflections on blogging</title><content type="html">&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/SUuitwzu-kI/AAAAAAAAAoU/i1VEtlAI_EY/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="76" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/SUuiufh_bQI/AAAAAAAAAoY/Cu1KmZgSJ-Y/image_thumb%5B3%5D.png?imgmax=800" width="500" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I thought I would do a best of post, as many others seems to be doing it. &lt;/p&gt;  &lt;p&gt;Most viewed posts (in order): &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/04/ioc-container-benchmark-unity-windsor.html"&gt;IoC Container Benchmark - Unity, Windsor, StructureMap and Spring.NET&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/04/nhibernate-20-events-and-listeners.html"&gt;NHibernate 2.0 Events and Listeners&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/05/jquery-and-separation-of-concerns.html"&gt;JQuery and Seperation of Concerns&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/07/cleanup-your-html-with-jquery.html"&gt;Cleanup your html with JQuery&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/10/breadcrum-menu-using-jquery-and-aspnet.html"&gt;Breadcrumb menu using JQuery and ASP.NET MVC&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/09/url-routing-fluent-interface.html"&gt;Url Routing Fluent Interface&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/11/creating-watin-dsl-using-mgrammar.html"&gt;Creating a WatiN DSL using MGrammar&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/10/view-model-inheritance.html"&gt;View Model Inheritance&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinginstinct.com/2008/04/nhibernate-20-statistics-and-monorail.html"&gt;NHibernate 2.0 Statistics and a MonoRail filter&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_TU8pT7DhyWk/SUuiuuLBBgI/AAAAAAAAAoc/_BHR2xnAoso/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="281" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/SUuivctX48I/AAAAAAAAAog/ZeX5O4iPhPU/image_thumb%5B8%5D.png?imgmax=800" width="400" align="right" border="0" /&gt;&lt;/a&gt; This was actually my first year of blogging. I have had ambitions to start blogging for years but just never got around to actually do it, mainly because of two reasons. First I thought that if I was going to start blogging I would need to setup a custom domain, fix hosting, install and configure some blogging software, etc. All that initial setup time was a road block to start blogging, I could just not find the time to do it because of a heavy work load and a lot of overtime. The second reason was that if I started blogging I wanted it to be a serious blog with good valuable content, and for that I felt that I needed to mature and gain some more experience.&lt;/p&gt;  &lt;p&gt;But in retrospect I regret that I did not start sooner, during 2005-2007 I was a lead developer on a multi-tenant B2B system where I did some interesting work with url rewriting with WebForms (before there was much information about it), started using NHibernate and Castle Windsor, SAP integration logging using AOP, etc, in short I had a lot to blog about that could have been valuable and helpful to the .NET community.&lt;/p&gt;  &lt;p&gt;I am very glad that I eventually started blogging because it has been a very fun, rewarding and learning experience. One of the reasons that I eventually started was the extremely easy setup that Google's blogger service provided where you could register a domain and start blogging in a mater of minutes. Google's blogger service has been pretty great as a way to get started, the only problem is the bad comment system and some lack of flexibility. I will probably be moving to a hosted solution where I can run and configure the blogging software myself during 2009 but right now it is not a top priority.&lt;/p&gt;  &lt;p&gt;I want thank everyone who subscribes or reads this blog, I have been very pleasantly surprised by the amount of people who subscribe, it is very motivating to see that people find value in things I write and keeps me wanting to write more and better. &lt;/p&gt;  &lt;p&gt;Merry Christmas &amp;amp; Happy New Year&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-8682843417950965138?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=UCJ0gbaHl_s:uaj36ldSr_Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=UCJ0gbaHl_s:uaj36ldSr_Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=UCJ0gbaHl_s:uaj36ldSr_Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/8682843417950965138/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=8682843417950965138" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/8682843417950965138?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/8682843417950965138?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/12/best-of-2008-and-some-reflections-on.html" title="Best of 2008 and some reflections on blogging" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;DkEARHwzfyp7ImA9WxRbF0g.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-3409434042308438568</id><published>2008-12-08T17:36:00.001+01:00</published><updated>2008-12-08T17:44:05.287+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-08T17:44:05.287+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Object Oriented ETL using RhinoETL</title><content type="html">&lt;p&gt;If you have worked with DTS or SSIS packages you probably know that they can quickly become painful to work with, especially concerning versioning, logging and above all deployment. &lt;/p&gt;  &lt;p&gt;I recently tried Ayende&amp;#180;s open source ETL framework &lt;a href="http://ayende.com/Blog/category/545.aspx"&gt;RhinoETL&lt;/a&gt;, it tackles the ETL problem from a completely different angle compared to DTS / SSIS. At it's heart RhinoETL is a very simple .NET framework to handle an ETL process, the key components are processes, pipelines and operations.&amp;#160; &lt;/p&gt;  &lt;p&gt;The process that I needed was a very simple one, namely to update a text table stored in multiple databases. The update could be of different types, for example swap every occurrence of a text translation to another and delete or update a specific row. In previously releases this was handled by writing manual update scripts. The release that I am working on currently however requires extensive changes to the texts in these tables spread over many databases and writing repetitive SQL scripts was not something that I felt doing. It felt like a good opportunity to try RhinoETL.&lt;/p&gt;  &lt;p&gt;I began writing this input operation:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;ReadWordList&lt;/span&gt; : &lt;span class="type"&gt;InputCommandOperation&lt;/span&gt;
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ReadWordList(&lt;span class="kwrd"&gt;string&lt;/span&gt; connectionStringName) 
      : &lt;span class="kwrd"&gt;base&lt;/span&gt;(connectionStringName) {  }

    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="type"&gt;Row&lt;/span&gt; CreateRowFromReader(&lt;span class="type"&gt;IDataReader&lt;/span&gt; reader)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Row.FromReader(reader);                
    }

    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PrepareCommand(&lt;span class="type"&gt;IDbCommand&lt;/span&gt; cmd)
    {
        cmd.CommandText = &lt;span class="str"&gt;&amp;quot;SELECT * FROM Wordlists&amp;quot;&lt;/span&gt;;
    }
}&lt;/pre&gt;

&lt;p&gt;This is the first operation, its responsibility is to fill the pipeline with rows from the Worldlists table. The next operation is the one updating the rows. It takes as input a list of ITextChange instances that is the object that performs the change. &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;TextChangeOperation&lt;/span&gt; : &lt;span class="type"&gt;AbstractOperation&lt;/span&gt;
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; IList&amp;lt;&lt;span class="type"&gt;ITextChange&lt;/span&gt;&amp;gt; changes;
  
    &lt;span class="kwrd"&gt;public&lt;/span&gt; TextChangeOperation(IList&amp;lt;&lt;span class="type"&gt;ITextChange&lt;/span&gt;&amp;gt; changes)
    {
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.changes = changes;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IEnumerable&amp;lt;&lt;span class="type"&gt;Row&lt;/span&gt;&amp;gt; Execute(IEnumerable&amp;lt;&lt;span class="type"&gt;Row&lt;/span&gt;&amp;gt; rows)
    {
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;var&lt;/span&gt; row &lt;span class="kwrd"&gt;in&lt;/span&gt; rows)
        {
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;var&lt;/span&gt; change &lt;span class="kwrd"&gt;in&lt;/span&gt; changes)
            {
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (change.IsValidFor(row))
                    change.Perform(row);
            }

            &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; row;
        }
    }
}&lt;/pre&gt;

&lt;p&gt;There is a class hierarchy representing the different types of text changes: &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_TU8pT7DhyWk/ST1NC2-zJMI/AAAAAAAAAhk/xZWQ5tx8jNo/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="400" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/ST1NEfEpOkI/AAAAAAAAAho/7b0SV_WKpqo/image_thumb%5B2%5D.png?imgmax=800" width="376" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code for the GeneralTextSwap class is very simple:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;GeneralTextSwap&lt;/span&gt; : &lt;span class="type"&gt;ITextChange&lt;/span&gt;
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; TextOld { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; TextNew { get; set; }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsValidFor(&lt;span class="type"&gt;Row&lt;/span&gt; row)
    {
        &lt;span class="kwrd"&gt;var&lt;/span&gt; text = ((&lt;span class="kwrd"&gt;string&lt;/span&gt;) row[&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;]).Trim();
        &lt;span class="kwrd"&gt;return&lt;/span&gt; text == TextOld;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Perform(&lt;span class="type"&gt;Row&lt;/span&gt; row)
    {
        row[&lt;span class="str"&gt;&amp;quot;TextOld&amp;quot;&lt;/span&gt;] = row[&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;];
        row[&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;] = TextNew;
    }
}&lt;/pre&gt;

&lt;p&gt;The point of storing the old text value is that I have an operation after the TextChangeOperation that logs all changes to a csv file. The changes for a specific release is then just defined as static list on a static class. For example: &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;ReleaseChanges_For_Jan09&lt;/span&gt;
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IList&amp;lt;&lt;span class="type"&gt;ITextChange&lt;/span&gt;&amp;gt; List;

  &lt;span class="kwrd"&gt;static&lt;/span&gt; ReleaseChanges_For_Jan09()
  {
    List = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="type"&gt;ITextChange&lt;/span&gt;&amp;gt;()
    {            
      &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;GeneralTextSwap&lt;/span&gt;() 
      {
         TextOld = &lt;span class="str"&gt;&amp;quot;some old link value&amp;quot;&lt;/span&gt;,
         TextNew = &lt;span class="str"&gt;&amp;quot;some new link value&amp;quot;&lt;/span&gt;
      },
      &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;UpdateTextRow&lt;/span&gt;()
      {
          DbName = &lt;span class="str"&gt;&amp;quot;DN_NAME&amp;quot;&lt;/span&gt;,
          WorldList = &lt;span class="str"&gt;&amp;quot;USER_PAGE&amp;quot;&lt;/span&gt;,
          Name = &lt;span class="str"&gt;&amp;quot;CROSS_APP_LINK&amp;quot;&lt;/span&gt;,
          TextNew = &lt;span class="str"&gt;&amp;quot;New link value&amp;quot;&lt;/span&gt;
      },
      &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;DeleteTextRow&lt;/span&gt;()
      {
          DbName = &lt;span class="str"&gt;&amp;quot;DN_NAME_2&amp;quot;&lt;/span&gt;,
          WorldList = &lt;span class="str"&gt;&amp;quot;SOME_PAGE&amp;quot;&lt;/span&gt;,
          Name = &lt;span class="str"&gt;&amp;quot;SOME_LINK&amp;quot;&lt;/span&gt;
      }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;The above is just an example in reality I have hundreds of general and specific changes, and yes this is legacy system which handles text and links very strangely. The above code could easily be handled by a simple sql script with about the same number of lines of TSQL code, the benefit of placing this inside an ETL written in C# is that I can easily reuse the change logic over multiple databases and I also get great logging and tracing of all changes. The point of this post is to show how easy it can be to use OOP to model and abstract an ETL process using RhinoETL. Even though this ETL process i very simple it serves as good example for showing how a TSQL script, DTS or SSIS packages can be rewritten and simplified using the power of an object oriented language. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-3409434042308438568?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=xVplqF0N3Yo:25QTYCPhMRI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=xVplqF0N3Yo:25QTYCPhMRI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=xVplqF0N3Yo:25QTYCPhMRI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/3409434042308438568/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=3409434042308438568" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3409434042308438568?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3409434042308438568?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/12/object-oriented-etl-using-rhinoetl.html" title="Object Oriented ETL using RhinoETL" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total></entry><entry gd:etag="W/&quot;DEcBSHs8eip7ImA9WxRbE0Q.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-2783340079004795671</id><published>2008-12-04T13:27:00.001+01:00</published><updated>2008-12-04T14:07:39.572+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-04T14:07:39.572+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="AOP" /><title>Crosscutting concerns &amp; AOP</title><content type="html">&lt;p&gt;Fredrik Norm&amp;#233;n recently &lt;a href="http://weblogs.asp.net/fredriknormen/archive/2008/12/04/isn-t-it-boring-to-write-crosscutting-concerns.aspx"&gt;posted&lt;/a&gt; about how crosscutting concerns are implemented with boring and often duplicated code, which can be handled by using aspect oriented programming (AOP). I have used AOP with great success in previous projects to handle scenarios like logging, transactions and change tracking. &lt;/p&gt;  &lt;p&gt;The problem with AOP is that it is not well supported or integrated into the CLR or the .NET framework and toolset. Sure there are great AOP frameworks that solve the problem via dynamic proxies, but such solutions have some big restrictions, for example they only work with virtual functions and you need to instantiate the object via a proxy creator. PostSharp handled AOP differently, it is a framework and a .NET post compiler that injects your crosscutting concerns at compile time. The problem I have found with PostSharp is that the post compile step is kind of slow, which is an issue if you do TDD (because you are constantly recompiling). Beside the compile time issue PostSharp is great tool and framework with great flexibility and power. &lt;/p&gt;  &lt;p&gt;I was kind of disappointed that Microsoft didn't present any plan to make AOP scenarios easier and more natural on the .NET platform at this years PDC. I am not sure how, but I just feel that the AOP experience on .NET could be vastly improved :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-2783340079004795671?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=TVUJspxWras:-ZqxPUBnt_8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=TVUJspxWras:-ZqxPUBnt_8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=TVUJspxWras:-ZqxPUBnt_8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/2783340079004795671/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=2783340079004795671" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2783340079004795671?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/2783340079004795671?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/12/crosscutting-concerns-aop.html" title="Crosscutting concerns &amp;amp; AOP" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;DEYEQ3c8eip7ImA9WxRbGEw.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-9085967652802164634</id><published>2008-12-03T16:21:00.001+01:00</published><updated>2008-12-09T10:48:22.972+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T10:48:22.972+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Presentations" /><category scheme="http://www.blogger.com/atom/ns#" term="Agile" /><title>The problem with agile statistics</title><content type="html">&lt;p&gt;A couple of weeks ago I was invited to a presentation by &lt;a href="http://www.ambysoft.com/scottAmbler.html"&gt;Scott Ambler&lt;/a&gt; on &amp;quot;Scaling Agile Software Development: Strategies for Applying Agile in Complex Situations&amp;quot;, it was an interesting talk. He showed a lot of diagrams and stats from a 2008 Agile Adoption rate survey, you can find the info &lt;a href="http://www.ambysoft.com/surveys/agileFebruary2008.html"&gt;here&lt;/a&gt;. The survey results are for example agile adoption rates, success rates, increase / decrease in code quality and costs. The problem with the survey is that it does not include any definition of what qualifies as agile. There are many different definitions on what makes software development agile, and many definitions like the &lt;a href="http://agilemanifesto.org/"&gt;manifesto&lt;/a&gt; (if you can even call that a definition) are very vague. I am not saying there is anything wrong with the manifesto or that agile needs to be better defined, what I am saying is that because agile can mean a lot of things to different people, and that many think they are doing agile while others might heartedly disagree, makes agile surveys like this very hard to interpret. &lt;/p&gt;  &lt;p&gt;For example, the survey that covers &lt;a href="http://www.ambysoft.com/surveys/modelingDocumentation2008.html"&gt;modelling and documentation practices&lt;/a&gt; concludes that:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Agile teams are more likely to model than traditional teams. &lt;/li&gt;    &lt;li&gt;Traditional teams are equally as likely to create deliverable documentation. &lt;/li&gt;    &lt;li&gt;For all the talk in the agile community about acceptance test driven development, few teams are actually doing it in practice. &lt;/li&gt;    &lt;li&gt;etc.. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Without some minimum criteria for what qualifies as &amp;quot;doing agile&amp;quot; these surveys don't tell me that much. Even if I would disagree with the definition I think they would make surveys like this a lot more interesting.&lt;/p&gt;  &lt;p&gt;I am not saying that the surveys are worthless, they do tell you something and they are a great resource for convincing management of agile practices so it is great that someone is taking the time to make them.&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-9085967652802164634?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=pwwcFmN-p2g:MGLpKw0o9mU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=pwwcFmN-p2g:MGLpKw0o9mU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=pwwcFmN-p2g:MGLpKw0o9mU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/9085967652802164634/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=9085967652802164634" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/9085967652802164634?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/9085967652802164634?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/12/problem-with-agile-statistics.html" title="The problem with agile statistics" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DU8HQ30zfyp7ImA9WxRbEkk.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-5219574591195394371</id><published>2008-12-02T20:45:00.001+01:00</published><updated>2008-12-02T20:57:12.387+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-02T20:57:12.387+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="M" /><category scheme="http://www.blogger.com/atom/ns#" term="MGrammar" /><title>English defined in MGrammar</title><content type="html">&lt;p&gt;&lt;a href="www.nicholsoncartoons.com.au"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="268" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/STWQUdrR8wI/AAAAAAAAAhU/6Kw8lW_1t2g/image%5B24%5D.png?imgmax=800" width="400" align="right" border="0" /&gt;&lt;/a&gt; I am very interested in how natural languages work and evolve (see my review of the book &lt;a href="http://www.codinginstinct.com/2008/05/language-instinct-review.html"&gt;The Language Instinct&lt;/a&gt;) and ever since I began playing with MGrammar I have wanted to see if it was possible to define English sentence structure using it. &lt;/p&gt;  &lt;p&gt;Lets begin with a simple sentence:&lt;/p&gt;  &lt;blockquote&gt;The boy likes the girl.&lt;/blockquote&gt;  &lt;p&gt;This sentence is composed of the noun phrase (NP) &amp;quot;the boy&amp;quot; and a verb phrase(VP) &amp;quot;likes the girl&amp;quot;. So lets begin with this MGrammar syntax:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;syntax&lt;/span&gt; Main = S*;        
&lt;span class="kwrd"&gt;syntax&lt;/span&gt; S = NP VP &lt;span class="str"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;;&lt;/pre&gt;

&lt;p&gt;If we look at the noun phrase &amp;quot;the boy&amp;quot;, it is composed of determiner followed by noun, like wise if we look at the verb phrase &amp;quot;likes the girl&amp;quot; we see that it is composed of verb followed by a noun phrase. The MGrammar should then be: &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;syntax&lt;/span&gt; NP = Det? N;
&lt;span class="kwrd"&gt;syntax&lt;/span&gt; VP = V NP;&lt;/pre&gt;

&lt;p&gt;Then we just need to add some determiners, verbs and nouns: &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;syntax&lt;/span&gt; Det = &amp;quot;a&amp;quot; | &amp;quot;the&amp;quot; | &amp;quot;one&amp;quot;;
&lt;span class="kwrd"&gt;syntax&lt;/span&gt; N = &amp;quot;boy&amp;quot; | &amp;quot;girl&amp;quot; | &amp;quot;dog&amp;quot; | &amp;quot;school&amp;quot; | &amp;quot;hair&amp;quot;;
&lt;span class="kwrd"&gt;syntax&lt;/span&gt; V = &amp;quot;likes&amp;quot; | &amp;quot;bites&amp;quot; | &amp;quot;eats&amp;quot; | &amp;quot;discuss&amp;quot;;&lt;/pre&gt;

&lt;p&gt;If you add an interleave rule to skip whitespace the sentence should be correctly parsed. That was a really simple sentence, lets add an adjective. &lt;/p&gt;

&lt;blockquote&gt;The nerdy boy likes the girl.&lt;/blockquote&gt;

&lt;p&gt;We need to modify the noun phrase rule. Before the noun an optional amount of adjectives (A*) can be placed. This is a simple change, just add A* to the noun phrase rule and add some adjectives. &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;syntax&lt;/span&gt; NP = Det? A* N;
&lt;span class="kwrd"&gt;syntax&lt;/span&gt; A = &amp;quot;happy&amp;quot; | &amp;quot;lucky&amp;quot; | &amp;quot;tall&amp;quot; | &amp;quot;red&amp;quot; | &amp;quot;nerdy&amp;quot;;&lt;/pre&gt;

&lt;p&gt;That was simple, lets add something more to the sentence, for example: &lt;/p&gt;

&lt;blockquote&gt;The nerdy boy likes the girl from school with red hair .&lt;/blockquote&gt;

&lt;p&gt;I added a nested prepositional phrase (PP). A prepositional phrase is, according to &lt;a href="http://en.wikipedia.org/wiki/Prepositional_phrase"&gt;wikipedia&lt;/a&gt;, composed of a preposition(P) and a noun phrase. &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;syntax&lt;/span&gt; NP = Det? A* N PP?;
&lt;span class="kwrd"&gt;syntax&lt;/span&gt; PP = P NP;
&lt;span class="kwrd"&gt;syntax&lt;/span&gt; P = &amp;quot;on&amp;quot; | &amp;quot;in&amp;quot; | &amp;quot;from&amp;quot; | &amp;quot;with&amp;quot;;&lt;/pre&gt;

&lt;p&gt;The recursive nature of the PP phrase makes it possible to nest infinite number of prepositional phrases inside each other. Here is an illustration of the syntax tree for &amp;quot;girl from school with red hair&amp;quot;: &lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_TU8pT7DhyWk/STWTEr7o_XI/AAAAAAAAAhY/2o4GZ6b_nZY/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="335" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/STWTFUbu3MI/AAAAAAAAAhc/DRm9ASxQ0f0/image_thumb%5B2%5D.png?imgmax=800" width="550" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I think I will stop here because this post is turning in to an English grammar lesson and I don't won't to loose all my subscribers :) Defining the English sentence structure in MGrammar is pretty pointless, unless you are building a grammar checker, in which case you are still out of luck as it will probably be impossible to define grammar for how words are built and you will run into trouble with ambiguity (which most natural languages have). But it was a fun try, and it is a good example for showing how recursive rules are parsed. &lt;/p&gt;

&lt;p&gt;If you missed Martin Fowlers &lt;a href="http://martinfowler.com/bliki/Oslo.html"&gt;post on Oslo&lt;/a&gt;, it is a good read, I like how he defines it as a &lt;a href="http://martinfowler.com/articles/languageWorkbench.html"&gt;Language Workbench&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;PS. I have started &lt;a href="http://twitter.com/torkelo"&gt;twittering&lt;/a&gt;, I know am late to the game, I just didn't get the point of twitter. I have been using it for a two days now and I am beginning to see the light. Oh, and please skip pointing out the irony with the inevitable grammatical errors in this post :) &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-5219574591195394371?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=lHXZx9XHy8A:CcNGKSGPIHk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=lHXZx9XHy8A:CcNGKSGPIHk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=lHXZx9XHy8A:CcNGKSGPIHk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/5219574591195394371/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=5219574591195394371" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5219574591195394371?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/5219574591195394371?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/12/english-defined-in-mgrammar.html" title="English defined in MGrammar" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry gd:etag="W/&quot;A0EBR346eSp7ImA9WxRUEkw.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-7192452786896139608</id><published>2008-11-20T18:49:00.001+01:00</published><updated>2008-11-20T23:20:56.011+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-20T23:20:56.011+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Graphics" /><title>Raytracing 4D fractals, visualizing the four dimensional properties of the Julia set</title><content type="html">&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SSWjIbcH8tI/AAAAAAAAAf4/PEKHfj4VGGE/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="350" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/SSWjI9jf8yI/AAAAAAAAAf8/peg4_prA9f4/image_thumb%5B6%5D.png?imgmax=800" width="300" align="right" border="0" /&gt;&lt;/a&gt;My main area of interest in programming during my school and university years was in computer graphics. I did a lot of hobby programming with games, like the Quake 3 mod Rocket Arena 3, and specifically with fractal graphics. This generated a quite serious outcome during a course on research methodologies where I together with a friend wrote a scientific paper on 4D Julia rendering. &lt;/p&gt;  &lt;p&gt;The 2D Julia fractal to the left is a shape that everyone recognizes. The simple formula that defines the Julia and Mandelbrot set is also something that many know:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_TU8pT7DhyWk/SSWjJOP9E2I/AAAAAAAAAgA/94Xa-8vMisI/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="37" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/SSWjJXEOzQI/AAAAAAAAAgE/Zmy8pPS1b7M/image_thumb%5B8%5D.png?imgmax=800" width="157" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The variable z and constant c are in a normal 2D Julia set &lt;a href="http://en.wikipedia.org/wiki/Complex_number"&gt;complex numbers&lt;/a&gt;. A complex number is a tuple of two values, a real and imaginary part, which can be visualized in the complex pane, which is a 2D geometric representation of complex numbers.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_TU8pT7DhyWk/SSWjJqNj1vI/AAAAAAAAAgI/W3MP3mponVw/s1600-h/image%5B19%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="134" alt="image" src="http://lh3.ggpht.com/_TU8pT7DhyWk/SSWjKPkd1iI/AAAAAAAAAgM/qZ63FnuvkNM/image_thumb%5B13%5D.png?imgmax=800" width="100" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Complex numbers can be extended to a four-tuple value with one real and three imaginary units. These are called Quaternions and can be visualized as a four dimensional space. When using the Julia equation with Quaternions we can define a 4D dimensional object. It becomes a lot trickier to visualize however. What is needed is a 4D camera from which you can cast rays (vectors). The algorithm traverse these vectors step by step (from the camera) and for each point the Julia equation is recursively run to determine if the point is part of the Julia set or not. &lt;/p&gt;  &lt;p&gt;Here is 2D illustration of how a ray is thrown and sampled at regular intervals:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/SSWjKViyR5I/AAAAAAAAAgQ/r_kttSs0SB4/s1600-h/image%5B23%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="174" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/SSWjK558sGI/AAAAAAAAAgU/UshNid5bLWo/image_thumb%5B15%5D.png?imgmax=800" width="240" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The process of sampling each point can be very time consuming so the distance between sample points can not be to small, but it can not be the to high either as it directly relates to the point resolution you get as exemplified by these two images:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/SSWjLYGyYCI/AAAAAAAAAgY/UDZyMXmF36I/s1600-h/image%5B44%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="154" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/SSWjLmUNvLI/AAAAAAAAAgc/8gbOki3RhDg/image_thumb%5B28%5D.png?imgmax=800" width="487" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The left image has a higher distance between sample points compared to the image to the right. You can clearly see the artifact of how the algorithm works in the rings in the image to the left (each ring is a sample point along the ray). To optimise the sampling process we can move back after a sample hit and then move forward in smaller steps.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_TU8pT7DhyWk/SSWjMI85kiI/AAAAAAAAAgg/An9WVQzipyA/s1600-h/image%5B28%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="249" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/SSWjMjqcbqI/AAAAAAAAAgk/ICe_P23dB6U/image_thumb%5B18%5D.png?imgmax=800" width="480" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here is the Julia set viewed from the side, the constant (Julia seed) is (0.4 0.5i 0j 0k).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SSWjNN5stjI/AAAAAAAAAgo/Ha7PkgLlAoI/s1600-h/image%5B33%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="263" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SSWjNnZ-EWI/AAAAAAAAAgs/VZ1RJwS9L5Q/image_thumb%5B21%5D.png?imgmax=800" width="437" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The raytracing gives coordinates in a 4D space that belongs to the Julia set, each point can be given a color depending on how far the point is from the camera (as above). Further each point can be lighted and shaded. To accurately light a point you need it's surface normal, these normals can be calculated by looking at the relative heights of neighbouring points (pixels). &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SSWjNxSRbAI/AAAAAAAAAgw/dPFa716Sp7A/s1600-h/image%5B39%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="210" alt="image" src="http://lh3.ggpht.com/_TU8pT7DhyWk/SSWjOJ6hliI/AAAAAAAAAg0/MJs225cznOI/image_thumb%5B25%5D.png?imgmax=800" width="240" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The most fascinating aspect of 4D Julia sets can be viewed when you animated them. To animate them you render pictures with small change to the Julia seed constant or to the camera position. What is particularly interesting is when you move the camera in the fourth dimension. What you get is an animation of how the Julia set looks like from different four dimensional angles. It is hard to describe what happens, but basically the shape morphs into different shapes when viewed from different four dimensional angles :) &lt;/p&gt;  &lt;p&gt;During the process of coding our raytracer we accidentally made an error in the quaternion multiplication, which resulted in a very strange shape:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SSWjOnSydZI/AAAAAAAAAg4/aEmgBP3Evl8/s1600-h/image%5B49%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="274" alt="image" src="http://lh3.ggpht.com/_TU8pT7DhyWk/SSWjPKV1uxI/AAAAAAAAAg8/TzddVKBgnWw/image_thumb%5B31%5D.png?imgmax=800" width="492" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;We named these &amp;#252;ber quaternions. Later when we were writing the paper we discovered that we had used commutative multiplication rules which resulted in &lt;a href="http://en.wikipedia.org/wiki/Hypercomplex_numbers"&gt;hypercomplex numbers&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Here is another picture showing how the shape gets more detail depending on the number of times you recurse over the Julia algorithm:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_TU8pT7DhyWk/SSWjPcDW1OI/AAAAAAAAAhA/BwcDoTFhhkM/s1600-h/image%5B54%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="252" alt="image" src="http://lh6.ggpht.com/_TU8pT7DhyWk/SSWjQEJcZaI/AAAAAAAAAhE/gaQKp1zsB18/image_thumb%5B34%5D.png?imgmax=800" width="423" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Isn't it fascinating and beautiful how such a simple algorithm can define such an intricate structure? The raytracer was witten in C++ and my plan is to (someday, maybe next year) port / rewrite it in F# :) &lt;/p&gt;  &lt;p&gt;The paper is very technical so I doubt that it will interest many, but here is the link and abstract:&lt;/p&gt;  &lt;blockquote&gt;By using rules defined by quaternion algebra the Julia set can be extended to four dimensions. Techniques for visualizing the four dimensional Julia set as a three dimensional object has previously been explored, however those techniques usually ignores the fourth dimension. In this paper we describe our attempt to extend the already established technique of ray tracing Julia sets to fully incorporate its four dimensional properties. We also discuss an optimisation algorithm that drastically increases the amount of details in images and shortens rendering time.&lt;/blockquote&gt;  &lt;p&gt;Link to the paper: &lt;a href="http://www.codinginstinct.com-a.googlepages.com/Raytracing4D.pdf"&gt;Raytracing4D.pdf&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Movies:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;4D Camera move: &lt;a href="http://www.codinginstinct.com-a.googlepages.com/4d_cameramove.avi"&gt;4d_cameramove.avi&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Another 4D Camera move: &lt;a href="http://www.codinginstinct.com-a.googlepages.com/r4d.avi"&gt;r4d.avi&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Moving the seed in circle (on the complex pane): &lt;a href="http://www.codinginstinct.com-a.googlepages.com/cycle.avi"&gt;cycle.avi&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Moving the seed from left to right (on the complex pane): &lt;a href="http://www.codinginstinct.com-a.googlepages.com/cwalk.avi"&gt;cwalk.avi&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Moving the camera in a circle around the hypercomplex julia set:&amp;#160; &lt;a href="http://www.codinginstinct.com-a.googlepages.com/uber_highres.avi"&gt;uber_highres.avi&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;It is worth pointing our that in the two first movies with 4D camera movies it is only the camera that is moving the julia seed never changes, only the angle that the object is viewed at. The paper was written with LaTeX, which was a lot of fun to learn, although quite hard to use. But the output looks so much more professional.&lt;/p&gt;  &lt;p&gt;Were you also a graphics geek? Did you write a flame or plasma effect in assembler, did you use allegro to write DOS games? I sure did :) &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-7192452786896139608?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=o-qqkbA5ZDA:V4_Jl5xqMZo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=o-qqkbA5ZDA:V4_Jl5xqMZo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=o-qqkbA5ZDA:V4_Jl5xqMZo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/7192452786896139608/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=7192452786896139608" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/7192452786896139608?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/7192452786896139608?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/11/raytracing-4d-fractals-visualizing-four.html" title="Raytracing 4D fractals, visualizing the four dimensional properties of the Julia set" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;C0UFQHc7cSp7ImA9WxRUEUs.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-3771941200212404989</id><published>2008-11-19T17:24:00.001+01:00</published><updated>2008-11-20T07:06:51.909+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-20T07:06:51.909+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MGrammar" /><category scheme="http://www.blogger.com/atom/ns#" term="Oslo" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="WatiN" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>Browser Automation DSL using MGrammar, Part 2</title><content type="html">&lt;p&gt;My &lt;a href="http://www.codinginstinct.com/2008/11/creating-watin-dsl-using-mgrammar.html"&gt;first try&lt;/a&gt; with writing a DSL for WatiN was such fun experience that I decided to have another go. I wanted to try to create something with a little more natural sentence like syntax. Here are some tests showing of the new syntax: &lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="type"&gt;--- Can filter by author ---&lt;/span&gt;
goto address &lt;span class="str"&gt;&amp;quot;http://demo.codesaga.com/&amp;quot;&lt;/span&gt;. 
click the link with the text &lt;span class="str"&gt;&amp;quot;MvcContrib&amp;quot;&lt;/span&gt;.
select &lt;span class="str"&gt;&amp;quot;torkel&amp;quot;&lt;/span&gt; from the list with the id &lt;span class="kwrd"&gt;#author-fitler&lt;/span&gt;.
page should contain the text &lt;span class="str"&gt;&amp;quot;Filtering view by author torkel&amp;quot;&lt;/span&gt;.

&lt;span class="type"&gt;--- Can filter by date ---&lt;/span&gt; 
goto address &lt;span class="str"&gt;&amp;quot;http://demo.codesaga.com&amp;quot;&lt;/span&gt;. 
click the link with the text &lt;span class="str"&gt;&amp;quot;xUnit&amp;quot;&lt;/span&gt;.
set focus to the textbox with the id &lt;span class="kwrd"&gt;#date-filter&lt;/span&gt;.
click the link with the text &lt;span class="str"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;.
page should contain the text &lt;span class="str"&gt;&amp;quot;Filtering view by date&amp;quot;&lt;/span&gt;.

&lt;span class="type"&gt;--- Can expand diff in changsest view (via ajax) ---&lt;/span&gt;
goto address &lt;span class="str"&gt;&amp;quot;http://demo.codesaga.com/history/xUnit?cs=25434&amp;quot;&lt;/span&gt;.
click the element with the class name &lt;span class="kwrd"&gt;@cs-item-diff&lt;/span&gt;.
page should contain the element with the class name &lt;span class="kwrd"&gt;@code-cell&lt;/span&gt;, wait for
it 3 seconds.&lt;/pre&gt;

&lt;p&gt;The added verbosity might be to much for programmers but the point of making something like this more readable is to make acceptance tests understandable by non-programmers. I am not saying that acceptance tests is something that shouldn't involve developers. But having them accessible to for non-programmers can be very valuable. I am not sure why, I kind of like the verbosity in this case (I usually don't). It would be very easy to make some words optional so one can write &amp;quot;click #edit&amp;quot; as a shortening of &amp;quot;click the link with the id #edit&amp;quot;. &lt;/p&gt;
The MGrammar for this language: 

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;module&lt;/span&gt; CodingInstinct {
    &lt;span class="kwrd"&gt;import&lt;/span&gt; Language;
    &lt;span class="kwrd"&gt;import&lt;/span&gt; Microsoft.Languages;
    &lt;span class="kwrd"&gt;export&lt;/span&gt; BrowserLang;
 
    &lt;span class="kwrd"&gt;language&lt;/span&gt; BrowserLang {
                  
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; Main = t:Test* =&amp;gt; t;
        
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; Test = name:TestName
            a:ActionList =&amp;gt; Test { Name { name }, ActionList { a } };
                                      
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; ActionList
          = item:Action =&amp;gt; [item]
          | list:ActionList item:Action =&amp;gt; [valuesof(list), item];
                             
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; Action = a:ActionDef &lt;span class="str"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; =&amp;gt; a;
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; ActionDef
            = a:GotoAction =&amp;gt; a
            | a:ClickAction =&amp;gt; a
            | a:SelectAction =&amp;gt; a
            | a:TextAssert =&amp;gt; a
            | a:ElementAssert =&amp;gt; a
            | a:TypeAction =&amp;gt; a
            | a:SetFocusAction =&amp;gt; a;
                            
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; GotoAction = &lt;span class="str"&gt;&amp;quot;goto&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;address&amp;quot;&lt;/span&gt;? theUrl:StringLiteral
            =&amp;gt; GotoAction { Url { theUrl } };
                
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; ClickAction = &lt;span class="str"&gt;&amp;quot;click&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt;? (&lt;span class="str"&gt;&amp;quot;link&amp;quot;&lt;/span&gt; | &lt;span class="str"&gt;&amp;quot;element&amp;quot;&lt;/span&gt;)? ec:ElementConstraint 
            =&amp;gt; ClickAction { Constraint { ec } };
        
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; TypeAction = &lt;span class="str"&gt;&amp;quot;type&amp;quot;&lt;/span&gt; value:StringLiteral &lt;span class="str"&gt;&amp;quot;into&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;textbox&amp;quot;&lt;/span&gt; ec:ElementConstraint
            =&amp;gt; TypeAction { Value { value&amp;gt; }, Constraint { ec } };
            
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; SelectAction = &lt;span class="str"&gt;&amp;quot;select&amp;quot;&lt;/span&gt; value:StringLiteral &lt;span class="str"&gt;&amp;quot;from&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;list&amp;quot;&lt;/span&gt; ec:ElementConstraint
            =&amp;gt; SelectAction { Value { value }, Constraint { ec } };
        
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; TextAssert = &lt;span class="str"&gt;&amp;quot;page should contain&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; text:StringLiteral 
            =&amp;gt; TextAssert { Value { text } };
            
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; ElementAssert = &lt;span class="str"&gt;&amp;quot;page should contain&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;element&amp;quot;&lt;/span&gt; ec:ElementConstraint 
            wait:ElementWait?
            =&amp;gt; ElementAssert { Constraint { ec }, Wait { wait } };
            
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; ElementWait = &lt;span class="str"&gt;&amp;quot;wait&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;for&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;it&amp;quot;&lt;/span&gt; sec:Base.Digits (&lt;span class="str"&gt;&amp;quot;second&amp;quot;&lt;/span&gt; | &lt;span class="str"&gt;&amp;quot;seconds&amp;quot;&lt;/span&gt;) 
            =&amp;gt; sec;
            
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; SetFocusAction = &lt;span class="str"&gt;&amp;quot;set&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;focus&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;to&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;textbox&amp;quot;&lt;/span&gt; ec:ElementConstraint 
            =&amp;gt; SetFocusAction { Constraint { ec } };
                 
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; ElementConstraint
            = &lt;span class="str"&gt;&amp;quot;with&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; name:StringLiteral =&amp;gt; TextConstraint { Value { name } } 
            | &lt;span class="str"&gt;&amp;quot;with&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; name:ElementId =&amp;gt; IdConstraint { Value { name } } 
            | &lt;span class="str"&gt;&amp;quot;with&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;the&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;class&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;name&amp;quot;&lt;/span&gt; name:ElementClass =&amp;gt; ClassConstraint { Value { name } };
                  
        &lt;span class="kwrd"&gt;token&lt;/span&gt; TestName = &lt;span class="str"&gt;&amp;quot;--- &amp;quot;&lt;/span&gt; (Base.Letter|Base.Whitespace)+ &lt;span class="str"&gt;&amp;quot; ---&amp;quot;&lt;/span&gt;;    
        &lt;span class="kwrd"&gt;token&lt;/span&gt; ElementId = &lt;span class="str"&gt;'#'&lt;/span&gt; (Base.Letter|&lt;span class="str"&gt;'-'&lt;/span&gt;|&lt;span class="str"&gt;'_'&lt;/span&gt;)+;
        &lt;span class="kwrd"&gt;token&lt;/span&gt; ElementClass = &lt;span class="str"&gt;'@'&lt;/span&gt; (Base.Letter|&lt;span class="str"&gt;'-'&lt;/span&gt;|&lt;span class="str"&gt;'_'&lt;/span&gt;)+;
                                                    
        &lt;span class="kwrd"&gt;interleave&lt;/span&gt; Skippable
          = Base.Whitespace+ 
          | Language.Grammar.Comment
          | Base.NewLine
          | &lt;span class="str"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;;
                
        &lt;span class="kwrd"&gt;syntax&lt;/span&gt; StringLiteral
          = val:Language.Grammar.TextLiteral =&amp;gt; val;        
    }

}&lt;/pre&gt;

&lt;p&gt;Another improvement in this new DSL syntax is the format for specifying an element or class name. In the above grammar these are defined as tokens, where ids begin with # and class names with @ followed by any word. The nice thing with a token is that you can add a Classification attribute to it where you specify what token category it belongs to. Classification names are linked to font and color styles (i.e. syntax highlighting). &lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SSQ9wPFxDuI/AAAAAAAAAfw/zFH2BFLOY_A/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="176" alt="image" src="http://lh5.ggpht.com/_TU8pT7DhyWk/SSQ9wVcTeXI/AAAAAAAAAf0/XNvdcG0WIXU/image_thumb%5B2%5D.png?imgmax=800" width="552" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;To get the DSL to actually execute you need the MGraph node tree that the parser spits. The MGraph is not something that you want work with directly as it is pretty low level. When I did the first version of this WatiN DSL I spent the majority of the time figuring out how to parse and deserialize the MGraph into a custom set of AST classes. In the process I wrote a very basic generic MGraph -&amp;gt; .NET classes deserializer. &lt;/p&gt;

&lt;p&gt;Luckily, as Don Box pointed out in the comments to my previous post, SpankyJ has written a &lt;a href="http://blogs.msdn.com/joshwil/archive/2008/11/12/using-mgrammar-to-create-net-instances-through-xaml.aspx"&gt;much better deserializer&lt;/a&gt; that converts the MGraph into Xaml via an MGraphXamlReader. It was very easy to switch to his implementation as he had some useful method extensions on the DynamicParser. &lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="type"&gt;DynamicParser&lt;/span&gt; parser = LoadExampleGrammar();

&lt;span class="kwrd"&gt;var&lt;/span&gt; xamlMap = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Dictionary&lt;/span&gt;&amp;lt;Identifier, Type&amp;gt;
    { { &lt;span class="str"&gt;&amp;quot;Person&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="type"&gt;Person&lt;/span&gt;) } };

&lt;span class="kwrd"&gt;var&lt;/span&gt; people = parser.Parse&amp;lt;List&amp;lt;&lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt;&amp;gt;(testInput, xamlMap);&lt;/pre&gt;

&lt;p&gt;But having to define the mapping between MGraph node names and .NET classes manually like this was something I did not like. I wanted something with a more convention based approach. &lt;a href="http://rogeralsing.com/"&gt;Roger Alsing&lt;/a&gt; is also doing some work with MGrammar and he gave me this great piece of code which I modified slightly: &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="type"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Identifier&lt;/span&gt;, &lt;span class="type"&gt;Type&lt;/span&gt;&amp;gt; GetTypeMap()
{
  &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="type"&gt;Assembly&lt;/span&gt;
    .GetExecutingAssembly()
    .GetTypes()
    .Where(t =&amp;gt; t.Namespace.StartsWith(&lt;span class="str"&gt;&amp;quot;WatinDsl.Ast&amp;quot;&lt;/span&gt;))
    .Where(t =&amp;gt; !t.IsAbstract)
    .ToDictionary
    (
      t =&amp;gt; (&lt;span class="type"&gt;Identifier&lt;/span&gt;)t.Name,
      t =&amp;gt; t
    );
}&lt;/pre&gt;

&lt;p&gt;Pretty simple code really,&amp;#160; it just creates a dictionary of all the non abstract types in the namespace WatinDsl.Ast. &lt;/p&gt;

&lt;p&gt;I basically rewrote the AST for this new version, now most actions have a Constraint property that determines what element the action is targeting. Here is an sample:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;ClickAction&lt;/span&gt; : &lt;span class="type"&gt;IAction&lt;/span&gt;
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="type"&gt;IElementConstraint&lt;/span&gt; Constraint { get; set; }
    
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Execute(&lt;span class="type"&gt;IBrowser&lt;/span&gt; browser)
    {
        browser.Element(Constraint.Get()).Click();
    }
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="type"&gt;IdConstraint&lt;/span&gt; : &lt;span class="type"&gt;IElementConstraint&lt;/span&gt;
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Value { get; set; }

  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="type"&gt;AttributeConstraint&lt;/span&gt; Get()
  {
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="type"&gt;Find&lt;/span&gt;.ById(Value.Substring(1));
  }
}&lt;/pre&gt;

&lt;p&gt;For the full code: &lt;a href="http://www.codinginstinct.com-a.googlepages.com/WatinDsl_2.zip"&gt;WatinDsl_2.zip&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This is still just an experimental spike for learning MGrammar, but it is also an interesting scenario for exploring the potential in a browser automation language. Is a browser automation language, like the one I have created, something that you would find useful? What would your syntax look like?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-3771941200212404989?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=XEvojea0zsU:9G6CTKvMbNc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=XEvojea0zsU:9G6CTKvMbNc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=XEvojea0zsU:9G6CTKvMbNc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/3771941200212404989/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=3771941200212404989" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3771941200212404989?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/3771941200212404989?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/11/browser-automation-dsl-using-mgrammar.html" title="Browser Automation DSL using MGrammar, Part 2" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">10</thr:total></entry><entry gd:etag="W/&quot;D0cFSXY6cCp7ImA9WxRUEU0.&quot;"><id>tag:blogger.com,1999:blog-3198935374994345981.post-7779709010296021298</id><published>2008-11-19T15:28:00.001+01:00</published><updated>2008-11-19T15:30:18.818+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-19T15:30:18.818+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Oslo" /><title>Intellipad Love</title><content type="html">&lt;p&gt;Working with MGrammar in Intellipad's split view in fullscreen on a 26&amp;quot; monitor is pure joy :) &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_TU8pT7DhyWk/SSQihmavzZI/AAAAAAAAAfo/7wSmZ_Sz16g/s1600-h/image%5B50%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="382" alt="image" src="http://lh4.ggpht.com/_TU8pT7DhyWk/SSQiiGkn-wI/AAAAAAAAAfs/IMnqOA5spIo/image_thumb%5B34%5D.png?imgmax=800" width="600" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;To change the default color schema in intellipad is easy, just modify the Intellipad\Settings\ClassificationFormats.xcml file. It looks like this:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;act:Export&lt;/span&gt; &lt;span class="x_attr"&gt;Name&lt;/span&gt;&lt;span class="x_attr_v"&gt;='{}{Microsoft.Intellipad}ClassificationFormat'&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;ls:ClassificationFormat&lt;/span&gt; &lt;span class="x_attr"&gt;Name&lt;/span&gt;&lt;span class="x_attr_v"&gt;='Unknown'&lt;/span&gt; 
                           &lt;span class="x_attr"&gt;FontSize&lt;/span&gt;&lt;span class="x_attr_v"&gt;='13'&lt;/span&gt; 
                           &lt;span class="x_attr"&gt;FontFamily&lt;/span&gt;&lt;span class="x_attr_v"&gt;='Consolas'&lt;/span&gt; 
                           &lt;span class="x_attr"&gt;Foreground&lt;/span&gt;&lt;span class="x_attr_v"&gt;='#FFEEEEEE'&lt;/span&gt; &lt;span class="x_kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;act:Export&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;act:Export&lt;/span&gt; &lt;span class="x_attr"&gt;Name&lt;/span&gt;&lt;span class="x_attr_v"&gt;='{}{Microsoft.Intellipad}ClassificationFormat'&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="x_kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="x_html"&gt;ls:ClassificationFormat&lt;/span&gt; &lt;span class="x_attr"&gt;Name&lt;/span&gt;&lt;span class="x_attr_v"&gt;='Numeric'&lt;/span&gt; 
                           &lt;span class="x_attr"&gt;Foreground&lt;/span&gt;&lt;span class="x_attr_v"&gt;='#FFEEEEEE'&lt;/span&gt; &lt;span class="x_kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="x_kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="x_html"&gt;act:Export&lt;/span&gt;&lt;span class="x_kwrd"&gt;&amp;gt;&lt;/span&gt;

///....&lt;/pre&gt;

&lt;p&gt;The hard part was to figure out how to change the background color, which currently can't be done by changing some xml config file but can be accomplished with a small python snippet. &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="type"&gt;@Metadata&lt;/span&gt;.CommandExecuted(&lt;span class="str"&gt;'{Microsoft.Intellipad}BufferView'&lt;/span&gt;, 
        &lt;span class="str"&gt;'{Microsoft.Intellipad}SetBlackBackground'&lt;/span&gt;, 
        &lt;span class="str"&gt;'Ctrl+Shift+F2'&lt;/span&gt;)
&lt;span class="kwrd"&gt;def&lt;/span&gt; SetBlackBackground(target, bufferView, args):
   bufferView.TextEditor.TextView.Background = System.Windows.Media.Brushes.Black&lt;/pre&gt;

&lt;p&gt;I got this snipped from Vijaye Raji (SUPER NINJA). You got to digg someone with SUPER NINJA in their Microsoft email display name :) &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3198935374994345981-7779709010296021298?l=www.codinginstinct.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=o2Zv2kOkyBI:Y87FpX-Ab7k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/codinginstinct?a=o2Zv2kOkyBI:Y87FpX-Ab7k:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/codinginstinct?i=o2Zv2kOkyBI:Y87FpX-Ab7k:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codinginstinct.com/feeds/7779709010296021298/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3198935374994345981&amp;postID=7779709010296021298" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/7779709010296021298?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3198935374994345981/posts/default/7779709010296021298?v=2" /><link rel="alternate" type="text/html" href="http://www.codinginstinct.com/2008/11/intellipad-love.html" title="Intellipad Love" /><author><name>Torkel Ödegaard</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09877956948598008136" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
