<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://consultingblogs.emc.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">John Rayner's Blog (2006-2010)</title><subtitle type="html">Brain.Extract&amp;lt;IBloggable&amp;gt;( Where.Author.Is( "John.Rayner" ) );</subtitle><id>http://consultingblogs.emc.com/johnrayner/atom.aspx</id><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/default.aspx" /><link rel="self" type="application/atom+xml" href="http://consultingblogs.emc.com/johnrayner/atom.aspx" /><generator uri="http://communityserver.org" version="2.1.20423.1">Community Server</generator><updated>2007-05-10T01:11:00Z</updated><entry><title>Downloading sessions from MIX10 (and PDC09)</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2010/03/24/sessions-from-mix10.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2010/03/24/sessions-from-mix10.aspx</id><published>2010-03-24T23:52:00Z</published><updated>2010-03-24T23:52:00Z</updated><content type="html">&lt;P&gt;To get hold of the videos of the &lt;A href="http://live.visitmix.com/"&gt;sessions from the recent MIX10 conference&lt;/A&gt;, the MIX10 site suggests you download cURL and hack around with some .bat files. &amp;nbsp;Yuck! &amp;nbsp;But now a much nicer option is available - &lt;A href="http://www.sharpfellows.com/author/naeemkhedarun.aspx"&gt;Naeem Khedarun&lt;/A&gt; from &lt;A href="http://www.sharpfellows.com/"&gt;#Fellows&lt;/A&gt; has recently &lt;A href="http://www.sharpfellows.com/post/Session-downloader-for-mix.aspx"&gt;announced a WPF session downloader&lt;/A&gt;. &amp;nbsp;It supports resuming of interrupted downloaded and you can install it via the magic of ClickOnce directly from the #Fellows site (see &lt;A href="http://www.sharpfellows.com/post/Session-downloader-for-mix.aspx"&gt;Naeem's post&lt;/A&gt; for the URL).&lt;/P&gt;
&lt;P&gt;As an added extra, downloads of the PDC 2009 videos still work from this application.&amp;nbsp; So install it once and you get easy access to 280 hours of technical goodness!&amp;nbsp; Including, of course, our very own &lt;A href="http://consultingblogs.emc.com/members/Paul.Dawson.aspx"&gt;Paul Dawson&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=16988" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author></entry><entry><title>Another reason to love Resharper: it can make you look like a LINQ-ninja</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2009/12/02/another-reason-to-love-resharper-it-can-make-you-look-like-a-linq-ninja.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2009/12/02/another-reason-to-love-resharper-it-can-make-you-look-like-a-linq-ninja.aspx</id><published>2009-12-02T00:24:00Z</published><updated>2009-12-02T00:24:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/Another-reason-to-love-Resharper-it-can-make-you-look-like-a-LINQ-ninja.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For those of who spend our time immersed in code, we're usually trying to find ways to write better code that more clearly expresses our intent.&amp;nbsp; And in a place like EMC Consulting there is a very healthy competition between devs to write code that is better, cleaner, faster, etc.&amp;nbsp; One of the new features of &lt;A href="http://www.jetbrains.com/resharper/index.html" target=_blank&gt;Resharper 5.0&lt;/A&gt; (R#) manages to address both of these points!&amp;nbsp; &lt;img src="http://consultingblogs.emc.com/emoticons/emotion-2.gif" alt="Big Smile" /&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.jetbrains.com/" target=_blank&gt;Jetbrains&lt;/A&gt; have given R# a pretty deep understanding of LINQ.&amp;nbsp; To be honest, I'm feeling like R# knows LINQ considerably better than I do!&amp;nbsp; You see, R# 5.0 will offer to convert your code into LINQ statements wherever it can.&amp;nbsp; Here's an example:&lt;/P&gt;
&lt;P&gt;My code:&lt;/P&gt;&lt;SPAN style="TEXT-ALIGN:left;"&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&lt;SPAN style="COLOR:blue;"&gt;foreach&lt;/SPAN&gt;(&lt;SPAN style="COLOR:blue;"&gt;var&lt;/SPAN&gt; summaryType &lt;SPAN style="COLOR:blue;"&gt;in&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;TypeMapper&lt;/SPAN&gt;.GetMapper(entityType.Assembly)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetSummaryTypes(entityType))&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp; &amp;nbsp;&lt;SPAN style="COLOR:blue;"&gt;if&lt;/SPAN&gt;(&lt;SPAN style="COLOR:blue;"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR:#2b91af;"&gt;VersionableSummaryBase&lt;/SPAN&gt;).IsAssignableFrom(summaryType))&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;var&lt;/SPAN&gt; summary = (&lt;SPAN style="COLOR:#2b91af;"&gt;VersionableSummaryBase&lt;/SPAN&gt;)&lt;SPAN style="COLOR:#2b91af;"&gt;EntityCache&lt;/SPAN&gt;.Instance.RetrieveIfCached(id, summaryType);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;if&lt;/SPAN&gt; (((&lt;SPAN style="COLOR:#2b91af;"&gt;IVersionable&lt;/SPAN&gt;)entity).Version &amp;lt; summary.Version)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mustReload = &lt;SPAN style="COLOR:blue;"&gt;true&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;break&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Applying the R# suggestion:&lt;/P&gt;&lt;SPAN style="TEXT-ALIGN:left;"&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;mustReload = &lt;SPAN style="COLOR:#2b91af;"&gt;TypeMapper&lt;/SPAN&gt;.GetMapper(entityType.Assembly)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetSummaryTypes(entityType)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Where(summaryType =&amp;gt; &lt;SPAN style="COLOR:blue;"&gt;typeof&lt;/SPAN&gt; (&lt;SPAN style="COLOR:#2b91af;"&gt;VersionableSummaryBase&lt;/SPAN&gt;).IsAssignableFrom(summaryType))&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Select(summaryType =&amp;gt; (&lt;SPAN style="COLOR:#2b91af;"&gt;VersionableSummaryBase&lt;/SPAN&gt;) &lt;SPAN style="COLOR:#2b91af;"&gt;EntityCache&lt;/SPAN&gt;.Instance.RetrieveIfCached(id, summaryType))&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Where(summary =&amp;gt; summary != &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Select(summary =&amp;gt; summary.Version)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Any(summaryVersion =&amp;gt; ((&lt;SPAN style="COLOR:#2b91af;"&gt;IVersionable&lt;/SPAN&gt;) entity).Version &amp;lt; summaryVersion);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Even without understanding what my TypeMapper class is doing, or any of the other details you can clearly see, I think that the second version is easier to read and more clearly expresses the underlying algorithm.&amp;nbsp; If you have an opinion on this, then please leave it in the comments ... I'd love to get other views.&lt;/P&gt;
&lt;P&gt;Here's another gem from R#.&amp;nbsp; My code:&lt;/P&gt;&lt;SPAN style="TEXT-ALIGN:left;"&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;SPAN style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt; sourceElements = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:#2b91af;"&gt;Dictionary&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR:blue;"&gt;int&lt;/SPAN&gt;, &lt;SPAN style="COLOR:#2b91af;"&gt;EntityBase&lt;/SPAN&gt;&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;o:p&gt;&lt;FONT size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;SPAN style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;foreach&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt; (&lt;SPAN style="COLOR:#2b91af;"&gt;EntityBase&lt;/SPAN&gt; element &lt;SPAN style="COLOR:blue;"&gt;in&lt;/SPAN&gt; collectionFromSource)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sourceElements.Add(element.InternalID, element);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;And the R# version:&lt;/P&gt;&lt;SPAN style="TEXT-ALIGN:left;"&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;SPAN style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt; sourceElements = collectionFromSource.Cast&amp;lt;&lt;SPAN style="COLOR:#2b91af;"&gt;EntityBase&lt;/SPAN&gt;&amp;gt;()&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt 36pt;" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY:Consolas;"&gt;&lt;FONT size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ToDictionary(element =&amp;gt; element.InternalID);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P style="TEXT-ALIGN:left;MARGIN:0cm 0cm 0pt;" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;I didn't even know that that particular extension methods existed until R# suggested I use it!&amp;nbsp; And perhaps with R# 5.0 in my toolkit, I'll be able to get the edge over some of the other devs at work.&amp;nbsp; At least, until someone blogs about it ... oh bother!&amp;nbsp; &lt;img src="http://consultingblogs.emc.com/emoticons/emotion-5.gif" alt="Wink" /&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=16656" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="Engineering practices" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Engineering+practices/default.aspx" /><category term="C# 3.0" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/C_2300_+3.0/default.aspx" /><category term="Resharper" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Resharper/default.aspx" /><category term="LINQ" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/LINQ/default.aspx" /></entry><entry><title>Sharding into the cloud</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2009/11/10/sharding-into-the-cloud.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="935061" href="http://consultingblogs.emc.com/johnrayner/attachment/16543.ashx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2009/11/10/sharding-into-the-cloud.aspx</id><published>2009-11-10T22:40:00Z</published><updated>2009-11-10T22:40:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/Sharding-into-the-cloud.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;NHibernate.Shards is an extension to the &lt;A href="http://nhforge.org/Default.aspx"&gt;well-known ORM&lt;/A&gt; which allows a logical database to be &lt;A href="http://en.wikipedia.org/wiki/Partition_(database)"&gt;partitioned&lt;/A&gt; across multiple physical databases and servers.&amp;nbsp; It's a port of the &lt;A href="https://www.hibernate.org/414.html"&gt;Hibernate.Shards project&lt;/A&gt;, as with lots of thing in NHibernate.&amp;nbsp; I thought it would be interesting to see how well it worked against &lt;A href="http://www.microsoft.com/windowsazure/sqlazure/"&gt;SQL Azure&lt;/A&gt;.&amp;nbsp; It turned out to be not interesting at all ... just plain easy!&amp;nbsp; &lt;img src="http://consultingblogs.emc.com/emoticons/emotion-2.gif" alt="Big Smile" /&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Step 1:&lt;/STRONG&gt; Register with SQL Azure&lt;BR&gt;&lt;EM&gt;Turnaround on token requests is pretty quick right now (&amp;lt;24 hours in my case).&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Step 2:&lt;/STRONG&gt; Setup some SQL Azure databases&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Step 3:&lt;/STRONG&gt; Setup appropriate logins, users&lt;BR&gt;&lt;EM&gt;The SQL Azure team have done a great job to allow SQL Server Management Studio to connect a query window to an Azure database, but I'm a bit SQL-phobic at the best of times. This was the most challenging bit for me!&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Step 4:&lt;/STRONG&gt; Download and compile NHibernate.Shards from &lt;A href="http://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk/src/NHibernate.Shards/"&gt;NHContrib Subversion&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Step 5:&lt;/STRONG&gt; Set your connection strings in the config file&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Step 6&lt;/STRONG&gt;: Press play.&amp;nbsp; Really, that's all there is to it!&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now you may notice that I neglected to create any schema in the Azure databases - that's because NHibernate&amp;nbsp;can do that for me.&amp;nbsp; Did I mention that I'm a bit SQL-phobic?&amp;nbsp; &lt;img src="http://consultingblogs.emc.com/emoticons/emotion-5.gif" alt="Wink" /&gt;&lt;/P&gt;
&lt;P&gt;The code I was using was the standard example that comes with NHibernate.Shards, which&amp;nbsp;records WeatherReport objects,&amp;nbsp;which I've attached.&amp;nbsp; It's the same example that Ayende dissected, so you can&amp;nbsp;also pick up his discussion of&amp;nbsp;&lt;A href="http://ayende.com/Blog/archive/2009/10/18/nhibernate-shards-progress-report.aspx"&gt;the workings of NHibernate.Shards&lt;/A&gt;.&amp;nbsp; The code looks like this (click to enlarge):&lt;/P&gt;
&lt;P&gt;&lt;A title="Full-size code" href="http://consultingblogs.emc.com/photos/conchango_bloggers/images/16544/original.aspx" target=_blank&gt;&lt;IMG style="WIDTH:500px;HEIGHT:316px;" border=0 hspace=30 src="http://consultingblogs.emc.com/photos/conchango_bloggers/images/16544/500x316.aspx" width=500 height=316&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;And the results are as follows (click to enlarge):&lt;/P&gt;
&lt;P&gt;&lt;A title="Full-size results" href="http://consultingblogs.emc.com/photos/conchango_bloggers/images/16545/original.aspx" target=_blank&gt;&lt;IMG style="WIDTH:500px;HEIGHT:295px;" border=0 hspace=30 src="http://consultingblogs.emc.com/photos/conchango_bloggers/images/16545/500x295.aspx" width=500 height=295&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Some of the features of NHibernate.Shards that really stood out for me:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It can query all shards in parallel or sequentially.&amp;nbsp; For SQL Azure, that's quite useful!&amp;nbsp; A sequential query my single-record shards took 601ms, whereas a parallelized query took 411ms (almost 33% less).&lt;/LI&gt;
&lt;LI&gt;New&amp;nbsp;records can be allocated to shards based on either the data (e.g. surname starts with A-M or N-Z) or some other scheme (e.g. round-robin).&lt;/LI&gt;
&lt;LI&gt;If&amp;nbsp;the correct&amp;nbsp;shard can be identified based on an object's identity, then only that single shard is queried to retrieve the&amp;nbsp;entity (this is based on your own IShardResolutionStrategy implementation).&lt;/LI&gt;
&lt;LI&gt;If you sort by a property, then this sort will be applied even when data is merged from multiple shards.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Overall though, it all just works tremendously well.&amp;nbsp; Congratulations really must go to:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The Microsoft SQL Azure team&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://darioquintana.com.ar/blogging/"&gt;Dario Quintana&lt;/A&gt;, for his work on NHibernate.Shards&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://fabiomaulo.blogspot.com/"&gt;Fabio&lt;/A&gt;, &lt;A href="http://ayende.com/Blog/Default.aspx"&gt;Ayende&lt;/A&gt; and the rest of the NHibernate committers&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;EDIT: Querying data from the shards is done using code like the following.&amp;nbsp; You should notice that this code makes no references to the shards, and in fact is "normal" NHibernate code.&amp;nbsp; The sharding is all handled transparently in the ORM.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH:610px;HEIGHT:38px;" hspace=30 src="http://consultingblogs.emc.com/photos/conchango_bloggers/images/16548/original.aspx" width=610 height=38&gt;&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=16543" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="NHibernate" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/NHibernate/default.aspx" /><category term="NHibernate.Shards" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/NHibernate.Shards/default.aspx" /><category term="SQL Azure" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/SQL+Azure/default.aspx" /><category term="Cloud" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Cloud/default.aspx" /></entry><entry><title>Google Chrome: First impressions (and a few benchmarks)</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2008/09/02/google-chrome-first-impressions-and-a-few-benchmarks.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2008/09/02/google-chrome-first-impressions-and-a-few-benchmarks.aspx</id><published>2008-09-02T21:13:00Z</published><updated>2008-09-02T21:13:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/Google-Chrome-First-impressions-(and-a-few-benchmarks).aspx"&gt;blog post has moved&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.google.com/chrome" target=_blank&gt;Google Chrome&lt;/A&gt; has now been released for download - see &lt;A href="http://blogs.conchango.com/derekdunlop/archive/2008/09/02/shiny-and-new-must-be-chrome-google-launches-new-browser-in-24hrs.aspx" target=_blank&gt;Derek's post&lt;/A&gt; for some opinion on this or the &lt;A href="http://googleblog.blogspot.com/2008/09/fresh-take-on-browser.html" target=_blank&gt;"leaked"&lt;/A&gt; &lt;A href="http://www.google.com/googlebooks/chrome/index.html" target=_blank&gt;information from Google&lt;/A&gt;.&amp;nbsp; I've installed it and I have to say that I like it a lot - the minimalist UI is rather nice (although IE7 has drifted in a similar direction), the "omnibox" (was previously the address bar) seems to actually work in terms of how it handles it's auto completion and the initial start page is a great idea.&amp;nbsp; But the thing that really got to me was just how fast it is.&amp;nbsp; And I mean ...&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH:440px;HEIGHT:110px;" title=FAST hspace=15 alt=FAST src="http://blogs.conchango.com/photos/conchango_bloggers/images/12423/original.aspx" width=440 height=110&gt;&lt;/P&gt;
&lt;P&gt;There's lots of numbers below where I try to measure just how fast Google Chrome is compared to IE 7, but what really impressed me was when my wife (who is non-techie) browsed a few sites using Chrome&amp;nbsp;and noticed the difference in speed.&lt;/P&gt;
&lt;P&gt;To see just how real the speed increase was, I visited a number of benchmarking sites.&amp;nbsp; &lt;A href="http://www.quirksmode.org/" target=_blank&gt;QuirksMode&lt;/A&gt; have a &lt;A href="http://www.quirksmode.org/dom/innerhtml.html" target=_blank&gt;benchmark for creating HTML table elements&lt;/A&gt; via JavaScript.&amp;nbsp; As the following table outlines, IE 7 took 4,652 ms to complete all the tests and Google Chrome took 186 ms.&amp;nbsp; That's literally an order of magnitude faster.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH:358px;HEIGHT:259px;" src="http://blogs.conchango.com/photos/conchango_bloggers/images/12420/original.aspx" width=358 height=259&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://celtickane.com/index.php" target=_blank&gt;Celtic Kane&lt;/A&gt; has a benchmark which attempts to &lt;A href="http://celtickane.com/webdesign/jsspeed.php" target=_blank&gt;measure the core JavaScript engine&lt;/A&gt;.&amp;nbsp; Again, Google Chrome is literally an order of magnitude faster than IE 7 and&amp;nbsp;it looks to me as if Chrome would probably come top of his &lt;A href="http://celtickane.com/webdesign/jsspeedarchive.php" target=_blank&gt;overall performance table&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH:442px;HEIGHT:224px;" src="http://blogs.conchango.com/photos/conchango_bloggers/images/12421/original.aspx" width=442 height=224&gt;&lt;/P&gt;
&lt;P&gt;As a final test, I loaded up the &lt;A href="http://www2.webkit.org/perf/sunspider-0.9/sunspider.html" target=_blank&gt;SunSpider test&lt;/A&gt; from &lt;A href="http://webkit.org/" target=_blank&gt;WebKit&lt;/A&gt;&amp;nbsp;- this is a test which purports to target real-world usage and avoid "useless" micro-benchmarks.&amp;nbsp; I expected Chrome to do well against this, since Google say that Webkit forms a big part of the Chrome browser, but Chrome managed to beat my already high expectations.&amp;nbsp; It came in 16.9 times faster than IE 7 and some of the differences were simply staggering.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH:670px;HEIGHT:937px;" src="http://blogs.conchango.com/photos/conchango_bloggers/images/12419/original.aspx" width=670 height=937&gt;&lt;/P&gt;
&lt;P&gt;Overall, this is quite an amazing first drop of code and I didn't have a single crash or notice any rendering errors.&amp;nbsp; I'll leave others to speculate on exactly what this means for Microsoft's Internet Explorer, but I think it's fair to say that Google have raised the standard of what to expect from a browser quite considerably.&lt;/P&gt;
&lt;P&gt;[EDIT: &lt;A href="http://blogs.conchango.com/rorystreet/default.aspx" target=_blank&gt;Rory&lt;/A&gt; has also &lt;A href="http://blogs.conchango.com/rorystreet/archive/2008/09/02/my-first-look-at-google-chrome.aspx" target=_blank&gt;posted about Google Chrome&lt;/A&gt;.&amp;nbsp; The interesting thing is that he also includes some numbers about memory usage.]&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=12424" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="Google Chrome" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Google+Chrome/default.aspx" /></entry><entry><title>ReSharper 4.0 from JetBrains is released</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2008/06/09/resharper-4-0-from-jetbrains-is-released.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2008/06/09/resharper-4-0-from-jetbrains-is-released.aspx</id><published>2008-06-09T22:17:00Z</published><updated>2008-06-09T22:17:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/ReSharper-40-from-JetBrains-is-released.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The &lt;A href="http://blogs.conchango.com/controlpanel/blogs/httP;/www.jetbrains.com" target=_blank&gt;JetBrains&lt;/A&gt; team have been working hard at getting functionality and bug fixes into version 4.0 of ReSharper.&amp;nbsp; I'm very excited to see that it's finally reached RTM status and now fully supports Visual Studio 2008 and all the C# 3.0 goodness!&amp;nbsp; &lt;A href="http://www.jetbrains.com/resharper/download/index.html" target=_blank&gt;Go get it here&lt;/A&gt;.&amp;nbsp; For those who have been involved in the &lt;A href="http://www.jetbrains.net/confluence/display/ReSharper/ReSharper+4.0+Nightly+Builds" target=_blank&gt;EAP program&lt;/A&gt;, it's actually build 819.&lt;/P&gt;
&lt;P&gt;For those who've never tried R#, I strongly suggest that you take it for a spin.&amp;nbsp; The improvements it brings to productivity are just immense.&amp;nbsp; For the full list of features the JetBrains site &lt;A href="http://www.jetbrains.com/resharper/features/index.html" target=_blank&gt;has all the info&lt;/A&gt;, but here are a couple of my favourite features:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Go To File / Member&lt;IMG style="WIDTH:656px;HEIGHT:374px;" title="Go To File / Type / Member" alt="Go To File / Type / Member" align=right src="http://blogs.conchango.com/photos/conchango_bloggers/images/11406/original.aspx" width=656 height=374&gt;&lt;/STRONG&gt;&lt;BR&gt;This functionality is brilliant at quickly navigating around large solutions.&amp;nbsp; You can type in the full name of the class / method / file that you are after, just the capital letters, you can use wildcards or you can combine all these techniques.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Refactoring Options&lt;/STRONG&gt;&lt;BR&gt;Yes I know that Visual Studio has included some refactoring functionality for a while now, but this one of ReSharper primary strengths.&amp;nbsp; It includes options such as:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV&gt;Rename class / method / variable / parameter / field / property (optionally searches within comments and strings)&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Change signature&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Extract / inline a method&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Extract interface / superclass&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Push members up / pull members down&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Introduce parameter&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Introduce field&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Introduce variable (I esp like the way it detects multiple occurrences of an expression of offers to replace them all)&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;Convert anonymous delegates to / from lamdas&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV&gt;Set field values from constructor arguments&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;There's so many of these - these are just the ones I can think of right now.&amp;nbsp; In fact, there are so many that I always keep a copy of the &lt;A href="http://www.jetbrains.com/resharper/docs/ReSharper40DefaultKeymap.pdf" target=_blank&gt;ReSharper keyboard mappings&lt;/A&gt; on my desk.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Coding in Reverse&lt;/STRONG&gt;&lt;BR&gt;Undoutebdly the most powerful feature available within ReSharper, JetBrains picked it out as &lt;A href="http://resharper.blogspot.com/2007/05/jedi-way-coding-in-reverse.html" target=_blank&gt;the primary skill of the ReSharper Jedi&lt;/A&gt;.&amp;nbsp; This is a technique where you use variables / methods / classes &lt;STRONG&gt;&lt;EM&gt;before they exist&lt;/EM&gt;&lt;/STRONG&gt;.&amp;nbsp; ReSharper will then infer their definition from your usage and allow you to actualize them with a couple of keystrokes.&amp;nbsp; It's immensely powerful, but it's really &lt;A href="http://www.jetbrains.com/resharper/documentation/presentation/codingSession/CodingSession.wmv" target=_blank&gt;got to be seen to be fully appreciated&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;And More&lt;BR&gt;&lt;/STRONG&gt;I strongly ReSharper to all developers who want to improve their productivity ... which should be all developers.&amp;nbsp; I also strongly suggest that you take some time out to learn the featureset and some of the options available within ReSharper.&amp;nbsp; &lt;A href="http://blog.excastle.com/" target=_blank&gt;Joe White's&lt;/A&gt; blog series &lt;A href="http://blog.excastle.com/2007/01/31/blog-event-the-31-days-of-resharper" target=_blank&gt;The 31 Days of ReSharper&lt;/A&gt; is a great place to start this journey.&amp;nbsp; Just be warned that you &lt;A href="http://closed-loop.blogspot.com/2007/08/resharper-to-next-level.html" target=_blank&gt;might&lt;/A&gt; &lt;A href="http://www.peterprovost.org/archive/2005/03/31/3108.aspx" target=_blank&gt;get&lt;/A&gt;&amp;nbsp;&lt;A href="http://www.ayende.com/Blog/archive/2006/03/25/7770.aspx" target=_blank&gt;seriously&lt;/A&gt; &lt;A href="http://andrewconnell.com/blog/archive/2005/03/25/1042.aspx" target=_blank&gt;hooked&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=11405" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="Development practices" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Development+practices/default.aspx" /><category term="Engineering practices" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Engineering+practices/default.aspx" /><category term="Visual Studio" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Visual+Studio/default.aspx" /><category term="C#" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/C_2300_/default.aspx" /><category term=".Net" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/.Net/default.aspx" /></entry><entry><title>Design-time perf improvements in Visual Studio 2008</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2008/01/28/Design_2D00_time-perf-improvements-in-Visual-Studio-2008.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2008/01/28/Design_2D00_time-perf-improvements-in-Visual-Studio-2008.aspx</id><published>2008-01-28T16:00:00Z</published><updated>2008-01-28T16:00:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/Design-time-perf-improvements-in-Visual-Studio-2008.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Some metrics that we captured on my project: (I think the numbers speak for themselves)&lt;/P&gt;
&lt;P&gt;
&lt;TABLE style="WIDTH:350pt;BORDER-COLLAPSE:collapse;" border=0 cellSpacing=0 cellPadding=0 width=465&gt;




&lt;TBODY&gt;
&lt;TR style="HEIGHT:15pt;"&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;WIDTH:142pt;FONT-FAMILY:Arial;HEIGHT:15pt;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:black 0.5pt solid;FONT-WEIGHT:700;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl65 class="xl65"&gt;Operation&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;WIDTH:52pt;FONT-FAMILY:Arial;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:black 0.5pt solid;FONT-WEIGHT:700;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl69 class="xl69"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; VS 2005&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;WIDTH:52pt;FONT-FAMILY:Arial;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:black 0.5pt solid;FONT-WEIGHT:700;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl69 class="xl69"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;VS 2008&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;WIDTH:104pt;FONT-FAMILY:Arial;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:black 0.5pt solid;FONT-WEIGHT:700;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl69 class="xl69"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %&amp;nbsp;Improvement&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="HEIGHT:15pt;"&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;HEIGHT:15pt;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl66 class="xl66"&gt;Start the IDE&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;00:30&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;00:09&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl68 align=right class="xl68"&gt;70%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="HEIGHT:15pt;"&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;HEIGHT:15pt;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl66 class="xl66"&gt;Load solution&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl67 align=right class="xl67"&gt;03:45&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl67 align=right class="xl67"&gt;00:45&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl68 align=right class="xl68"&gt;80%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="HEIGHT:15pt;"&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;HEIGHT:15pt;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl66 class="xl66"&gt;Get Latest (no changes)&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;00:13&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;00:05&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl68 align=right class="xl68"&gt;62%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="HEIGHT:15pt;"&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;HEIGHT:15pt;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl66 class="xl66"&gt;Rebuild solution&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl67 align=right class="xl67"&gt;02:21&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl67 align=right class="xl67"&gt;01:58&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;BORDER-TOP:#f0f0f0;BORDER-RIGHT:#f0f0f0;" class=xl68 align=right class="xl68"&gt;16%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="HEIGHT:15pt;"&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;HEIGHT:15pt;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl66 class="xl66"&gt;Run all tests&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;05:29&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;03:44&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:#f0f0f0;BORDER-LEFT:#f0f0f0;FONT-FAMILY:Arial;BACKGROUND:#d8d8d8;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl68 align=right class="xl68"&gt;32%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="HEIGHT:15pt;"&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;FONT-FAMILY:Arial;HEIGHT:15pt;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl66 class="xl66"&gt;Start the application&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;FONT-FAMILY:Arial;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;00:19&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;FONT-FAMILY:Arial;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl67 align=right class="xl67"&gt;00:18&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM:black 0.5pt solid;BORDER-LEFT:#f0f0f0;BACKGROUND-COLOR:transparent;FONT-FAMILY:Arial;COLOR:black;FONT-SIZE:10pt;BORDER-TOP:#f0f0f0;FONT-WEIGHT:400;BORDER-RIGHT:#f0f0f0;TEXT-DECORATION:none;text-underline-style:none;text-line-through:none;" class=xl68 align=right class="xl68"&gt;5%&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;FYI our solution has 33 projects in it (including a database project, a web&amp;nbsp;application project, numerous DLLs, an EXE and a WiX installer) and there are almost 1,600 unit and integration tests.&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=9589" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="Development practices" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Development+practices/default.aspx" /><category term="Engineering practices" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Engineering+practices/default.aspx" /><category term="Visual Studio" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Visual+Studio/default.aspx" /></entry><entry><title>Altnetconf UK: First round of registration is closed</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2008/01/03/Altnetconf-UK_3A00_-First-round-of-registration-is-closed.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2008/01/03/Altnetconf-UK_3A00_-First-round-of-registration-is-closed.aspx</id><published>2008-01-03T22:20:00Z</published><updated>2008-01-03T22:20:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/Altnetconf-UK-First-round-of-registration-is-closed.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;Registration to the first &lt;A href="http://www.altnetpedia.com/" target=_blank&gt;ALT.Net&lt;/A&gt; UK conference was recently &lt;A href="http://consultingblogs.emc.com/michelleflynn/archive/2008/01/02/Conchango-hosts-Alt.Net.UK-Conference.aspx" target=_blank&gt;announced by Michelle&lt;/A&gt;.&amp;nbsp; Unfortunately it's already full, so if you're name isn't on &lt;A href="http://www.altnetuk.com/Participants.aspx" target=_blank&gt;the participants list&lt;/A&gt; of people who have registered then I'm afraid you're a bit late for this round.&amp;nbsp; Ian Cooper says that &lt;A href="http://codebetter.com/blogs/ian_cooper/archive/2008/01/03/altnetconf-uk-first-release-of-tickets-sold-out.aspx" target=_blank&gt;another batch of registrations will&amp;nbsp;open soon&lt;/A&gt;, so those who watch closely may still be able to attend.&amp;nbsp; I'm pleased to announce that I will be attending the conference as a Conchango representative.&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=9415" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="ALT.Net" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/ALT.Net/default.aspx" /><category term="altnetconf" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/altnetconf/default.aspx" /></entry><entry><title>Exploring quality in software architecture</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2007/10/19/Exploring-quality-in-software-architecture.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2007/10/19/Exploring-quality-in-software-architecture.aspx</id><published>2007-10-18T23:39:00Z</published><updated>2007-10-18T23:39:00Z</updated><content type="html">&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;
&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/Exploring-quality-in-software-architecture.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;Strength, utility and beauty.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Here we will be exploring a number of the traditional “ilities” of software architecture and seeing how they can be related to these three architectural qualities.&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;These three qualities have been around for quite a while, under their Latin names of firmitas, utilitas and venustas, and were first written about by &lt;A href="http://en.wikipedia.org/wiki/Vitruvius" target=_blank&gt;Vitruvius&lt;/A&gt;.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Now architecture is always created with the intention of supporting something, e.g. an application (in the case of application architecture) or a business (in the case of enterprise architecture).&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;For brevity, I’ll refer to “the thing which the architecture supports” as “the system”, although I believe that my points here relate to all types of software architecture.&lt;/SPAN&gt;&lt;/P&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';"&gt;Utilitas, or Utility: Functional and &lt;/SPAN&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';"&gt;behavioural&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';"&gt; &lt;SPAN&gt;aspects of the architecture&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;The architecture needs to guarantee that the system can perform operations in a certain manner.&amp;nbsp; Architectural aspects which achieve this are:&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Availability – &lt;EM&gt;expected&lt;/EM&gt; &lt;EM&gt;levels of uptime that the architecture can provide&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Auditability – &lt;EM&gt;keeping a log of changes and operations within the system.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Correctness and verifiability – &lt;EM&gt;sometimes operations within the system can be externally verified.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The architecture needs to support and pass such verification.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Environmental compatibility – &lt;EM&gt;the architecture needs to fit into its environment, e.g. there may be a high latency network which needs to be considered&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Performance – &lt;EM&gt;how quickly operations can be performed&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Security and confidentiality – &lt;EM&gt;authentication and &lt;/EM&gt;&lt;/SPAN&gt;&lt;EM&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;authorisation&lt;/SPAN&gt;&lt;/EM&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 10pt 36pt;" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Transactionality – &lt;EM&gt;the architecture needs to ensure that operations are atomic&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;A person can only really be called an architect if they can design an architecture that works, i.e. displays these aspects.&lt;/SPAN&gt;&lt;/P&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';"&gt;&lt;FONT size=3&gt;Firmitas, or Strength: Non-functional aspects of the architecture&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;In addition to supporting the operations of the system, there are a number of further considerations for architecture:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Adaptability – &lt;EM&gt;how well the architecture can cope to evolving situations without being changed&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Efficiency – &lt;EM&gt;how well does the architecture use its resources such as CPU, memory, bandwidth, etc&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Extensibility – &lt;EM&gt;how easily can the architecture be extended and changed&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Maintainability – &lt;EM&gt;this is really just a combination of extensibility and understandability.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;If an architecture is easy to understand and easy to change, then it is easy to maintain.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Recoverability – &lt;EM&gt;is it possible to reconstitute the state of the system after a disaster&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Reliability – &lt;EM&gt;how stable is the architecture under normal circumstances&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Resiliance – &lt;EM&gt;how stable is the architecture under abnormal circumstances&lt;/EM&gt; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Scalability – &lt;EM&gt;can the throughput of the system be increased without requiring changes&lt;/EM&gt; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 10pt 36pt;" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Understandability – &lt;EM&gt;how easy is it to comprehend the architecture&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Really good architects manage to incorporate these aspects into architecture they design.&lt;/SPAN&gt;&lt;/P&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';"&gt;&lt;FONT size=3&gt;Venustas, or Beauty: Aesthetic aspects of the architecture&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Beauty, as a quality, is practically impossible to define objectively.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;“Beauty is in the eye of the beholder”, as the saying goes.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;However, you do know beauty when you see it.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Here are some points which I think contribute to making architecture beautiful:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Conceptual integrity – &lt;EM&gt;sometimes called the principle of least surprise, there should be an underlying theme or vision that unifies the design of the architecture at all levels&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 0pt 36pt;" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Elegance – &lt;EM&gt;closely related to simplicity, elegance implies a certain understated effortlessness&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT:-18pt;MARGIN:0cm 0cm 10pt 36pt;" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:Symbol;FONT-SIZE:10pt;"&gt;&lt;SPAN&gt;·&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;Simplicity – &lt;EM&gt;an architecture should be as simple as possible, but not simplistic&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;An architect that can incorporate these aspects into a design that also displays utility and strength, is really one of the greats.&lt;/SPAN&gt;&lt;/P&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;STRONG&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';"&gt;&lt;FONT size=3&gt;And so what?&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/STRONG&gt;
&lt;P style="MARGIN:0cm 0cm 10pt;" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;And so we have a bit of a framework for inspecting the quality of architecture.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;I don’t regard all of these aspects as quantitative, but at least we can discuss architecture in qualitative terms.&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT:115%;FONT-FAMILY:'Arial','sans-serif';FONT-SIZE:10pt;"&gt;In my next post, I’ll be discussing some of the specific considerations of&amp;nbsp;iterative development of software and how these points here should influence that process.&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=8821" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="Technical Architect Role" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Technical+Architect+Role/default.aspx" /><category term="Architecture" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Architecture/default.aspx" /></entry><entry><title>What makes a good (software) architecture</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2007/09/11/What-makes-a-good-_2800_software_2900_-architecture.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2007/09/11/What-makes-a-good-_2800_software_2900_-architecture.aspx</id><published>2007-09-11T22:30:00Z</published><updated>2007-09-11T22:30:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/What-makes-a-good-(software)-architecture.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Lately I've been investigating software architecture with regard to how it can impact on an agile development project.&amp;nbsp;I recently&amp;nbsp;read&amp;nbsp;(&lt;A title="Do we need software architects? 10 reasons why not." href="http://softwarecreation.org/2007/do-we-need-software-architects-10-reasons-why-not/" target=_blank&gt;here&lt;/A&gt;) a&amp;nbsp;very short list that resonated really powerfully with me and describes key architectural virtues (explanations are mine):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Strength&lt;/STRONG&gt; - reliable, secure, resilient to change&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Utility&lt;/STRONG&gt; - must deliver&amp;nbsp;either business value or (more likely) developer&amp;nbsp;productivity&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Beauty&lt;/STRONG&gt; - easy to understand and communicate, clean design, minimal&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;It turns out that these ideas &lt;A title="Vitruvius, an architect in the Roman Empire" href="http://en.wikipedia.org/wiki/Vitruvius" target=_blank&gt;have been around for quite a while&lt;/A&gt;, under their Latin names of &lt;EM&gt;firmitas&lt;/EM&gt;, &lt;EM&gt;utilitas&lt;/EM&gt; and &lt;EM&gt;venustas&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;I hope to produce a series of blog posts detailing my thoughts and expanding on some of these points, including why I think this question is especially relevant to iterative development.&lt;/P&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=8434" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="Technical Architect Role" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Technical+Architect+Role/default.aspx" /><category term="Architecture" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Architecture/default.aspx" /></entry><entry><title>SAPI: Speech synthesis on Vista</title><link rel="alternate" type="text/html" href="http://consultingblogs.emc.com/johnrayner/archive/2007/05/10/SAPI_3A00_-Speech-synthesis-on-Vista.aspx" /><id>http://consultingblogs.emc.com/johnrayner/archive/2007/05/10/SAPI_3A00_-Speech-synthesis-on-Vista.aspx</id><published>2007-05-10T00:11:00Z</published><updated>2007-05-10T00:11:00Z</updated><content type="html">&lt;P&gt;EDIT: I became a &lt;A href="http://www.sharpfellows.com/"&gt;SharpFellow&lt;/A&gt; and so this &lt;A href="http://www.sharpfellows.com/post/SAPI-Speech-synthesis-on-Vista.aspx"&gt;blog post has moved&lt;/A&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The &lt;A href="http://www.visitmix.com/" target=_blank&gt;MIX07 Keynote&lt;/A&gt; includes a brief screen&amp;nbsp;capture&amp;nbsp;from the &lt;A href="http://consultingblogs.emc.com/ciaranhanway/archive/2007/02/21/Conchango_2C00_-Daily-Mail-and-Vista.aspx" target=_blank&gt;Daily Mail eReader&lt;/A&gt;&amp;nbsp;and reminded me that I had meant to blog about the speech synthesis portion of the app.&amp;nbsp; It's something which many users might not have seen, because it's only available on Windows Vista.&amp;nbsp; Vista includes the&amp;nbsp;Speech API (SAPI) version 5.3 which provides a text-to-speech (TTS) engine which is greatly superior to SAPI 5.2 which shipped with Windows XP.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH:309px;HEIGHT:412px;" title="Speak the News with the Daily Mail eReader" hspace=20 alt="Speak the News with the Daily Mail eReader" align=right src="http://consultingblogs.emc.com/photos/conchango_bloggers/images/6932/original.aspx" width=309 height=412&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;How it looks&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The way the UI works is pretty straightforward - it's meant to mimic an autocue.&amp;nbsp; So a user will trigger the functionality and the window you see on the right will appear.&amp;nbsp; As the user's computer begins speaking the news story, the text will slowly scroll up.&amp;nbsp; The word currently being spoken will always be bold and will always appear in the letterbox.&lt;/P&gt;
&lt;P&gt;I'm presonally a bit tickled that this bit of UI made it into Ray Ozzie's keynote presentation (even if it was only for about a quarter of a second) because I developed this part of the eReader and wrote this UI.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Getting SAPI to produce speech&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The TTS functionality is actually quite easy to kick off.&amp;nbsp; All it takes is a call to the appropriate function, passing in a string holding the text to be read, and SAPI will begin to speak.&amp;nbsp; Specifically, .Net 3.0&amp;nbsp;provides a System.Speech assembly which does all the hard work for you.&amp;nbsp; This assembly includes the class &lt;FONT face="Courier New,serif"&gt;System.Speech.Synthesis.&lt;SPAN style="COLOR:teal;"&gt;SpeechSynthesizer&lt;/SPAN&gt;&lt;/FONT&gt; which has a method &lt;FONT face="Courier New,serif"&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; Speak(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; textToSpeak)&lt;/FONT&gt;&lt;/FONT&gt;.&amp;nbsp; This is easy to use if all you want is text-to-speech.&lt;/P&gt;
&lt;P&gt;The problem is that this is a synchronous call.&amp;nbsp; So the call will block until the speech rendering is complete.&amp;nbsp; To get around this, the &lt;SPAN style="COLOR:teal;"&gt;&lt;FONT face="Courier New"&gt;SpeechSynthesizer&lt;/FONT&gt;&lt;/SPAN&gt; class also includes a method &lt;FONT face="Courier New"&gt;SpeakAsync&lt;/FONT&gt;.&amp;nbsp; This does pretty much what you'd expect and runs the TTS activity on a background thread.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Getting updated with TTS progress&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now the &lt;SPAN style="COLOR:teal;"&gt;&lt;FONT face="Courier New"&gt;SpeechSynthesizer&lt;/FONT&gt;&lt;/SPAN&gt; class even provides &lt;A href="http://msdn2.microsoft.com/en-us/library/system.speech.synthesis.speechsynthesizer_events.aspx" target=_blank&gt;some helpful events&lt;/A&gt; relating to the progress of the speech rendering.&amp;nbsp; However, it turns out that the SAPI libraries regard these events as sort of incidental to their main job - i.e. they will raise the events when they can.&amp;nbsp; So there is every possibility that these events will occur some time after the actual speech rendering of a word (or phoneme, etc) has started.&amp;nbsp; The SAPI library also seems to stop raising the events altogether, if the event handlers are consuming too much time.&amp;nbsp; This was probably a design decision made by Microsoft that the quality of the speech shouldn't be affected by calls to user code.&lt;/P&gt;
&lt;P&gt;This last point means that you need to be very careful how you write your event handlers.&amp;nbsp; I suspect that a fair amount of time is consumed with the transition from the unmanaged SAPI libraries back into the System.Speech assembly, which doesn't leave much time for your C# code to do anything useful.&amp;nbsp; It certainly doesn't leave enough time to update a XAML UI.&amp;nbsp; The initial approach I used would update the UI with about 2 or 3 words and then UI updating would cease altogether.&lt;/P&gt;
&lt;P&gt;The solution was (a) to be very, very careful to write efficient code; (b) use the Output window for debug info rather than trying to break into the running code; and (c) make good use of asynchronous delegates.&amp;nbsp; The SAPI events are called on a background thread, which means that a &lt;FONT face="Courier New"&gt;Dispatcher.Invoke&lt;/FONT&gt; call is needed before code can update the UI at all.&amp;nbsp; So the simplest solution was to replace this with a &lt;FONT face="Courier New"&gt;Dispatcher.BeginInvoke&lt;/FONT&gt; call which then updated the UI asynchronously to the event handler.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Constructing the UI&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;It took a little bit of trial and error to get a XAML UI that could efficiently update without continually doing a lot of layout work.&amp;nbsp; Ironically, the grey letterbox with its opacity and the opacity gradient of the textual content were the easy bits!&amp;nbsp; And getting a thick window border of Vista glass was also pretty trivial.&amp;nbsp;The part which took some effort was working out that to display the content I needed to use a &lt;FONT face="Courier New"&gt;ScrollViewer&lt;/FONT&gt; control with three separate &lt;FONT face="Courier New"&gt;Run&lt;/FONT&gt; elements - one for the text which had been read, one for the text being read and one for the text which is still to be read.&amp;nbsp; The updates from the TTS engine can then simply be translated into shuffling characters between the various &lt;FONT face="Courier New"&gt;Run&lt;/FONT&gt; elements.&lt;/P&gt;
&lt;P&gt;Getting the highlighted word to stay in the letterbox also took some trial and error.&amp;nbsp; The solution lay in the following line of code:&lt;/P&gt;
&lt;DIV style="FONT-FAMILY:Courier New;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:teal;"&gt;Rect&lt;/SPAN&gt; screenPosition = CurrentlyReadingRun.ContentStart.GetCharacterRect(&lt;SPAN style="COLOR:teal;"&gt;LogicalDirection&lt;/SPAN&gt;.Forward);&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;This gave me&amp;nbsp;the screen co-ordinates of the currently bold word, which I then used like so:&lt;/P&gt;
&lt;DIV style="FONT-FAMILY:Courier New;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;P style="MARGIN:0px;"&gt;_scrollViewer.ScrollToVerticalOffset(screenPosition.Top + _scrollViewer.VerticalOffset - _paddingHeight);&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=6933" width="1" height="1"&gt;</content><author><name>john.rayner</name><uri>http://consultingblogs.emc.com/members/john.rayner.aspx</uri></author><category term="WPF" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/WPF/default.aspx" /><category term="SAPI" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/SAPI/default.aspx" /><category term="Vista" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/Vista/default.aspx" /><category term="TTS" scheme="http://consultingblogs.emc.com/johnrayner/archive/tags/TTS/default.aspx" /></entry></feed>
