<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Christopher Bennage</title><link>http://devlicious.com/blogs/christopher_bennage/default.aspx</link><description>&lt;div&gt;Our &lt;a href="http://www.amazon.com/gp/product/0672329859?&amp;amp;camp=212361&amp;amp;linkCode=wey&amp;amp;tag=bluspiconinc-20&amp;amp;creative=380733"&gt;WPF book&lt;/a&gt; is now available!&lt;/div&gt;</description><dc:language>en</dc:language><generator>CommunityServer 2007 (Build: 20416.853)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/ChristopherBennage" type="application/rss+xml" /><item><title>Shared Hosting &amp; The Bleeding Edge</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/402919807/shared-hosting-amp-the-bleeding-edge.aspx</link><pubDate>Thu, 25 Sep 2008 15:58:56 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:42441</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>10</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=42441</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/09/25/shared-hosting-amp-the-bleeding-edge.aspx#comments</comments><description>&lt;p&gt;So we&amp;#39;ve been working on a web project for a friend&amp;#39;s startup company (I don&amp;#39;t like doing work for my friends, but that&amp;#39;s a different matter). Since he has no technological preference and since we are such bleeding edge kinda guys (&lt;em&gt;the Achilles&amp;#39; Heel of ALT.NET?&lt;/em&gt;), we decided to build the site with the following: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.codeplex.com/aspnet/Wiki/View.aspx?title=MVC&amp;amp;referringTitle=Home" target="_blank"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="212" alt="Careful, don&amp;#39;t cut yourself." src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/SharedHostingTheBleedingEdge_94C8/iStock_000005472751XSmall_3.jpg" width="320" align="right" border="0" /&gt;ASP.NET MVC&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.codeplex.com/MVCContrib" target="_blank"&gt;MVC Contrib&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.castleproject.org/container/index.html" target="_blank"&gt;Castle Windsor&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.hibernate.org/343.html" target="_blank"&gt;NHibernate&lt;/a&gt;  &lt;li&gt;&lt;a href="http://code.google.com/p/fluent-nhibernate/" target="_blank"&gt;Fluent NHibernate&lt;/a&gt; (this rocks) &lt;li&gt;NHibernate.Linq (part of &lt;a href="http://sourceforge.net/projects/nhcontrib/" target="_blank"&gt;NHibernate Contrib&lt;/a&gt;) (this rocks as well)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Castle and NHibernate (as you likely know) are mature products. So in keeping with our bleeding theme, we decided to use the trunk for these instead of the most recent release.&lt;/p&gt; &lt;p&gt;Despite all the blood, the development process was pretty smooth. I had a minor learning curve with MVC and a slightly less minor curve with some of the other bits, but all in all, it went well. (I am omitting a lengthy struggle writing a query because it is embarrassing how my &lt;strike&gt;SQL&lt;/strike&gt; query writing skills have atrophied.)&lt;/p&gt; &lt;p&gt;Ok, well, the time to deploy to the production site comes. Remember I said that this was a friend&amp;#39;s startup and there is little money to go around, so the production site is going be hosted at &lt;a href="http://www.crystaltech.com/" target="_blank"&gt;CrystalTech&lt;/a&gt;. I deploy the site, and -- nothing. It doesn&amp;#39;t work in the shared hosting environment.&lt;/p&gt; &lt;p&gt;We&amp;#39;re not used to having our applications run in a shared environment; most of our clients have dedicated hardware. If I had spent any amount of time thinking about it, I would have realized the forthcoming pain.&lt;/p&gt; &lt;p&gt;Unfortunately, I will not be able to present you with a step-by-step way to &lt;span&gt;make the pieces fit&lt;/span&gt;, the pain has blurred my memory. However, I will give you a general outline that I believe you will find helpful.&lt;/p&gt; &lt;h3&gt;Windows 2008, IIS 7, and Routing&lt;/h3&gt; &lt;p&gt;Most shared hosting environments are not running on Windows 2008 and that means no IIS 7. If you are using routing with MVC to get your Rails-style urls (and who isn&amp;#39;t?), routing is not going to work without IIS7. You can still get your MVC app to run, but&amp;nbsp; you have to call the view explicitly (something like \root\views\home\index.aspx).&lt;/p&gt; &lt;p&gt;I didn&amp;#39;t really think about this because the web server built-in to Visual Studio handles the routing correctly. (Even though I&amp;#39;ve run into a similar problem using MonoRail years ago).&lt;/p&gt; &lt;p&gt;CrystalTech (at the time of writing) only has &lt;em&gt;one server&lt;/em&gt; running IIS 7 and only &lt;em&gt;one plan&lt;/em&gt; available for that server. I didn&amp;#39;t think about this when my buddy signed up for the account, and I had to ask them to relocated the site to the 2008 server.&lt;/p&gt; &lt;p&gt;&lt;a href="http://anglicangeek.com/" target="_blank"&gt;Drew&lt;/a&gt; suggested that I ask the host to do a &lt;a href="http://professionalaspnet.com/archive/2007/07/27/Configure-IIS-for-Wildcard-Extensions-in-ASP.NET.aspx" target="_blank"&gt;wildcard mapping&lt;/a&gt; instead of moving the site over to IIS 7. This would work, but CrystalTech won&amp;#39;t to do it. I had actually tried to get them to do this a while back when I first started learning MonoRail.&lt;/p&gt; &lt;h3&gt;Partial Trust&lt;/h3&gt; &lt;p&gt;Shared hosting environment have to restrict security. If not, you could write your application to&lt;em&gt; do bad things&lt;/em&gt; to their server. Limited trust can prevent you from using lots nifty tricks that you may be used to. For example, application running under &lt;a href="http://msdn.microsoft.com/en-us/library/ms998341.aspx" target="_blank"&gt;Medium Trust&lt;/a&gt; cannot use reflection. Luckily, many hosts don&amp;#39;t lock you down that tight.&lt;/p&gt; &lt;p&gt;The real problem is that by default &lt;a href="http://msdn.microsoft.com/en-us/library/wd40t7ad.aspx" target="_blank"&gt;strongly named assemblies&lt;/a&gt; cannot be called by assemblies executing under less than Full Trust. For example, the Castle assemblies are strongly-named and thus they are not callable by your application in most typical shared environments. &lt;/p&gt; &lt;p&gt;The solution, if you have access to the source, is to use &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.allowpartiallytrustedcallersattribute.aspx" target="_blank"&gt;AllowPartiallyTrustedCallersAttribute&lt;/a&gt;. Just slap that bad boy into your AssemblyInfo.cs and your strongly named assembly can then be called.&lt;/p&gt; &lt;p&gt;Fortunately, Castle makes this easy. You execute the build script with something like this:&lt;/p&gt;&lt;pre&gt;nant -t:net-2.0 -D:assembly.allow-partially-trusted-callers=true release&lt;/pre&gt;
&lt;p&gt;I believe NHibernate has the attribute by default, but any other assembly that is strongly-named will need this attribute, and then you will want to recompile all the dependencies after adding the attribute.&lt;/p&gt;
&lt;h3&gt;The Nutshell&lt;/h3&gt;
&lt;p&gt;If you have to use a shared hosting environment,&lt;em&gt; talk to the host&lt;/em&gt;. Tell them what you are planning on doing. Secondly, visit the forums for the host and search them to see if someone is doing what you plan to do.&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=42441" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/402919807" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Castle+Project/default.aspx">Castle Project</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ALT.NET/default.aspx">ALT.NET</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/NHibernate/default.aspx">NHibernate</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/MVC/default.aspx">MVC</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/09/25/shared-hosting-amp-the-bleeding-edge.aspx</feedburner:origLink></item><item><title>Building a WPF Application: Part 3</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/369649866/building-a-wpf-application-part-3.aspx</link><pubDate>Wed, 20 Aug 2008 04:28:57 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41939</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>8</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41939</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/20/building-a-wpf-application-part-3.aspx#comments</comments><description>&lt;ul&gt; &lt;li&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/07/20/build-a-wpf-application-part-0.aspx" target="_blank"&gt;Part 0&lt;/a&gt;  &lt;li&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/07/22/building-a-wpf-application-part-1.aspx" target="_blank"&gt;Part 1&lt;/a&gt;&amp;nbsp; &lt;li&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/08/16/building-a-wpf-application-part-2.aspx" target="_blank"&gt;Part 2&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Application Architecture&lt;/h3&gt; &lt;p&gt;I&amp;#39;m going to back up a bit discuss my overall approach to structuring this WPF project. So far the solution consists of four projects:&lt;/p&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="159" alt="solution" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/BuildingaWPFApplicationPart4_150D4/solution_3.png" width="256" align="right" border="0" /&gt;  &lt;ul&gt; &lt;li&gt;&lt;strong&gt;ChumChase&lt;/strong&gt; is the actual WPF project.  &lt;li&gt;&lt;strong&gt;FriendFeed&lt;/strong&gt; is the official .NET api I downloaded from &lt;a href="http://code.google.com/p/friendfeed-api/downloads/list" target="_blank"&gt;here&lt;/a&gt;, and patched so that it would compile. :-)  &lt;li&gt;&lt;strong&gt;IntegrationTests&lt;/strong&gt; is for testing the bits of the application that interact with the FriendFeed api.&amp;nbsp; I separated this out because it is much slower to run than my &lt;strong&gt;Specifications&lt;/strong&gt; tests, and goes beyond the trust boundary of the app.  &lt;li&gt;&lt;strong&gt;Specifications&lt;/strong&gt; is the bulk of the unit tests for the project. I&amp;#39;m influenced by the whole &lt;a title="Does really know what BDD is? Does anybody really care?" href="http://en.wikipedia.org/wiki/Behavior_driven_development" target="_blank"&gt;BDD&lt;/a&gt; approach, and I like to think of my unit tests as &lt;em&gt;executable technical specifications&lt;/em&gt;. &lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Project Structure&lt;/h3&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/BuildingaWPFApplicationPart4_150D4/project_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="357" alt="project" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/BuildingaWPFApplicationPart4_150D4/project_thumb.png" width="238" align="right" border="0" /&gt;&lt;/a&gt;&lt;/strong&gt;In the main project you&amp;#39;ll find the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Presenters&lt;/strong&gt; - This folder contains the presenter classes. I usually name these classes with the suffix &amp;quot;Presenter, though that&amp;#39;s a bit of a hang over from other frameworks (MonoRail, RoR). This directory is where I have the HomePresenter class we&amp;#39;ve been discussing.  &lt;li&gt;&lt;strong&gt;Views&lt;/strong&gt; - These are usually user controls or some derivative thereof. I name them to correspond to their presenter. So you would expect, since we have HomePresenter, to find HomeView.xaml. (Actually, I goofed and the current source has the view named HomeFeedView.xaml).  &lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; - This is the object model that represents the &amp;quot;business problem&amp;quot; I&amp;#39;m trying to solve. In this case it happens to mirror the actual api quite a bit.  &lt;li&gt;&lt;strong&gt;Repositories&lt;/strong&gt; - Here I am influenced by Eric Evans&amp;#39; &lt;a title="Sams Teach Yourself WPF in 24 Hours -- preorder yours today! :-)" href="http://www.amazon.com/Sams-Teach-Yourself-WPF-Hours/dp/0672329859" target="_blank"&gt;book&lt;/a&gt; on Domain-Driven Design. Repositories are classes that allow me to access/persist data in a way that makes sense to my business domain. It&amp;#39;s also a place where I can hook in orthogonal concerns such as logging, caching, or security. Repositories differ from the traditional data access layer in that there is an emphasis on the domain model (as opposed to following the semantics of a relation database).  &lt;li&gt;&lt;strong&gt;Services&lt;/strong&gt; - These are supporting classes. They are not necessarily part of the business or problem domain. A classic example is an SMTP provider. Classes in your model or presenters might utilize these.  &lt;li&gt;&lt;strong&gt;Framework&lt;/strong&gt; - These support the framework of application, but don&amp;#39;t have anything to do with the business concern. If we need to create a base class for views, we&amp;#39;d put it here. Currently, I have a class there that is going to assist us with binding to commands. This is code that could likely be pushed out to a reusable library.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Aside from these folders you will also find:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;App.xaml&lt;/strong&gt; - This is the starting point for the application. It will kick off our Windsor configuration, and launch the first window for the application. Eventually, we&amp;#39;ll include some application-wide resources in the xaml, primarily for styling.  &lt;li&gt;&lt;strong&gt;Shell.xaml&lt;/strong&gt; - This is the main window of the application. I call it Shell, because there is very little to its UI. It&amp;#39;s content is bound to view of our current presenter. This class might have some logic in it&amp;#39;s code-behind if we need to do some things like managing a set of tabs. It also provides the overall layout of the application.  &lt;li&gt;&lt;strong&gt;ApplicationController&lt;/strong&gt; - I briefly mentioned this in the last post. Honestly, I&amp;#39;ve waffled a bit on what to call it. It&amp;#39;s responsibility is to coordinate the presenters for the application. For example, if presenter X needs to load presenter Y it passes that request to the application controller. In this, it also handles some statefulness for the overall application. This will become more clear as we begin to work with the class.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;What&amp;#39;s Not Here Yet&lt;/h3&gt; &lt;p&gt;There are several other things that usually appear in my projects. I often end up with a base class for test fixtures, though I think the new Rhino.Mocks features might affect that. However, the big piece that&amp;#39;s missing is the folders and files related to organizing the XAML.&lt;/p&gt; &lt;p&gt;It&amp;#39;s common for me to have the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Colors &amp;amp; Brushes&lt;/strong&gt; - I typically have a&amp;nbsp; resource dictionary dedicated to defining the colors and brushes used in the application.  &lt;li&gt;&lt;strong&gt;Default Styles&lt;/strong&gt; - When I provide a completely custom style for an application, I&amp;#39;ll have a resource dictionary that defines all of the default styles for controls. It useful to note that I avoid putting control templates inline in this dictionary.  &lt;li&gt;&lt;strong&gt;Control Templates folder&lt;/strong&gt; - In this folder, I will have a file for each control template in the application. I&amp;#39;ll usually have a &amp;quot;manifest&amp;quot; resource dictionary where I merge in all of the individual templates. This helps to keep the structure clean in other areas. These are the control templates that are referenced in my default styles dictionary.  &lt;li&gt;&lt;strong&gt;Data Templates folder&lt;/strong&gt; - Inside the Views directory, I will have a sub-folder for data templates. Data templates really are views.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;What Happens at Runtime?&lt;/h3&gt; &lt;p&gt;A synopsis of what happens at runtime, well, what &lt;em&gt;will&lt;/em&gt; happen once we&amp;#39;ve finished:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;App.xaml starts off.&lt;/li&gt; &lt;li&gt;In its constructor, we configure our &lt;em&gt;container&lt;/em&gt;, which in this case is Windsor.&amp;nbsp; The container is told how to resolve resources, such as where do I find the actual implementation of IFriendFeedProxy.&lt;/li&gt; &lt;li&gt;Still in the constructor, we then request an instance of &lt;strong&gt;IApplicationController&lt;/strong&gt;, and call &lt;strong&gt;StartApplication()&lt;/strong&gt;.&amp;nbsp; Note that we don&amp;#39;t set the &lt;strong&gt;StartupUri&lt;/strong&gt; in the XAML for App.&lt;/li&gt; &lt;li&gt;&lt;strong&gt;StartApplication()&lt;/strong&gt; might handle some things like loading up user preferences, but mostly it will initialize and open Shell.xaml. &lt;/li&gt; &lt;li&gt;Somewhere around here we&amp;#39;ll request the HomePresenter from the container, and inject into the shell.&lt;/li&gt; &lt;li&gt;As the user interacts with the application, presenters may be removed and new ones injected (probably into a tab, or new window). The shell&amp;#39;s code-behind has the code for actually placing these presenter&amp;#39;s views into the layout.&lt;/li&gt; &lt;li&gt;The presenter will have use &lt;a target="_blank"&gt;commands&lt;/a&gt; as properties that can be bound to in there views. These commands are coordinators of individual activities in the application.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I&amp;#39;m certain that parts of this are confusion, but I believe it will make sense as we continue to build the application. As always, your feedback is welcome.&lt;/p&gt; &lt;p&gt;More to come!&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41939" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/369649866" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Software+Architecture/default.aspx">Software Architecture</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/TDD/default.aspx">TDD</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ChumChase/default.aspx">ChumChase</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/20/building-a-wpf-application-part-3.aspx</feedburner:origLink></item><item><title>Error Message UX Fail</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/368406972/error-message-ux-fail.aspx</link><pubDate>Mon, 18 Aug 2008 20:25:22 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41877</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41877</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/18/error-message-ux-fail.aspx#comments</comments><description>&lt;p&gt;I encountered this nugget while signing up to get developer access to a &lt;span&gt;certain high profile web-based service&lt;/span&gt;. It turns out that my first choice for a password did not meet the site&amp;#39;s policy and I greeted with this:&lt;/p&gt; &lt;p&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="221" alt="stupid_tiny_warning" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/9f44448b2196_DB75/stupid_tiny_warning_3.png" width="577" border="0" /&gt; &lt;/p&gt; &lt;p&gt;&lt;em&gt;This is puts a big capital S in front of &lt;/em&gt;&lt;a href="http://en.wikipedia.org/wiki/User_experience" target="_blank"&gt;&lt;em&gt;UX&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41877" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/368406972" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/humor/default.aspx">humor</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/18/error-message-ux-fail.aspx</feedburner:origLink></item><item><title>Building a WPF Application: Part 2</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/366925488/building-a-wpf-application-part-2.aspx</link><pubDate>Sun, 17 Aug 2008 01:34:03 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41865</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41865</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/16/building-a-wpf-application-part-2.aspx#comments</comments><description>&lt;ul&gt; &lt;li&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/07/20/build-a-wpf-application-part-0.aspx" target="_blank"&gt;Part 0&lt;/a&gt;  &lt;li&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/07/22/building-a-wpf-application-part-1.aspx" target="_blank"&gt;Part 1&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So let&amp;#39;s get back to this whole building a WPF application thing. &lt;/p&gt; &lt;p&gt;A number of things went down since my last post: I was out sick with a stomach bug for few days, my infant son caught the same bug and subsequently we spent a few days in the hospital (he&amp;#39;s fine now, it was nothing serious), &lt;em&gt;and&lt;/em&gt; I finally caught up on the AAA syntax in &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx" target="_blank"&gt;Rhino.Mocks&lt;/a&gt;.&lt;/p&gt; &lt;h3&gt;Changing My Testing Style&lt;/h3&gt; &lt;p&gt;Lots of people have blogged about the AAA syntax &lt;a href="http://www.ayende.com/Blog/archive/2008/05/16/Rhino-Mocks--Arrange-Act-Assert-Syntax.aspx" target="_blank"&gt;here&lt;/a&gt;, &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/24/arrange-act-assert-and-bdd-specifications.aspx" target="_blank"&gt;here&lt;/a&gt;, and &lt;a href="http://blog.jpboodhoo.com/BDDAAAStyleTestingAndRhinoMocks.aspx" target="_blank"&gt;here&lt;/a&gt; (to list a few). I won&amp;#39;t go in depth, but briefly the idea is that you arrange your unit test thusly:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Arrange&lt;/strong&gt;: do the minimal setup required to execute the test  &lt;li&gt;&lt;strong&gt;Act&lt;/strong&gt;: execute the actual code under test  &lt;li&gt;&lt;strong&gt;Assert&lt;/strong&gt;: assert that the code did what you expected&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I decided to adopt this style. It seems to yield more readable, more focused, and less brittle tests. I rewrote the test from my last post using AAA.&amp;nbsp; The original test was this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[TestFixture]
public class The_presenter_for_the_home_feed : TestFixtureBase
{
    private HomePresenter _presenter;
    private IFeedRepository _feedRepository;

    protected override void given_the_context_of()
    {
        _feedRepository = Mocks.StrictMock&amp;lt;IFeedRepository&amp;gt;();
        _presenter = new HomePresenter(_feedRepository);
    }

    [Test]
    public void can_refresh_the_home_feed()
    {
        using (Record)
        {
            Expect.Call(_feedRepository.FetchHomeFeed())
                .Return(new List&amp;lt;Entry&amp;gt;());
        }

        using (Playback)
        {
            _presenter.RefreshHomeFeed();
        }
    }
}&lt;/pre&gt;
&lt;p&gt;and I rewrote it as this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[TestFixture]
public class The_presenter_for_the_home_feed : TestFixtureBase
{
    private HomePresenter _presenter;
    private IFeedRepository _feedRepository;

    protected override void given_the_context_of()
    {
        _feedRepository = MockRepository.GenerateStub&amp;lt;IFeedRepository&amp;gt;();
        _presenter = new HomePresenter(_feedRepository);
    }

    [Test]
    public void can_refresh_the_home_feed_when_credentials_are_available()
    {
        _presenter.RefreshHomeFeed();
        _feedRepository.AssertWasCalled(x =&amp;gt; x.FetchHomeFeed());
    }
}&lt;/pre&gt;
&lt;p&gt;Again, you can gather more details about this approach in one of the links above. &lt;/p&gt;
&lt;p&gt;One interesting note though is that &lt;strong&gt;AssertWasCalled&lt;/strong&gt; is an extension method and we&amp;#39;re using it to assert the method FetchHomeFeed() was actually called on feedRepository. &lt;/p&gt;
&lt;p&gt;(I also think that I should &lt;em&gt;not&lt;/em&gt; have used StrickMock in the original test, as that added to fragility of the test.)&lt;/p&gt;
&lt;p&gt;I tend to think of my code in terms of sentences and paragraphs, at least when it comes to the use of white space. You&amp;#39;ll notice as the tests get a little larger that there will usually be three &amp;quot;paragraphs&amp;quot; in the code: arrange, act, assert.&lt;/p&gt;
&lt;h3&gt;Focusing on the Story&lt;/h3&gt;
&lt;p&gt;I said in my last post that the core story for this application is &lt;em&gt;to retrieve the home feed.&lt;/em&gt; As such, I&amp;#39;d like to take the shortest path to getting that feature fully functional.&amp;nbsp; The next few steps are roughly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write a proxy to wrap the existing FriendFeed api, but just enough to fetch the home feed. 
&lt;li&gt;Write a repository that will manage the home feed data. Even though this seems superfluous at the moment, it&amp;#39;s a seam in the application where I will add future functionality (such as caching, logging, etc.). 
&lt;li&gt;Provide support for authentication.&amp;nbsp; The FriendFeed api requires a username and remote key for accessing the home feed.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Very soon, I want to be able to launch the application, click a Refresh button, and see my feed. If I haven&amp;#39;t provided credentials, I want the application to prompt me for them.&lt;/p&gt;
&lt;h3&gt;The Credentials Problem&lt;/h3&gt;
&lt;p&gt;The parts of the story regarding credentials raise some interesting design questions. Let&amp;#39;s consider some of the pieces of the puzzle.&lt;/p&gt;
&lt;p&gt;The HomePresenter is going to initiate the act getting the home feed. We&amp;#39;ve already seen that HomePresenter is going to invoke some implementation of IFeedRepository. The repository will talk to the FriendFeed api through a wrapper (IFriendFeedProxy) . Inside the wrapper class is the official .NET FriendFeed client, and it is the class that is really interested in the credentials. It&amp;#39;s what talks to the FriendFeed web service, and that needs to be authenticated with the credentials. So at the bottom of this, somewhere in our code, we&amp;#39;ll have this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;FriendFeedClient client = new FriendFeedClient(&amp;quot;username&amp;quot;, &amp;quot;remoteKey&amp;quot;);&lt;/pre&gt;
&lt;p&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="279" alt="classes" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/BuildingaWPFApplicationPart2_F0F6/classes_3.png" width="336" align="right" border="0" /&gt;I&amp;#39;m using the &lt;a href="http://en.wikipedia.org/wiki/Dependency_inversion_principle" target="_blank"&gt;Dependency Inversion Principle&lt;/a&gt; (which I&amp;#39;ll talk about more later). However a consequence of this is that the constructor for HomePresenter takes an IFeedRepository and an IApplicationController. &lt;/p&gt;
&lt;p&gt;In turn, my implementation of IFeedRepository, cleverly named &lt;em&gt;FeedRepository&lt;/em&gt;, requires an instance of IFriendProxy in its constructor. My implementation of IFriendProxy wraps the official api. Did you follow all of that?&lt;/p&gt;
&lt;p&gt;When I first began working through the design, I thought that I&amp;#39;d have to request the credentials from the user at the presenter level, and then pass them down to the repository, then to the proxy which would in turn set them on the actual client. &lt;em&gt;But I could tell quickly that this smelled bad.&lt;/em&gt; The repository doesn&amp;#39;t need to be concerned with credentials, and neither the HomePresenter. So far there are really just two classes that need to know about credentials: some sort of UI for getting the credentials from the user (that is a presenter of some sort) and FriendFeedProxy. &lt;/p&gt;
&lt;p&gt;Oh and what&amp;#39;s this IApplicationController interface all about? Um, I&amp;#39;ll come back to that in the next post. &lt;/p&gt;
&lt;h3&gt;Single Source&lt;/h3&gt;
&lt;p&gt;Ideally, what I want is a single source for the credentials: a class whose sole responsibility is managing the current set of credentials. This lead me to create an ICredentialsSource interface. In order to flesh out what the interface should look like I began writing tests for how the client proxy would interact with it:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[TestFixture]
public class The_client_for_FriendFeed
{
    private const string _username = &amp;quot;your_username&amp;quot;;
    private const string _remotekey = &amp;quot;your_remotekey&amp;quot;;
    private ICredentialsSource _credentials;
    private FriendFeedProxy _client;

    [SetUp]
    public void given_the_context_of()
    {
        _credentials = MockRepository.GenerateStub&amp;lt;ICredentialsSource&amp;gt;();
        _client = new FriendFeedProxy(_credentials);
    }

    [Test]
    public void can_get_the_home_feed_when_authenticated()
    {
        _credentials.Stub(x =&amp;gt; x.UserName).Return(_username);
        _credentials.Stub(x =&amp;gt; x.RemoteKey).Return(_remotekey);
        _credentials.Raise(x =&amp;gt; x.CredentialsChanged += null, _credentials, EventArgs.Empty);

        var feed = _client.FetchHomeFeed();

        IList&amp;lt;Entry&amp;gt; entries = feed.ToList();
        Assert.That(entries[0].Id, Is.Not.Null);
        Assert.That(entries[0].Title, Is.Not.Null);
        Assert.That(entries[0].Published, Is.Not.Null);
    }

    [Test]
    [ExpectedException(typeof (WebException))]
    public void cannot_get_the_home_feed_when_not_authenticated()
    {
        var feed = _client.FetchHomeFeed();
    }

    [Test]
    public void updates_credentials_when_the_credentials_source_changes()
    {
        //arrange
        _credentials.Stub(x =&amp;gt; x.UserName).Return(_username);
        _credentials.Stub(x =&amp;gt; x.RemoteKey).Return(_remotekey);

        //act
        Assert.That(_client.DoesClientHaveCredentials, Is.False);
        _credentials.Raise(x =&amp;gt; x.CredentialsChanged += null, _credentials, EventArgs.Empty);

        //assert
        Assert.That(_client.DoesClientHaveCredentials, Is.True);
    }
}&lt;/pre&gt;
&lt;p&gt;These tests live in my &lt;strong&gt;IntegrationTests&lt;/strong&gt; assembly, separate from my &amp;quot;real&amp;quot; unit test is the &lt;strong&gt;Specifications&lt;/strong&gt; assembly. I consider these tests to be &lt;em&gt;integration tests&lt;/em&gt; because they actually interact with the web services. They are not run as often as my Specifications.&lt;/p&gt;
&lt;p&gt;I found these tests hard to write, and I would appreciate any feedback on how to improve them.&lt;/p&gt;
&lt;p&gt;My point here though is to illustrate how these tests led me to create ICredentialsSource. I know that there will be a little more to it, a method perhaps that will allow me to set the credentials, but we&amp;#39;ll get to that when we need it.&lt;/p&gt;
&lt;p&gt;Right now, the interface looks like this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public interface ICredentialsSource
{
    string UserName { get; }
    string RemoteKey { get; }
    event EventHandler CredentialsChanged;
}&lt;/pre&gt;
&lt;p&gt;I obviously need the username and remote key (and I was tempted to create a class that represented them as a unit.) I also discovered that I wanted the credentials source to raise a change notification event so that the proxy client would be aware when the user changed them.&lt;/p&gt;
&lt;p&gt;Some other places in the application will actually set the credentials on this source, perhaps a yet-unwritten presenter whose job will be to request them from the user. This really helps to decouple responsibilities and keep the code clean. For this approach to work however, our application will need a single instance of this class. I&amp;#39;ll show how I&amp;#39;ll handle that when we cover dependency injection.&lt;/p&gt;
&lt;h3&gt;Next&lt;/h3&gt;
&lt;p&gt;I had a lot of interruptions trying to complete this post, and I had to go back reread what I&amp;#39;ve written so far. In doing so, I realized that I ought to take a step back and explain my overall default architecture that I&amp;#39;m using. That will be the subject of my next post; and &lt;em&gt;I promise&lt;/em&gt; to get the actual WPF bits soon!&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41865" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/366925488" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Software+Architecture/default.aspx">Software Architecture</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/TDD/default.aspx">TDD</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ChumChase/default.aspx">ChumChase</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/16/building-a-wpf-application-part-2.aspx</feedburner:origLink></item><item><title>Why Red Gate Rocks</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/360012503/why-red-gate-rocks.aspx</link><pubDate>Sat, 09 Aug 2008 03:36:40 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41772</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41772</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/08/why-red-gate-rocks.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;ve been working with the eap release of &lt;a href="http://www.red-gate.com/products/ants_profiler/index.htm" target="_blank"&gt;ANTS Performance Profiler&lt;/a&gt; from Red Gate. While I don&amp;#39;t have a lot of experience with other tools of this nature, I&amp;#39;ve been pretty impressed.&lt;/p&gt; &lt;p&gt;My intention was to hold off and blog a full review after I&amp;#39;ve had to time to &lt;em&gt;really&lt;/em&gt; use the application, but today my installed version expired and I just had to share the notification message I received:&lt;/p&gt; &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Dead_parrot" target="_blank"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="289" alt="I&amp;#39;m lovin&amp;#39; these guys" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/WhyRedGateRocks_149FB/red-gate-rocks_3.png" width="623" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Every tool I used from these guys just plain rocks, I should really do them more justice by blogging about it.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I am a &lt;a href="http://codebetter.com/blogs/products/pages/64386.aspx" target="_blank"&gt;Friend of Red Gate&lt;/a&gt;, and I get free licenses for their tools.&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41772" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/360012503" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/humor/default.aspx">humor</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Opinion/default.aspx">Opinion</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/08/08/why-red-gate-rocks.aspx</feedburner:origLink></item><item><title>Building a WPF Application: Part 1</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/343033839/building-a-wpf-application-part-1.aspx</link><pubDate>Tue, 22 Jul 2008 23:51:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41392</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41392</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/22/building-a-wpf-application-part-1.aspx#comments</comments><description>&lt;p&gt;I actually meant to say in my &lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/07/20/build-a-wpf-application-part-0.aspx" target="_blank"&gt;last post&lt;/a&gt; that I had investigated the API options for FriendFeed and they have a C# wrapper already available &lt;a href="http://code.google.com/p/friendfeed-api/downloads/list" target="_blank"&gt;here&lt;/a&gt;. It&amp;#39;s packaged up in a single download with its Python and PHP counterparts.&amp;nbsp; Unfortunately, it has compilation errors. I fixed the errors and then I let &lt;a href="http://www.jetbrains.com/resharper/documentation/" target="_blank"&gt;ReSharper (R#)&lt;/a&gt; have its way with it [&lt;em&gt;R#: Ctrl+Alt+Shift+F].&lt;/em&gt; Yes, I do understand that the Code Cleanup feature of R# can be a nuclear bomb of churn for diffing your source, but &lt;em&gt;&lt;a title="yes, it&amp;#39;s valid!" href="http://www.morewords.com/word/egads/" target="_blank"&gt;egads&lt;/a&gt;&lt;/em&gt; I do love it so.&lt;/p&gt; &lt;p&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/BuildingaWPFApplicationPart1_3D0/soln01_2.png"&gt;&lt;img style="border-right:0px;border-top:0px;margin:0px 0px 0px 4px;border-left:0px;border-bottom:0px;" height="411" alt="FriendFeed project in the solution explorer" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/BuildingaWPFApplicationPart1_3D0/soln01_thumb.png" width="258" align="right" border="0" /&gt;&lt;/a&gt;I also broke out the FriendFeed classes into separate files [&lt;em&gt;R#: F6]&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;&lt;em&gt;Hmm, I &lt;a href="http://devlicio.us/blogs/christopher_bennage/pages/resharper-shortcuts.aspx" target="_blank"&gt;just decided&lt;/a&gt; that I&amp;#39;ll notate R# and VisualStudio keyboard shortcuts like this [app:shortcut]. Is there already a convention for that out there?&lt;/em&gt;&lt;/p&gt; &lt;p&gt;I also decided to keep the FriendFeed code in a separate assembly. I don&amp;#39;t always advocate &lt;a href="http://www.lostechies.com/blogs/chad_myers/archive/2008/07/15/project-anti-pattern-many-projects-in-a-visual-studio-solution-file.aspx" target="_blank"&gt;assembly proliferation&lt;/a&gt;, but it made sense in this case. I created a project called FriendFeed and moved all their classes there.&amp;nbsp; I also preserved their namespace, FriendFeed, as well. (I&amp;#39;m getting tired of typing &amp;quot;FriendFeed&amp;quot;.)&lt;/p&gt; &lt;p&gt;At this point, I just wanted to get a feel for the API. So I read over what appeared to be the significant classes, and I used a couple of tests to see how it really works. Simple enough, instantiate the client and call FetchHomeFeed().&lt;/p&gt; &lt;h3&gt;Building in Seams&lt;/h3&gt; &lt;p&gt;I picked up the term &lt;em&gt;seam&lt;/em&gt; from Ayende in this &lt;a href="http://www.ayende.com/Blog/archive/2007/03/03/The-Production-Value-of-Seams.aspx" target="_blank"&gt;post&lt;/a&gt;. You can think of a seam as a natural boundary in an application. It&amp;#39;s a place where you easily extend or modify an application. It&amp;#39;s a little bit like a &lt;a href="http://domaindrivendesign.org/discussion/messageboardarchive/BoundedContext.html" target="_blank"&gt;Bounded Context&lt;/a&gt;, but just a little. I used to try to coerce my design into the metaphor of &lt;em&gt;layers&lt;/em&gt;, but seams are a more natural concept. You might also think of them as a way of describing componentized architecture.&lt;/p&gt; &lt;p&gt;Consider the example of a desktop computer: you have a motherboard, CPU, memory, video card, etc. All of the components are required for the computer to function, but you can replace any one of them. You can extend the functionality of the computer by adding more hardware. Some things might be tightly coupled, like those wretched integrated video cards. But you don&amp;#39;t think of these components as layers. This is a flexible way to architect your application.&lt;/p&gt; &lt;p&gt;Seams are a standard consideration for me when it comes to designing an application. Yes, you can go crazy with it, you can go crazy with anything. In the case of ChumChase, I don&amp;#39;t want to be tightly coupled to the official API. I have a few reasons right now: [a] the official API might change. [b] I might want to implement my own API against their web services just for kicks [c] it&amp;#39;s a good excuse to demonstrate the technique. I&amp;#39;m going to hide the FriendFeed API behind a repository. The IFeedRepository interface will be a seam in my application.&lt;/p&gt; &lt;h3&gt;MVP&lt;/h3&gt; &lt;p&gt;I mentioned before that I&amp;#39;m going to use Model-View-Presenter. This pattern is similar to MVC, and like barbeque sauce, everyone has their own flavor. In my case, a presenter is a class that represents the &lt;em&gt;behavior&lt;/em&gt; of the UI, and possibly some state. It is ignorant of how the UI visually appears. The view will be a user control, window, page, tab item, etc. We&amp;#39;ll use data binding to glue the two together. The ignorance of the presenter about the view is important because it helps us to isolate the presenter in our unit tests.&lt;/p&gt; &lt;h3&gt;TDD&lt;/h3&gt; &lt;p&gt;It&amp;#39;s &lt;strike&gt;sometimes&lt;/strike&gt; hard to decide where to start writing to tests. I tend to write tests that reflect the &lt;em&gt;behaviors of the user interacting with the application&lt;/em&gt;. This is as opposed to testing how the application might interact with a data source, or some other more internal function of the application. This approach of working from the outside in helps prevent me from making too many assumptions about the internals.&amp;nbsp; The negative is that I have to provide mocks or stubs for the dependencies that I haven&amp;#39;t written yet.&lt;/p&gt; &lt;p&gt;My core story, that is the basic behavior that I&amp;#39;m interested in, is for the application to fetch my home feed. I&amp;#39;ll place this feature on a class called HomePresenter. HomePresenter might end up being my only presenter, I don&amp;#39;t know yet. It common though for applications to have several presenters. We&amp;#39;ll talk later about how to logically organize presenters.&lt;/p&gt; &lt;p&gt;Let&amp;#39;s look at a test:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[TestFixture]
public class The_presenter_for_the_home_feed : TestFixtureBase
{
    private HomePresenter _presenter;
    private IFeedRepository _feedRepository;

    protected override void given_the_context_of()
    {
        _feedRepository = Mocks.StrictMock&amp;lt;IFeedRepository&amp;gt;();
        _presenter = new HomePresenter(_feedRepository);
    }

    [Test]
    public void can_refresh_the_home_feed()
    {
        using (Record)
        {
            Expect.Call(_feedRepository.FetchHomeFeed())
                .Return(new List&amp;lt;Entry&amp;gt;());
        }

        using (Playback)
        {
            _presenter.RefreshHomeFeed();
        }
    }
}&lt;/pre&gt;
&lt;p&gt;First, my TestFixtureBase is just an abstract class to reduce clutter. The Mocks, Record, and Playback properties all exist on it and they are really just pass-throughs to Rhino.Mocks. Likewise, I have a setup method in TestFixtureBase that calls &lt;em&gt;given_the_context_of()&lt;/em&gt; before each test is executed. It&amp;#39;s meant to reset the system-under-test (SUT) into a consistent and pristine state.&lt;/p&gt;
&lt;p&gt;Notice that I named my class and method such that they read as a specification for the behavior I&amp;#39;m testing: &lt;em&gt;The presenter for the home feed can refresh the home feed.&lt;/em&gt; I&amp;#39;m not sure that I like saying &amp;quot;presenter&amp;quot; in the specification. If I was working with non-technical users, that wouldn&amp;#39;t make sense to them. I could replace it with &amp;quot;UI&amp;quot; or &amp;quot;interface&amp;quot; or &amp;quot;screen&amp;quot; perhaps.&lt;/p&gt;
&lt;p&gt;The test has two blocks or phases: record and playback. This is generally a big stumbling block for people. I know when I first encountered it I was thoroughly confused. The record phase is where I tell the test what I&amp;#39;m expecting to happen during the playback phase.&amp;nbsp; The record phase plays the same roles as asserts.&lt;/p&gt;
&lt;p&gt;The function we are really testing here is:&lt;/p&gt;
&lt;p&gt;_presenter.RefreshHomeFeed(); &lt;/p&gt;
&lt;p&gt;Since there is not a state that I can verify after calling RefreshHomeFeed(), I am checking to make sure that it&amp;#39;s doing what I expect it to do. That is, I expect it to get a list of entries from a repository of feeds.&lt;/p&gt;
&lt;p&gt;The Expect.Call().Return() is Rhino.Mocks syntax that allows me to say: &lt;em&gt;I expect my SUT to execute _feedRepository.FetchHomeFeed() and I expect that to return a List&amp;lt;Entry&amp;gt; instance.&lt;/em&gt; Right now Entry is just an empty class, but conceptually it represents a single item in the feed. You should also note that the relationship between my presenter and the repository is established in given_the_context_of().&lt;/p&gt;
&lt;p&gt;Yes, this is a simple test, but writing this test helped me to shake out what I needed.&amp;nbsp; Unfortunately, the test as it stands here does not reflect the process of writing it.&amp;nbsp; I wrote some things, decided they didn&amp;#39;t look right, changed them a bit and so on. It probably took me 10 minutes or so before I settled on what you see.&lt;/p&gt;
&lt;p&gt;Moving on to the next test. This is in the same class, so you can read it as: &lt;em&gt;The presenter for the home feed notifies the UI when the home feed is refreshed.&lt;/em&gt;&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[Test]
public void notifies_the_UI_when_the_home_feed_is_refreshed()
{
    var property_has_changed = false;

    _presenter.PropertyChanged +=
        (s, e) =&amp;gt; { property_has_changed = (e.PropertyName == &amp;quot;HomeFeed&amp;quot;); };

    _presenter.RefreshHomeFeed();

    Assert.That(property_has_changed);
}&lt;/pre&gt;
&lt;p&gt;I want to verify that when I call _presenter.RefreshHomeFeed() a change notification is raised for the HomeFeed property. This means my presenter needs a HomeFeed property. I have a boolean flag that helps me track the state and I&amp;#39;m using an inline delegate to set my flag when the property is changed. (There&amp;#39;s actually a flaw in this test that we&amp;#39;ll examine later, can you see it?)&amp;nbsp; &lt;/p&gt;
&lt;p&gt;I don&amp;#39;t like strings though. If I happen to change the name of the HomeFeed property and forget to change the string in the test, I&amp;#39;ve broken my test. Of course, I&amp;#39;ll notice as soon as I run the tests, but it would sure be nice to eliminate the string. So I wrote this extension method for PropertyChangedEventArgs:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public static bool HasChanged&amp;lt;T&amp;gt;(this PropertyChangedEventArgs args, Expression&amp;lt;Func&amp;lt;T&amp;gt;&amp;gt; property)
{
    var expression = (MemberExpression)property.Body;
    return expression.Member.Name == args.PropertyName;
}&lt;/pre&gt;
&lt;p&gt;Now I can change my test to the following and eliminate the string:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[Test]
public void notifies_the_UI_when_the_home_feed_is_refreshed()
{
    var property_has_changed = false;

    _presenter.PropertyChanged +=
        (s, e) =&amp;gt; { property_has_changed = e.HasChanged(() =&amp;gt; _presenter.HomeFeed); };

    _presenter.RefreshHomeFeed();

    Assert.That(property_has_changed);
}&lt;/pre&gt;
&lt;p&gt;Of course, in between these tests I was writing code to make them pass. (&lt;a href="http://geekswithblogs.net/WillSmith/archive/2008/03/18/red-green-refactor.aspx" target="_blank"&gt;Red -&amp;gt; Green -&amp;gt; Refactor&lt;/a&gt;, right?) Here&amp;#39;s what my presenter class looked liked afterwards:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using ChumChase.Extensions;

namespace ChumChase.Presenters
{
    public class HomePresenter : INotifyPropertyChanged
    {
        private readonly IFeedRepository _feedRepository;
        private IList&amp;lt;Entry&amp;gt; _homeFeed;

        public HomePresenter(IFeedRepository feedRepository)
        {
            _feedRepository = feedRepository;
        }

        public IList&amp;lt;Entry&amp;gt; HomeFeed
        {
            get { return _homeFeed; }
            private set
            {
                _homeFeed = value;
                OnPropertyChanged( ()=&amp;gt; HomeFeed);
            }
        }

        public void RefreshHomeFeed()
        {
            HomeFeed = _feedRepository.FetchHomeFeed();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged&amp;lt;T&amp;gt;(Expression&amp;lt;Func&amp;lt;T&amp;gt;&amp;gt; property)
        {
            if (PropertyChanged != null) PropertyChanged(this, property.CreateChangeEventArgs());
        }
    }
}&lt;/pre&gt;
&lt;p&gt;The source is now available &lt;a href="http://www.codeplex.com/chumchase" target="_blank"&gt;here&lt;/a&gt;. &lt;strike&gt;More to come!&lt;/strike&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/08/16/building-a-wpf-application-part-2.aspx" target="_blank"&gt;Continue to Part 2&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41392" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/343033839" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Software+Architecture/default.aspx">Software Architecture</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/TDD/default.aspx">TDD</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ChumChase/default.aspx">ChumChase</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/22/building-a-wpf-application-part-1.aspx</feedburner:origLink></item><item><title>Building a WPF Application: Part 0</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/341151722/build-a-wpf-application-part-0.aspx</link><pubDate>Mon, 21 Jul 2008 03:18:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41363</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>8</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41363</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/20/build-a-wpf-application-part-0.aspx#comments</comments><description>&lt;p&gt;In a rather indirect way, I was inspired by a commenter on &lt;a title="BabySmash + Books = Good WPF" href="http://www.hanselman.com/blog/LearningWPFWithBabySmashAndBackToBasicsMakingAssumptionsAndWhenToTurnToBooks.aspx" target="_blank"&gt;one of Scott Hanselman&amp;#39;s posts&lt;/a&gt; to begin a series that walks through building a WPF application from start to finish. We did this for four different applications in &lt;a title="I just can&amp;#39;t get enough of linking to our book!" href="http://www.amazon.com/gp/product/0672329859?&amp;amp;camp=212361&amp;amp;linkCode=wey&amp;amp;tag=bluspiconinc-20&amp;amp;creative=380733" target="_blank"&gt;our book&lt;/a&gt;, but those where targeted to demonstrate particular facets of WPF whereas in these (yet unwritten) posts I&amp;#39;d like to focus more on &amp;quot;this is how I build my WPF apps&amp;quot;. Not to say that my way is the *right way*, but so that we might learn together. In the spirit of the aforementioned post, I&amp;#39;m bound to make mistakes, so please (gently) correct me when you think you see one.&lt;/p&gt; &lt;h3&gt;What to build?&lt;/h3&gt; &lt;p&gt;You might not have noticed, but there&amp;#39;s quite a bit of .NET chatter in &lt;a href="http://twitter.com/" target="_blank"&gt;twit-space&lt;/a&gt;. There are already lots of Twitter clients, and &lt;a title="Witty" href="http://code.google.com/p/wittytwitter/" target="_blank"&gt;some are WPF&lt;/a&gt;, so that path has been rigorously trod. However, the &lt;a href="http://www.techcrunch.com/2008/05/20/twitter-something-is-technically-wrong/" target="_blank"&gt;technical difficulties&lt;/a&gt; surrounding Twitter has given rise to the popularity of another mash up web 2.0 thingy app called &lt;a href="http://friendfeed.com/" target="_blank"&gt;FriendFeed&lt;/a&gt;.&amp;nbsp; Everyone seems to agree that the web interface for FriendFeed is all stinky bad, &lt;em&gt;and&lt;/em&gt; there&amp;#39;s an &lt;a href="http://code.google.com/p/friendfeed-api/wiki/ApiDocumentation" target="_blank"&gt;API&lt;/a&gt; readily available, so I think a FriendFeed client is in order.&lt;/p&gt; &lt;p&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="53" alt="ff_logo" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/BuildaWPFApplicationPart0_FA/ff_logo_3.png" width="234" align="right" border="0" /&gt; Briefly, FriendFeed is a way to consolidate all of your creepy Internet voyeurism in one spot. You can track a friend&amp;#39;s Flickr account, NetFlix queue, Amazon wishlist, and yes, their Twitter tweets and much, much more. Oh yeah, and you can subscribe to me &lt;a title="please, pay attention to me! I&amp;#39;m really cool! Really!" href="http://friendfeed.com/bennage" target="_blank"&gt;here&lt;/a&gt;. (I&amp;#39;m such a loser.)&lt;/p&gt; &lt;h3&gt;What to do?&lt;/h3&gt; &lt;p&gt;I&amp;#39;m not going to set an agenda or outline a detailed plan. I&amp;#39;m just going to post as I have time to work on it. I started tonight, so I&amp;#39;m expecting to have a real Part 1 posted by midweek. I&amp;#39;ve already set up a project at &lt;a href="http://www.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt; (though it won&amp;#39;t be published for a few more days still.) I named it &lt;a href="http://www.codeplex.com/chumchase" target="_blank"&gt;ChumChase&lt;/a&gt;. Isn&amp;#39;t that great? &lt;/p&gt; &lt;p&gt;Part of my plan is to step you through my thinking and decision making process in sort of &lt;a title="I&amp;#39;m talking about Jimmy Nilsson." href="http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1216528167&amp;amp;sr=8-1" target="_blank"&gt;Nilssonian&lt;/a&gt; way. I&amp;#39;ve only just begun but here&amp;#39;s what I can tell you so far.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;I&amp;#39;m going to use a Model-View-Presenter pattern  &lt;li&gt;Expect to see some DDD artifacts. &lt;li&gt;I&amp;#39;m going to use &lt;a title="wow, can you believe that I actually linked to NUnit?" href="http://www.nunit.org/index.php" target="_blank"&gt;NUnit&lt;/a&gt; and &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx" target="_blank"&gt;RhinoMocks&lt;/a&gt;.  &lt;li&gt;I&amp;#39;ll probably use &lt;a href="http://castleproject.org/container/index.html" target="_blank"&gt;Windsor&lt;/a&gt; too (or maybe &lt;a href="http://structuremap.sourceforge.net/Default.htm" target="_blank"&gt;StructureMap&lt;/a&gt; though, anybody have a preference?) &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I had intended to write a set of user stories&amp;nbsp; using the issue tracker of CodePlex. However, I got tired of retyping them every time the site errorred out, which was about 60% of the time. (Is that typical for the CodePlex issue tracker? This was my first usage.)&amp;nbsp; It also occurred to me that I am lazy and ought to have a life outside of coding, so sorry no user stories.&lt;/p&gt; &lt;h3&gt;What to think?&lt;/h3&gt; &lt;p&gt;I&amp;#39;m all about conversation. If this interests you, please let me know. I welcome (friendly) criticisms as well. The more I hear, the more motivated I&amp;#39;ll be to do it. (Believe me there&amp;#39;s a lot to distract right now. I had a new baby son born on the 10th.)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2008/07/22/building-a-wpf-application-part-1.aspx"&gt;Continue to Part 1&lt;/a&gt;&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41363" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/341151722" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Software+Architecture/default.aspx">Software Architecture</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/TDD/default.aspx">TDD</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ChumChase/default.aspx">ChumChase</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/20/build-a-wpf-application-part-0.aspx</feedburner:origLink></item><item><title>Using Lambdas to get at properties</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210226/using-lambdas-to-get-at-properties.aspx</link><pubDate>Thu, 17 Jul 2008 00:36:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41324</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>9</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41324</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/16/using-lambdas-to-get-at-properties.aspx#comments</comments><description>&lt;p&gt;This is a somewhat made-up scenario based on a recent project. My client has not given me permission to discuss the specifics of the application (yet), so I apologize for keeping it vague. I hope you don&amp;#39;t give up before the payoff.&lt;/p&gt; &lt;h3&gt;The Problem&lt;/h3&gt; &lt;p&gt;Imagine an application, where a user can create &amp;quot;styles&amp;quot; and those styles can be applied to shapes. The application uses WPF to visualize the shapes with the styles applied.&amp;nbsp; (Perhaps it&amp;#39;s a design tool meant for Hanselman&amp;#39;s &lt;a href="http://www.hanselman.com/blog/CategoryView.aspx?category=BabySmash"&gt;BabySmash&lt;/a&gt;?) Let&amp;#39;s say that there are three kinds of shapes: a line, a circle, and a bull&amp;#39;s eye.&lt;/p&gt; &lt;p&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/1a84ff9474f3_108BF/styled_shapes_2.gif"&gt;&lt;img height="225" alt="styled_shapes" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/1a84ff9474f3_108BF/styled_shapes_thumb.gif" width="160" align="right" border="0" /&gt;&lt;/a&gt; Each shape has specific attributes that can be styled, and the these attributes are unique to each shape.&amp;nbsp; Here&amp;#39;s a simple listing of possible attributes:&lt;/p&gt; &lt;div align="center"&gt; &lt;table style="border-right:#dddddd 1px solid;border-top:#dddddd 1px solid;border-left:#dddddd 1px solid;width:300px;border-bottom:#dddddd 1px solid;border-collapse:collapse;" cellspacing="0" cellpadding="0" align="center"&gt;  &lt;tr&gt; &lt;th&gt;Line&lt;/th&gt; &lt;th&gt;Circle&lt;/th&gt; &lt;th&gt;Bull&amp;#39;s Eye&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p align="center"&gt;Stroke&lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p align="center"&gt;Fill&lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p align="center"&gt;Outer Fill&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p align="center"&gt;Thickness&lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p align="center"&gt;Stroke&lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p align="center"&gt;Inner Fill&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;div align="center"&gt;&amp;nbsp;&lt;/div&gt; &lt;p&gt;Now, we have three classes to represent the styles: LineStyle, CircleStyle, BullsEyeStyle. The Fill and Stroke attributes are all of type &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.brush.aspx"&gt;Brush&lt;/a&gt;. Furthermore, all three classes derive from ShapeStyle.&lt;/p&gt; &lt;p&gt;Now, imagine that we have to construct instances of these styles for some data that comes in the form of an API that we don&amp;#39;t control. The constructor for LineStyle might look like this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public class LineStyle : ShapeStyle
{
    public LineStyle(ForeignLineStyle style)
    {
        Thickness = style.StrokeThickness;
        Stroke = style.StrokeBrush;
    }

    public Brush Stroke { get; set; }
    public double Thickness { get; set; }
}&lt;/pre&gt;
&lt;p&gt;That&amp;#39;s simple enough, but remember the properties are of type Brush, and we don&amp;#39;t really want our instances of LineStyle to share &lt;em&gt;the same&lt;/em&gt; Brush with instances of ForeignLineStyle.&amp;nbsp; Luckily, Brush has a Clone method! Yeah!&amp;nbsp; Only, what if the Brush is null? Okay, we&amp;#39;ll change it to this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public class LineStyle : ShapeStyle
{
    public LineStyle(ForeignLineStyle style)
    {
        Thickness = style.StrokeThickness;
        Stroke = (style.StrokeBrush != null)
                     ? style.StrokeBrush.Clone()
                     : null;
    }

    public Brush Stroke { get; set; }
    public double Thickness { get; set; }
}&lt;/pre&gt;
&lt;p&gt;Now, every time I have a property of type Brush on one of these style classes the pattern is the same.&amp;nbsp; I&amp;nbsp; start copying and pasting. (&lt;a href="http://en.wikipedia.org/wiki/Code_smell"&gt;Do you smell something?&lt;/a&gt;)&amp;nbsp; Hmm, what if I have lot of Brush properties? Many more than I initially listed in the table. I sure feel like I am &lt;a href="http://en.wikipedia.org/wiki/Don&amp;#39;t_repeat_yourself"&gt;repeating myself&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;At this point, my instinct is to extract this pattern into a method. But how do I do this? The properties are unique to each class, and using reflection would be way overkill.&lt;/p&gt;
&lt;h3&gt;Lambda Magic&lt;/h3&gt;
&lt;p&gt;What I want is a method that takes the brush from ForeignLineStyle, and the setter for a property of type Brush. Using a lambda for the setter, I am able to create:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public static void SetBrush(Brush brush, Action&amp;lt;Brush&amp;gt; property)
{
    var value = (brush != null)
            ? brush.Clone()
            : null;

    property.Invoke(value);
}&lt;/pre&gt;
&lt;p&gt;For this to make sense, you need to recognize that a setter is a essentially a method with a signature like this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;delegate void PropertySetter&amp;lt;T&amp;gt;(T value);&lt;/pre&gt;
&lt;p&gt;That signature is the same as &lt;a href="http://msdn.microsoft.com/en-us/library/018hxwa8.aspx"&gt;Action&amp;lt;T&amp;gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, I can modify LineStyle to look like this:&lt;/p&gt;&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public class LineStyle : ShapeStyle
{
    public LineStyle(ForeignLineStyle style)
    {
        Thickness = style.StrokeThickness;
        SetBrush(style.StrokeBrush, brush =&amp;gt; Stroke = brush);
    }

    public Brush Stroke { get; set; }
    public double Thickness { get; set; }
}&lt;/pre&gt;
&lt;p&gt;Notice that the second parameter is :&lt;/p&gt;&lt;pre&gt;brush =&amp;gt; Stroke = brush&lt;/pre&gt;
&lt;p&gt;and not simply&lt;/p&gt;&lt;pre&gt;()=&amp;gt; Stroke&lt;/pre&gt;
&lt;p&gt;The latter is for the getter and would match &lt;a href="http://msdn.microsoft.com/en-us/library/bb534960.aspx"&gt;Func&amp;lt;T&amp;gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;After Thoughts&lt;/h3&gt;
&lt;p&gt;Arguably, this doesn&amp;#39;t accomplish much.&amp;nbsp; The repetitive code had a small footprint, and the SetBrush method is likely to throw off other developers. &lt;/p&gt;
&lt;p&gt;It&amp;#39;s up to you to decide it&amp;#39;s applicability, but a least it&amp;#39;s one more tool in the box.&lt;/p&gt;
&lt;p&gt;(Thanks to &lt;a title="some say that he&amp;#39;s just that crazy!" href="http://devlicio.us/blogs/rob_eisenberg/default.aspx"&gt;Rob Eisenberg&lt;/a&gt;, who wrote some code that planted this ideas in my head.) &lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41324" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210226" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/lambdas/default.aspx">lambdas</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/16/using-lambdas-to-get-at-properties.aspx</feedburner:origLink></item><item><title>TemplateBinding: a bridge between styles and templates</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210234/templatebinding-a-bridge-between-styles-and-templates.aspx</link><pubDate>Fri, 04 Jul 2008 04:30:09 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41205</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41205</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/04/templatebinding-a-bridge-between-styles-and-templates.aspx#comments</comments><description>&lt;p&gt;This is partially a follow-up to my &lt;a href="http://devlicio.us/blogs/christopher_bennage/archive/2008/06/27/contrasting-control-templates-amp-styles-in-wpf.aspx" target="_blank"&gt;last post&lt;/a&gt; contrasting control templates and styles. Like I mentioned before I&amp;#39;ve been working on an application that has required a custom theme. In addition to styling the standard controls like text boxes and expanders, we&amp;#39;ve had to create a number of custom controls as well. That has added up to a lot of control templates.&lt;/p&gt; &lt;p&gt;This recent work has emphasized the importance of the template binding. (Beatriz Costa first helped me get a handle on template binding &lt;a title="you&amp;#39;ll need to scroll down a bit" href="http://www.beacosta.com/blog/?m=200611" target="_blank"&gt;here&lt;/a&gt;.)&amp;nbsp; &lt;a href="http://msdn.microsoft.com/en-us/library/ms742882.aspx" target="_blank"&gt;TemplateBinding&lt;/a&gt; is a special markup extension specifically designed for binding values in a template. (That&amp;#39;s a bit of a circular definition, isn&amp;#39;t it?) TemplateBinding is the mechanism that allows us to &lt;em&gt;inject&lt;/em&gt; values into our templates, or to parameterize them.&lt;/p&gt; &lt;h4&gt;An Example&lt;/h4&gt; &lt;p&gt;First, imagine that we have a resource dictionary where we have defined a set of brushes that we&amp;#39;ll use as the palette for our application. We might go about building a control template for the &lt;a title="an overview of the ToolTip" href="http://msdn.microsoft.com/en-us/library/ms754034.aspx" target="_blank"&gt;ToolTip&lt;/a&gt; control like this:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;ControlTemplate x:Key=&amp;quot;ToolTipTemplate&amp;quot;
                 TargetType=&amp;quot;ToolTip&amp;quot;&amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;Border x:Name=&amp;quot;DropShadow&amp;quot;
                Focusable=&amp;quot;False&amp;quot;
                CornerRadius=&amp;quot;3&amp;quot;
                Background=&amp;quot;Black&amp;quot;
                Opacity=&amp;quot;0.4&amp;quot;
                Margin=&amp;quot;3 3 0 0&amp;quot; /&amp;gt;
        &amp;lt;Border Background=&amp;quot;{DynamicResource NormalControlBackground}&amp;quot;
                BorderBrush=&amp;quot;{DynamicResource NormalControlBorder}&amp;quot;
                BorderThickness=&amp;quot;1&amp;quot;
                Margin=&amp;quot;0 0 3 3&amp;quot;
                CornerRadius=&amp;quot;3&amp;quot;
                Padding=&amp;quot;6&amp;quot;&amp;gt;
            &amp;lt;ContentPresenter TextBlock.Foreground=&amp;quot;{DynamicResource NormalControlText}&amp;quot; /&amp;gt;
        &amp;lt;/Border&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;p&gt;This control template is too rigid. What if another team member needs to create a special ToolTip in just one place with a background color other than NormalControlBackground?&amp;nbsp; They would probably write some markup like this:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;Button Content=&amp;quot;History Eraser Button&amp;quot;&amp;gt;
    &amp;lt;Button.ToolTip&amp;gt;
        &amp;lt;ToolTip Background=&amp;quot;Red&amp;quot; 
                 Foreground=&amp;quot;White&amp;quot;
                 Content=&amp;quot;Don&amp;#39;t press it!&amp;quot; /&amp;gt;
    &amp;lt;/Button.ToolTip&amp;gt;
&amp;lt;/Button&amp;gt;&lt;/pre&gt;
&lt;p&gt;Sadly, they would discover that it wouldn&amp;#39;t work. The control template doesn&amp;#39;t know anything about the properties we set on the ToolTip in the markup. Everything is defined in the control template and it&amp;#39;s self contained.&amp;nbsp; We really want the template to be able to use the properties that are set on the control. The template above can be rewritten to do that:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;ControlTemplate x:Key=&amp;quot;ToolTipTemplate&amp;quot;
                 TargetType=&amp;quot;ToolTip&amp;quot;&amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;Border x:Name=&amp;quot;DropShadow&amp;quot;
                Focusable=&amp;quot;False&amp;quot;
                CornerRadius=&amp;quot;3&amp;quot;
                Background=&amp;quot;Black&amp;quot;
                Opacity=&amp;quot;0.4&amp;quot;
                Margin=&amp;quot;3 3 0 0&amp;quot; /&amp;gt;
        &amp;lt;Border Background=&amp;quot;{TemplateBinding Background}&amp;quot;
                BorderBrush=&amp;quot;{TemplateBinding BorderBrush}&amp;quot;
                BorderThickness=&amp;quot;{TemplateBinding BorderThickness}&amp;quot;
                Margin=&amp;quot;0 0 3 3&amp;quot;
                CornerRadius=&amp;quot;3&amp;quot;
                Padding=&amp;quot;{TemplateBinding Padding}&amp;quot;&amp;gt;
            &amp;lt;ContentPresenter TextBlock.Foreground=&amp;quot;{TemplateBinding Foreground}&amp;quot; /&amp;gt;
        &amp;lt;/Border&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;p&gt;Using the template bindings allows the control template to pick up the values that are supplied directly on the element, or on the style applied to the element. That means that the Button markup above would work, or we could even create a style for the special case tool tip that looks like this:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;Style x:Key=&amp;quot;WarningStyle&amp;quot; TargetType=&amp;quot;ToolTip&amp;quot;&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Background&amp;quot; Value=&amp;quot;Red&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Foreground&amp;quot; Value=&amp;quot;White&amp;quot; /&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;h4&gt;Handling the Default Values&lt;/h4&gt;
&lt;p&gt;If you use a control template with template binding, and don&amp;#39;t provide any values on the control, what happens? The default values of the bound properties are used. There are many cases where this is &lt;em&gt;not&lt;/em&gt; what you want though. If your intent was to have a global look for tool tips based on our first example, then you want the template to use some specific brushes as well a few other things.&lt;/p&gt;
&lt;p&gt;In this case, you can use a style to set the desired defaults. To apply a style to a control for an entire application, set its TargetType and &lt;em&gt;don&amp;#39;t &lt;/em&gt;provide a key. The style will also need to be added to (or merged into) the resource dictionary of application. The style is also used to set the custom template for the control (otherwise you&amp;#39;d have to set the Template property on every instance of the control.)&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s an example style to accompany our template:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;Style TargetType=&amp;quot;ToolTip&amp;quot;&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Background&amp;quot; Value=&amp;quot;{DynamicResource NormalControlBackground}&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;BorderBrush&amp;quot; Value=&amp;quot;{DynamicResource NormalControlBorder}&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;BorderThickness&amp;quot; Value=&amp;quot;1&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Foreground&amp;quot; Value=&amp;quot;{DynamicResource NormalControlText}&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Padding&amp;quot; Value=&amp;quot;6&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Template&amp;quot; Value=&amp;quot;{DynamicResource ToolTipTemplate}&amp;quot; /&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;p&gt;I&amp;#39;m interested in feedback. If you find this useful, or too basic, or whatever, please let me know!&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41205" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210234" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/control+templates/default.aspx">control templates</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/data+binding/default.aspx">data binding</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/styles/default.aspx">styles</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/07/04/templatebinding-a-bridge-between-styles-and-templates.aspx</feedburner:origLink></item><item><title>Contrasting Control Templates &amp; Styles in WPF</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210235/contrasting-control-templates-amp-styles-in-wpf.aspx</link><pubDate>Fri, 27 Jun 2008 05:54:36 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41102</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41102</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/06/27/contrasting-control-templates-amp-styles-in-wpf.aspx#comments</comments><description>&lt;p&gt;We&amp;#39;ve had a few projects that involved custom styling for many of the standard controls. At first, I found myself swimming in a sea of XAML and rather double-minded about where to put things. Now, an approach has begun to coalesce for me.&lt;/p&gt; &lt;p&gt;When it comes to customizing the look of controls, there are two concerns: &lt;em&gt;styles&lt;/em&gt; and &lt;em&gt;control templates&lt;/em&gt;. Knowing when to use one or the other can be confusing, as there is really a lot of overlap in what they each do.&lt;/p&gt; &lt;h4&gt;Styles&lt;/h4&gt; &lt;p&gt;Styles are frequently compared to cascading styles sheets (css) in the html world. WPF styles are like css in that they can be used to globally define the looks of certain elements, they can be paired to specific element by way of a key, or they can even be declared inline directly on an element.&lt;/p&gt; &lt;p&gt;I&amp;#39;ve come to view styles as a way to set default values on the public properties of WPF elements. (Really, it&amp;#39;s dependency properties, but most public properties on WPF controls are dependency properties anyway .) When you associate a style with an element you are essentially saying &amp;quot;here&amp;#39;s the set of properties and corresponding values that I&amp;#39;d like to set.&amp;quot; This distinction is important for two reasons:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Styles can only affect the public dependency properties.  &lt;li&gt;Styles can affect non-visual properties.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;This concept of setting properties is inherent in the syntax of styles:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;Style&amp;gt;
    &amp;lt;Setter Property=&amp;quot;X&amp;quot; Value=&amp;quot;Y&amp;quot; /&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;This also means that styles are limited in what they can do by the public API of the element that they are applied to.&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;Control Templates&lt;/h4&gt;
&lt;p&gt;Control templates are used for manipulating the &lt;em&gt;composition&lt;/em&gt; of a control.&amp;nbsp; They are a means of modifying the structure of a control. &lt;/p&gt;
&lt;p&gt;First, you need to recognize that every control in WPF is composed out of other WPF elements. If you were to examine a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.button.aspx" target="_blank"&gt;Button&lt;/a&gt; control, you would discovered that internally it&amp;#39;s composed of something like this:&lt;/p&gt;&lt;pre class="xml:nogutter:nocontrols" name="code"&gt;&amp;lt;ms:ClassicBorderDecorator x:Name=&amp;quot;ContentContainer&amp;quot;
                           SnapsToDevicePixels=&amp;quot;True&amp;quot;
                           Background=&amp;quot;{TemplateBinding Background}&amp;quot;
                           BorderBrush=&amp;quot;{TemplateBinding BorderBrush}&amp;quot;
                           BorderStyle=&amp;quot;Raised&amp;quot;
                           BorderThickness=&amp;quot;3,3,3,3&amp;quot;&amp;gt;
    &amp;lt;ContentPresenter /&amp;gt;
&amp;lt;/ms:ClassicBorderDecorator&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.windows.themes.classicborderdecorator.aspx" target="_blank"&gt;ClassicBorderDecorator&lt;/a&gt; is an element Microsoft built for emulating the look of the existing Windows UI (that&amp;#39;s pre-WPF elements). It&amp;#39;s very much like a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.border.aspx" target="_blank"&gt;Border&lt;/a&gt;, and tucked away in the theme-specific assembly PresentationFramework.Classic.dll. (Ok, maybe that&amp;#39;s a lame example).&lt;/p&gt;
&lt;p&gt;There are certain internal elements that the control looks for in its template.&amp;nbsp; In the case of Button, it look for a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter.aspx" target="_blank"&gt;ContentPresenter&lt;/a&gt;, though it might be &lt;a title="need to find out which part?" href="http://devlicio.us/blogs/christopher_bennage/archive/2008/03/09/identifying-control-templates-parts-in-wpf.aspx" target="_blank"&gt;something else&lt;/a&gt; depending on the control.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/OrganizingWPFProjectsTemplatesStyles_125BE/button%20example_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="90" alt="button example" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/OrganizingWPFProjectsTemplatesStyles_125BE/button%20example_thumb.png" width="145" align="right" border="0" /&gt;&lt;/a&gt;Now, let&amp;#39;s say you want a button that has rounded corners, with a black background, and gray outline.&amp;nbsp; You can use a style to set the background and outline using the &lt;strong&gt;Background&lt;/strong&gt; and &lt;strong&gt;BorderBrush&lt;/strong&gt; properties, and you might hope for a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.border.cornerradius.aspx" target="_blank"&gt;CornerRadius&lt;/a&gt; property similar to that of a Border, but there isn&amp;#39;t one. In short, you can&amp;#39;t make a button have rounded corners using a style.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m sure someone out there is thinking that you &lt;em&gt;can&lt;/em&gt; use a style and set Background to a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.drawingbrush.aspx" target="_blank"&gt;DrawingBrush&lt;/a&gt; that looks like that, and well, yes, you could, but um, that&amp;#39;s a different matter and I need a simple example at the moment.&lt;/p&gt;
&lt;p&gt;We could achieve this with the following control template however:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;Button&amp;gt;
    &amp;lt;Button.Template&amp;gt;
        &amp;lt;ControlTemplate TargetType=&amp;quot;Button&amp;quot;&amp;gt;
            &amp;lt;Border CornerRadius=&amp;quot;4&amp;quot; 
                    Background=&amp;quot;Black&amp;quot;
                    BorderBrush=&amp;quot;Gray&amp;quot;
                    BorderThickness=&amp;quot;1&amp;quot;
                    Padding=&amp;quot;10 6&amp;quot;&amp;gt;
                &amp;lt;TextBlock Foreground=&amp;quot;White&amp;quot;
                           Text=&amp;quot;Click Me&amp;quot;/&amp;gt;
            &amp;lt;/Border&amp;gt;
        &amp;lt;/ControlTemplate&amp;gt;
    &amp;lt;/Button.Template&amp;gt;
&amp;lt;/Button&amp;gt;&lt;/pre&gt;
&lt;p&gt;You are afforded much more liberty with control templates than you are with styles, but the control templates are also trickier to use. In the template above, we completely bypassed the Content property on the button, and we manually created the &amp;quot;content&amp;quot; in the template.&amp;nbsp; That makes the template not so reusable and the above example is not a good template. Here&amp;#39;s one that&amp;#39;s a bit more generic:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;Button Content=&amp;quot;Click Me&amp;quot;&amp;gt;
    &amp;lt;Button.Template&amp;gt;
        &amp;lt;ControlTemplate TargetType=&amp;quot;Button&amp;quot;&amp;gt;
            &amp;lt;Border CornerRadius=&amp;quot;4&amp;quot; 
                    Background=&amp;quot;Black&amp;quot;
                    BorderBrush=&amp;quot;Gray&amp;quot;
                    BorderThickness=&amp;quot;1&amp;quot;
                    Padding=&amp;quot;10 6&amp;quot;&amp;gt;
                &amp;lt;ContentPresenter TextBlock.Foreground=&amp;quot;White&amp;quot; /&amp;gt;
            &amp;lt;/Border&amp;gt;
        &amp;lt;/ControlTemplate&amp;gt;
    &amp;lt;/Button.Template&amp;gt;
&amp;lt;/Button&amp;gt;&lt;/pre&gt;
&lt;p&gt;We replaced the TextBlock with a ContentPresenter. We use an attached property to make any text inside the ContentPresenter white. &lt;/p&gt;
&lt;h4&gt;Why Both?&lt;/h4&gt;
&lt;p&gt;So we&amp;#39;ve redefined the look of a Button, and we didn&amp;#39;t touch the style.&amp;nbsp; Why do we need styles?&lt;/p&gt;
&lt;p&gt;There are a few good reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Styles are easier to use. You don&amp;#39;t need to be concerned about the internal composition of the control or making sure that you&amp;#39;ve included all the necessary pieces. 
&lt;li&gt;Styles can affect properties on the control that don&amp;#39;t have anything to due with the composition.&amp;nbsp; That means they can affect things that control templates cannot. 
&lt;li&gt;If you want to globally replace a template for a control in your application, you have to do it with a style. 
&lt;li&gt;It&amp;#39;s not uncommon to &amp;quot;break&amp;quot; your controls when you start creating custom templates. You don&amp;#39;t need to worry about this so much with styles.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;More to come ...&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41102" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210235" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/control+templates/default.aspx">control templates</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/data+binding/default.aspx">data binding</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/styles/default.aspx">styles</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/06/27/contrasting-control-templates-amp-styles-in-wpf.aspx</feedburner:origLink></item><item><title>Styling Separators in WPF</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210236/styling-separators-in-wpf.aspx</link><pubDate>Thu, 19 Jun 2008 15:37:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:41037</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=41037</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/06/19/styling-separators-in-wpf.aspx#comments</comments><description>&lt;p&gt;Separators are the little tiddly-bits that, um, &lt;em&gt;separate&lt;/em&gt; items in a menu or tool bar. &lt;a href="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/StylingSeparatorsinWPF_9A7D/separators_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;margin:4px 0px 0px 8px;border-right-width:0px;" height="149" alt="Examples of Separators" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/StylingSeparatorsinWPF_9A7D/separators_thumb.png" width="197" align="right" border="0" /&gt;&lt;/a&gt;The intention is to divide the items on the menu or toolbar into logical groups. &lt;a title="MSDN documentation" href="http://msdn.microsoft.com/en-us/library/system.windows.controls.separator.aspx" target="_blank"&gt;Separators&lt;/a&gt; are controls, but they don&amp;#39;t have any real behavior.&lt;/p&gt; &lt;p&gt;One of our current projects includes an exhaustive custom styling of a WPF application.&amp;nbsp; Last week, I was working on the top level menu as well as context menus.&amp;nbsp; I wanted all of my separators to look the same.&amp;nbsp; So I ignorantly created a style, the same way that I would for any other control. It looked something like this:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;!-- Separator --&amp;gt;
&amp;lt;Style TargetType=&amp;quot;Separator&amp;quot;&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Height&amp;quot; Value=&amp;quot;1&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Template&amp;quot;&amp;gt;
        &amp;lt;Setter.Value&amp;gt;
            &amp;lt;ControlTemplate TargetType=&amp;quot;{x:Type Separator}&amp;quot;&amp;gt;
                &amp;lt;Rectangle Height=&amp;quot;{TemplateBinding Height}&amp;quot;
                           Fill=&amp;quot;{StaticResource NormalBorderBrush}&amp;quot; /&amp;gt;
            &amp;lt;/ControlTemplate&amp;gt;
        &amp;lt;/Setter.Value&amp;gt;
    &amp;lt;/Setter&amp;gt;
&amp;lt;/Style&amp;gt;

&lt;/pre&gt;
&lt;p&gt;In case you&amp;#39;re not familiar with it, WPF allows to specify a default style for a control by setting the &lt;strong&gt;TargetType&lt;/strong&gt; and omitting the &lt;strong&gt;x:Key&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;But that doesn&amp;#39;t work for separators.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The reason is that &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.menuitem.aspx" target="_blank"&gt;MenuItem&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.toolbar.aspx" target="_blank"&gt;ToolBar&lt;/a&gt; both use separators, and thus creating global style for both wouldn&amp;#39;t make sense. (At least, I&amp;#39;m guessing that&amp;#39;s what the designers of WPF were thinking.) Instead, both of these MenuItem and ToolBar expose a static property, &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.menuitem.separatorstylekey.aspx" target="_blank"&gt;SeparatorStyleKey&lt;/a&gt;. This acts as the key for locating the corresponding separator style.&lt;/p&gt;
&lt;p&gt;If you want to style the separators for all menu items, your need to set&lt;strong&gt; x:Key&lt;/strong&gt; to this static property. The resulting style would look like this:&lt;/p&gt;&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;!-- Separator --&amp;gt;
&amp;lt;Style x:Key=&amp;quot;{x:Static MenuItem.SeparatorStyleKey}&amp;quot;  
       TargetType=&amp;quot;{x:Type Separator}&amp;quot;&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Height&amp;quot; Value=&amp;quot;1&amp;quot; /&amp;gt;
    &amp;lt;Setter Property=&amp;quot;Template&amp;quot;&amp;gt;
        &amp;lt;Setter.Value&amp;gt;
            &amp;lt;ControlTemplate TargetType=&amp;quot;{x:Type Separator}&amp;quot;&amp;gt;
                &amp;lt;Rectangle Height=&amp;quot;{TemplateBinding Height}&amp;quot;      
                           Fill=&amp;quot;{StaticResource NormalBorderBrush}&amp;quot; /&amp;gt;
            &amp;lt;/ControlTemplate&amp;gt;
        &amp;lt;/Setter.Value&amp;gt;
    &amp;lt;/Setter&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=41037" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210236" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/06/19/styling-separators-in-wpf.aspx</feedburner:origLink></item><item><title>ALT.Consultancy: Reflections on doing it my way</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210237/alt-consultancy-reflections-on-doing-it-my-way.aspx</link><pubDate>Sun, 18 May 2008 23:48:32 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:40622</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>7</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=40622</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/05/18/alt-consultancy-reflections-on-doing-it-my-way.aspx#comments</comments><description>&lt;p&gt;Awhile back there was some &lt;a href="http://tech.groups.yahoo.com/group/altdotnet/message/4540" target="_blank"&gt;discussion&lt;/a&gt; on the new &lt;a href="http://tech.groups.yahoo.com/group/altdotnet/" target="_blank"&gt;ALT.NET list&lt;/a&gt; about what it would be like to start a consultancy with a bunch ALT.NET minded people. The hypothetical scenario proposed there wasn&amp;#39;t &lt;em&gt;quite&lt;/em&gt; what I did, but I thought I&amp;#39;d go ahead and share my experiences and how we addressed (or are still addressing) some of the problems in running a business like this.&lt;/p&gt; &lt;h4&gt;The Background&lt;/h4&gt; &lt;p&gt;&lt;a href="http://devlicio.us/blogs/rob_eisenberg/default.aspx" target="_blank"&gt;Rob Eisenberg&lt;/a&gt; and I founded our company &lt;a href="http://www.bluespire.com/" target="_blank"&gt;Blue Spire&lt;/a&gt; in October 2006. We were long time friends, and had worked together for about two years prior to starting the company. In that time, we were learning about &lt;a title="Manifesto for Agile Software Development" href="http://www.agilemanifesto.org/" target="_blank"&gt;Agile&lt;/a&gt; in general, as well as patterns, TDD, OR/M, the myriad of awesome OSS tools, etc.&amp;nbsp; We didn&amp;#39;t know it, but we were developing a &lt;em&gt;culture&lt;/em&gt; between the two of us&lt;em&gt;. &lt;/em&gt;The elements of this culture included:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;continuous learning  &lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/magazine/cc135988.aspx" target="_blank"&gt;passion for our craft&lt;/a&gt;&amp;nbsp; &lt;li&gt;learning to &amp;quot;&lt;a href="http://www.extremeprogramming.org/rules/collective.html" target="_blank"&gt;code without ego&lt;/a&gt;&amp;quot;  &lt;li&gt;excitement about &amp;quot;doing things better&amp;quot; and discovering &amp;quot;better practices&amp;quot;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;We started our consulting firm with the belief that we could deliver quality, human friendly software in less time and for less cost that the majority of other firms. (The genesis of this thought occurred over a decade ago when I was subcontracting for a large consulting shop, working on an 18 month project with a team of around 25. I&amp;#39;m sure I was pretty cocky back then, but I felt at the time that a team of 5 could have delivered more in less than a year.) &lt;/p&gt; &lt;p&gt;We began with just the two of us, and we envisioned growing to a team of 4 to 6. &lt;a title="&amp;quot;Getting Real&amp;quot; is a must read..." href="http://gettingreal.37signals.com/ch08_Hire_Less_and_Hire_Later.php" target="_blank"&gt;Smaller is better&lt;/a&gt;. Even at the beginning though, we felt that consulting was just a stepping stone to something else.&lt;/p&gt; &lt;h4&gt;Kicking It Off&lt;/h4&gt; &lt;p&gt;The question was asked on the list if such a shop could compete.&amp;nbsp; What kind of sales and marketing would you need? How do you break in and demonstrate to potential clients that you can provide a better value than super consulting company X?&lt;/p&gt; &lt;p&gt;We&amp;#39;ve had zero down time since we started, and we&amp;#39;ve had almost zero sales and marketing efforts.&amp;nbsp; We started off having lunch with other software development shops in the area. We told them what we were doing (without being derogatory) and we talked about overflow work, and subcontracting. There&amp;#39;s enough business out there that the competition is pretty friendly.&amp;nbsp; We also offered ourselves at very, very reasonable rate. (We&amp;#39;re now charging double from what we started, and we&amp;#39;re probably going to raise our rates again this year.)&lt;/p&gt; &lt;p&gt;The majority of our clients have been other software shops. What&amp;#39;s cool is that they saw our value pretty quickly. What&amp;#39;s bad is that we were sometimes restricted from using the practices and tools that we wanted.&lt;/p&gt; &lt;p&gt;We also decided it was important to connect with the local developer community. Both for our own continuing professional development, but also for growing the reputation of our company. Rob has especially put in efforts to speak at Code Camps, and the &lt;a href="http://capitalcitydotnet.net/dotnetnuke/" target="_blank"&gt;local user group&lt;/a&gt;. It helps that we are genuinely excited about sharing. (This even helped us land a really fun agile coaching gig for the internal development team of a state agency.)&lt;/p&gt; &lt;h4&gt;Convincing Clients&lt;/h4&gt; &lt;p&gt;We&amp;#39;ve focused on Scrum for project management, and we were lucky to have a client who was already intent on using it. Nonetheless, even that client (who was not a software shop) required a statement of work. We estimated as best we could, and the client agreed that the SOW was a target and not a guarantee. &lt;/p&gt; &lt;p&gt;In our &amp;quot;sales pitch&amp;quot;, we tell clients that software development in inherently unpredictable. We contrast &amp;quot;release early, release often&amp;quot; with &amp;quot;throwing the spec over the wall&amp;quot;.&amp;nbsp; (There&amp;#39;s usually a lot of resonance if they&amp;#39;ve had software developed before.) We (cautiously) explain to them that no one really knows exactly what they need up front. Change is inevitable.&lt;/p&gt; &lt;h4&gt;What Really Happens&lt;/h4&gt; &lt;p&gt;Our projects have usually taken one of the following forms:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The client budgets a set amount of hours.&amp;nbsp; We provide a conservative statement of what we think can be accomplished in that time.&amp;nbsp; We explicitly qualify the risks as soon as they are known. &lt;br /&gt;We get the client to buy into the project, by allowing them to manage the priorities for each iteration in the project (usually 2 - 4 weeks). In this way, they share the responsibility with us for hitting the desired target.&lt;br /&gt;Because of the iterative nature, they are aware of risks and problems early.&lt;/li&gt; &lt;li&gt;Some client are too deeply rooted in the idea of &amp;quot;build me X, in Y hours, for Z dollars&amp;quot;.&amp;nbsp; We try to avoid that situation, but we&amp;#39;ve been there.&amp;nbsp; When that occurs we greatly exaggerate the hours (3x or 4x).&amp;nbsp; Funny enough, the exaggerated estimate is often within the client&amp;#39;s expectations.&amp;nbsp; We&amp;#39;ve alternately benefited and been burned by this arrangement.&amp;nbsp; I don&amp;#39;t like to do it this way.&lt;/li&gt; &lt;li&gt;This last arrangement is a mixture of the other two, and it&amp;#39;s only been useful for periods where we would would have been between projects and when a client has some flexibility in scheduling.&amp;nbsp; Essentially, we budget some initial time to size tasks.&amp;nbsp; Again we pad the hours to mitigate risk, and then we allow the client to pick and choose the tasks.&amp;nbsp; We commit to delivering an individual task for the number of hours we estimated, but we are not committed to delivering the entire project for a set amount.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The first option is preferred and honestly it is the one that provides the most cost effectiveness for the client.&amp;nbsp; We only use the other arrangements when the client isn&amp;#39;t comfortable with the first.&lt;/p&gt; &lt;h4&gt;Some Final Thoughts&lt;/h4&gt; &lt;p&gt;Here&amp;#39;s a few additional observations:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Having the right clients is paramount.&amp;nbsp; You want a genuine trust relationship.&amp;nbsp; We had one project where trust was eroded (if it was ever present on their side) and it was by far the most stress I&amp;#39;ve had in years.&amp;nbsp; It&amp;#39;s hard to turn down business, but sometimes you really need too.&lt;/li&gt; &lt;li&gt;Scheduling is difficult. Managing the pipeline is one of the more difficult tasks in managing a small shop.&amp;nbsp; &lt;em&gt;When is this project really going to be over? What if the client wants to extend? How much downtime can we afford? At what point are we over extended?&lt;br /&gt;&lt;/em&gt;Everyone that I&amp;#39;ve talked to that has a small project-based business seems to have the same difficulty.&amp;nbsp; So far, we haven&amp;#39;t made any clients mad, but we&amp;#39;ve had a few periods of &lt;a title="My goal is to eliminate this." href="http://www.extremeprogramming.org/rules/overtime.html" target="_blank"&gt;overtime&lt;/a&gt;.&amp;nbsp; This would be easier if we were a larger company, but size has many disadvantages too.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I&amp;#39;m a developer at heart, and running a business has been challenging (and distracting). So I&amp;#39;d love to hear from anyone else who is doing this sort of thing. &lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=40622" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210237" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Agile/default.aspx">Agile</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ALT.NET/default.aspx">ALT.NET</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Business/default.aspx">Business</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/05/18/alt-consultancy-reflections-on-doing-it-my-way.aspx</feedburner:origLink></item><item><title>The Roots of Best Practices</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210238/the-roots-of-best-practices.aspx</link><pubDate>Sun, 30 Mar 2008 17:55:54 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:39866</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=39866</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/03/30/the-roots-of-best-practices.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;ve been asked about best practices and good design several times over the last few months. A few questions have been from students, or newcomers to .NET, and I have found their questions very insightful. They ask questions I remember asking myself. One good example was &amp;quot;I know I should separate my app into three layers, but how should I do it?&amp;quot;&lt;/p&gt; &lt;p&gt;&lt;img height="159" alt="Getting to the Roots" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/666c277b84dc_C83F/iStock_000004023495XSmall_4.jpg" width="240" align="right" /&gt;I&amp;#39;m rather to sensitive to the idea of &amp;quot;answering the wrong question&amp;quot;. I believe that it&amp;#39;s easy to do that when talking about best practices.&amp;nbsp; My intention with this post is build a foundation for discussing good design. A starting point to make sure we are solving the right riddle. I certainly don&amp;#39;t consider myself a &lt;a href="http://www.pragprog.com/the-pragmatic-programmer" target="_blank"&gt;master&lt;/a&gt; on this topic, but I do have a lot of thoughts.&lt;/p&gt; &lt;h4&gt;Acknowledging My Bias&lt;/h4&gt; &lt;p&gt;I&amp;#39;m a fan of &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming" target="_blank"&gt;Object Orient Programming&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design" target="_blank"&gt;Domain-Driven Design&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Design_patterns" target="_blank"&gt;Design Patterns&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Test_Driven_Development" target="_blank"&gt;Test Driven Development&lt;/a&gt;, and &lt;a href="http://en.wikipedia.org/wiki/Agile_software_development" target="_blank"&gt;agile methodologies&lt;/a&gt;. I use a lot of &lt;a title="This is my stack at Ohloh." href="http://www.ohloh.net/accounts/10381/stacks/14905" target="_blank"&gt;open source software&lt;/a&gt;, and I&amp;#39;m &lt;a href="http://www.hanselminutes.com/default.aspx?showID=122" target="_blank"&gt;ALT.NET&lt;/a&gt;. Foremost, I like to think that I am pragmatic.&amp;nbsp;&amp;nbsp; I&amp;#39;m motivated by getting stuff done.&lt;/p&gt; &lt;h4&gt;The Point of Best Practices&lt;/h4&gt; &lt;p&gt;There are a long list of principles out that are generally acknowledged as best practices. They range from generalities like &amp;quot;your code should be well commented&amp;quot; to very specific and named rules such as the &lt;a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle" target="_blank"&gt;Liskov substitution principle&lt;/a&gt;. Regardless of the type, I think it&amp;#39;s important to know why a given principle is better than its alternatives.  &lt;p&gt;I&amp;#39;ll use the &lt;a href="http://en.wikipedia.org/wiki/Law_Of_Demeter" target="_blank"&gt;Law of Demeter&lt;/a&gt; (LoD) as an example. Overly simplified, the law says that an object should only invoke methods that it owns.&amp;nbsp; In other words, you&amp;#39;ll break the law with &lt;span class="mono"&gt;something.child.Method()&lt;/span&gt; whereas &lt;span class="mono"&gt;something.Method()&lt;/span&gt; does not.&amp;nbsp; &lt;p&gt;Why is LoD good? One quick answer is that you never know when &lt;span class="mono"&gt;something.child&lt;/span&gt; might be &lt;span class="mono"&gt;null&lt;/span&gt;, and applying LoD helps you avoid the nasty &lt;a href="http://msdn2.microsoft.com/en-us/library/system.nullreferenceexception.aspx" target="_blank"&gt;NullReferenceException&lt;/a&gt;. Wikipedia has a nice summary the benefits:  &lt;blockquote&gt; &lt;p&gt;The advantage of following the Law of Demeter is that the resulting software tends to be more maintainable and adaptable. Since objects are less dependent on the internal structure of other objects, object containers can be changed without reworking their callers.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now we are approaching the real heart of the matter, we want software that is easy to maintainable, and easy to extend. LoD promotes those values. In facts, most of the generally accepted principles are meant to produce software that is &lt;em&gt;maintainable and extensible&lt;/em&gt;. Here is my &lt;a title="physics is fun!" href="http://en.wikipedia.org/wiki/Grand_unification_theory" target="_blank"&gt;Grand Unification Theory&lt;/a&gt; of software best practices: the guiding, or root, principles are &lt;strong&gt;Maintainability&lt;/strong&gt; and &lt;strong&gt;Extensibility&lt;/strong&gt;. (These two are close cousins, and you might arguably combine them.)&lt;/p&gt; &lt;div class="sidebar"&gt;Okay, so maybe there are other guiding principles as well, such as &lt;strong&gt;Scalability&lt;/strong&gt; and &lt;strong&gt;Performance&lt;/strong&gt;. I&amp;#39;d even add that the most important root principle is &lt;strong&gt;Value&lt;/strong&gt;. By Value, I mean that the &lt;em&gt;software needs to do what the user wants done&lt;/em&gt;.&amp;nbsp; So maybe, Maintainability and Extensibility are just like electromagnetism and the weak nuclear force of good software design.&lt;/div&gt; &lt;h4&gt;The Root of the Matter&lt;/h4&gt; &lt;p&gt;Now, let&amp;#39;s deconstruct further.&amp;nbsp; Why do we care about Maintainability and Extensibility? We care because they result in &lt;em&gt;reduced costs&lt;/em&gt;.&amp;nbsp; The bulk of cost with custom software is &lt;em&gt;not&lt;/em&gt; building it, &lt;a href="http://csdl2.computer.org/persagen/DLAbsToc.jsp?resourcePath=/dl/proceedings/&amp;amp;toc=comp/proceedings/icsm/1997/8013/00/8013toc.xml&amp;amp;DOI=10.1109/ICSM.1997.624229" target="_blank"&gt;but&lt;/a&gt; &lt;a href="http://users.jyu.fi/~koskinen/smcosts.htm" target="_blank"&gt;maintaining&lt;/a&gt; &lt;a href="http://portal.acm.org/citation.cfm?id=595256.595312&amp;amp;dl=GUIDE&amp;amp;dl=GUIDE&amp;amp;CFID=9723890&amp;amp;CFTOKEN=67507506" target="_blank"&gt;it&lt;/a&gt;. If you are in business, reduced costs equals more money; if you are a hobbyist or open source developer then reduced costs means getting to the desired result in less time.&amp;nbsp; That&amp;#39;s the bottom line: &lt;em&gt;time and money&lt;/em&gt;. We employ best practices to save ourselves time and money.&lt;/p&gt; &lt;p&gt;Okay, well, nothing new here. You probably already knew this.&amp;nbsp; I emphasize it though because I&amp;#39;ve found that &amp;quot;best practices&amp;quot; have a tendency to degrade into a set of arbitrarily applied rules, enforced without exception, irrespective of whether or not they are useful. A great example is &amp;quot;always comment your code&amp;quot;. The intention of this rule is improve maintainability.&amp;nbsp; We&amp;#39;ve all seen the end result. &lt;/p&gt;&lt;pre&gt;//open the file 
FileStream stream = File.Open(pathToFile, FileMode.Open);&lt;/pre&gt;
&lt;p&gt;Does this improve maintainability? Perhaps if you can&amp;#39;t read C#, but even then it seems unlikely. Does one extraneous little comment hurt? Not by itself. A poppy flower is beautiful, a thousand poppies is dangerous. If 50% of your source is extraneous comments, it&amp;#39;s nothing but noise and it&amp;#39;s reducing maintainability.&lt;/p&gt;
&lt;h4&gt;My Point&lt;/h4&gt;
&lt;p&gt;Let&amp;#39;s take a look at the question I was asked again:&lt;/p&gt;
&lt;p&gt;&amp;quot;I know I should separate my app into three layers, but how should I do it?&amp;quot;&lt;/p&gt;
&lt;p&gt;To answer this correctly, we need to start with the motivation for layering an application in the first place. &amp;quot;Three-tier architecture&amp;quot; has a good intention, just as &amp;quot;well commented code&amp;quot; does. However, the principle has can easily be lost in the arbitrary application of the rule. &lt;/p&gt;
&lt;p&gt;In a soon-to-follow post, I&amp;#39;ll examine this specific question of layering an application from its roots.&lt;/p&gt;
&lt;h4&gt;Epilogue&lt;/h4&gt;
&lt;p&gt;For some reading in the meantime, check out the &lt;a href="http://lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspx" target="_blank"&gt;series of posts&lt;/a&gt; over at Los Techies on SOLID Principles. There is some great discussion in the comments too.&lt;/p&gt;
&lt;p&gt;What do you think?&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=39866" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210238" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Design+Patterns/default.aspx">Design Patterns</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Software+Architecture/default.aspx">Software Architecture</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Best+Practices/default.aspx">Best Practices</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/03/30/the-roots-of-best-practices.aspx</feedburner:origLink></item><item><title>Thoughts on ALT.NET</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210239/thoughts-on-alt-net.aspx</link><pubDate>Sat, 15 Mar 2008 21:39:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:39678</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>6</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=39678</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/03/15/thoughts-on-alt-net.aspx#comments</comments><description>&lt;p&gt;I just listened to &lt;a href="http://www.hanselminutes.com/default.aspx?showID=122" target="_blank"&gt;Scott Hanselman interviewing Dave Laribee&lt;/a&gt; regarding &lt;a href="http://altdotnet.org/" target="_blank"&gt;ALT.NET&lt;/a&gt;. I really like what Dave had to say, and I encourage everyone to go and listen.&amp;nbsp; I&amp;#39;ve been reticent about the ALT.NET movement (aside from my initial surge of enthusiasm.) I&amp;#39;m a bit shy when it comes to controversy, and even though I have strong evangelistic tendencies, I am also quick to shut up. ALT.NET has had its &lt;a href="http://altnetpursefight.blogspot.com/" target="_blank"&gt;share&lt;/a&gt; of &lt;a href="http://samgentile.com/blogs/samgentile/archive/2007/10/06/goodbye-codebetter-and-alt-net.aspx" target="_blank"&gt;controversy&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/ThoughtsonALT.NET_EF75/RWS2-Big_2.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="92" alt="Now we&amp;#39;re an institution!" src="http://devlicious.com/blogs/christopher_bennage/WindowsLiveWriter/ThoughtsonALT.NET_EF75/RWS2-Big_thumb.png" width="240" align="right" border="0" /&gt;&lt;/a&gt;I really like that Dave said &lt;em&gt;it&amp;#39;s not about the tools, it&amp;#39;s about the principles&lt;/em&gt;.&amp;nbsp; I am frequently asked about &amp;quot;good design&amp;quot; and &amp;quot;best practices&amp;quot;.&amp;nbsp;&amp;nbsp; This is why I&amp;#39;m ALT.NET. (In fact, I have a series of posts on this topic that I intend to start after we&amp;#39;re done with the &lt;a title="Sams Teach Yourself WPF in 24 Hours -- preorder yours today! :-)" href="http://www.amazon.com/Sams-Teach-Yourself-WPF-Hours/dp/0672329859" target="_blank"&gt;book&lt;/a&gt;.)&lt;/p&gt; &lt;p&gt;There&amp;#39;s an item in the interview that I&amp;#39;d like to comment on.&lt;/p&gt; &lt;p&gt;Scott asks (pardon my paraphrasing) why would the hypothetical &lt;a title="Is he (or she) a real person?" href="http://www.nfs.unl.edu/" target="_blank"&gt;Chief Architect of the Nebraska Department of Forestry&lt;/a&gt; have any interest in ALT.NET? The mythical Mort has pressing concerns, he just needs to get work done, why would he care about these conversations, discussions, and principles? Listen to the podcast for Dave&amp;#39;s answer.&amp;nbsp; However, my answer is this: &lt;em&gt;he probably doesn&amp;#39;t care and that&amp;#39;s okay&lt;/em&gt;. I think that ALT.NET is about bringing good design and principle to the forefront.&amp;nbsp; However, good ideas take a while to be adopted, to be democratized.&amp;nbsp; Those who are hungry, we&amp;#39;ll feed.&amp;nbsp; Those who aren&amp;#39;t, we&amp;#39;ll wish them well.&amp;nbsp; No hard feelings. Eventually, the good ideas will be institutionalized and they&amp;#39;ll trickle down. (Have you noticed the &amp;quot;refactor&amp;quot; menu in Visual Studio?) I&amp;#39;m more concerned about convincing the institutions and the thought leaders.&amp;nbsp; (Perhaps &amp;quot;convincing&amp;quot; is the wrong word, ALT.NET is more about &amp;quot;conversing&amp;quot; to me.) That&amp;#39;s why it&amp;#39;s good that ALT.NET is conversing with Microsoft, and that&amp;#39;s also why I&amp;#39;m encouraged to see Microsoft paying attention to things like open source (though I know many people are angry about the kind of attention being paid).&lt;/p&gt; &lt;p&gt;Now go learn &lt;a title="One-Click Ruby Installer for Windows" href="http://rubyinstaller.rubyforge.org/wiki/wiki.pl" target="_blank"&gt;Ruby&lt;/a&gt;!&amp;nbsp; :-)&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=39678" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210239" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Agile/default.aspx">Agile</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Musings/default.aspx">Musings</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ALT.NET/default.aspx">ALT.NET</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/03/15/thoughts-on-alt-net.aspx</feedburner:origLink></item><item><title>Identifying Control Templates Parts in WPF</title><link>http://feeds.feedburner.com/~r/ChristopherBennage/~3/338210240/identifying-control-templates-parts-in-wpf.aspx</link><pubDate>Mon, 10 Mar 2008 01:28:36 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:39618</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=39618</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2008/03/09/identifying-control-templates-parts-in-wpf.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;m currently writing the chapter about control templates in our &lt;a href="http://www.amazon.com/Sams-Teach-Yourself-WPF-Hours/dp/0672329859/" target="_blank"&gt;WPF book&lt;/a&gt;, and I wanted to include a list of all of the named parts that are hidden away in the dark recesses of the various controls.&amp;nbsp; Before I even started googling, I had an idea that I thought I&amp;#39;d share.&lt;/p&gt; &lt;p&gt;For those of you not yet familiar with control templates, WPF allows you to redefine the visual appearance of controls. The problem is that some of the controls have special named parts, that is, there are visual elements with specific names that the code expects to be there.&amp;nbsp; Luckily, there is the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.templatepartattribute.aspx" target="_blank"&gt;TemplatePartAttribute&lt;/a&gt; that&amp;#39;s meant to decorate controls with named parts. If you look at the documentation for a &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.controls.stickynotecontrol.aspx" target="_blank"&gt;given control,&lt;/a&gt; the attributes are listed and you&amp;#39;ll know what named elements a new template requires.&lt;/p&gt; &lt;p&gt;Given an assembly though, it&amp;#39;s quite easy to identify the controls programmatically. Here&amp;#39;s some C# that does just that:&lt;/p&gt;&lt;pre class="c-sharp:nogutter:nocontrols" name="code"&gt;using System;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;

namespace TemplatesParts
{
    class Program
    {
        static void Main()
        {
            var assembly = Assembly.GetAssembly(typeof (Control));
            var attributeType = typeof (TemplatePartAttribute);

            var controls = from c in assembly.GetTypes()
                           where c.GetCustomAttributes(attributeType, false).Length &amp;gt; 0
                           orderby c.Name
                           select new {c.Name,Parts=c.GetCustomAttributes(attributeType, false)};

            foreach (var control in controls)
            {
                Console.WriteLine(control.Name);
                foreach (var part in control.Parts)
                {
                    Console.WriteLine( &amp;quot;   &amp;quot; + ((TemplatePartAttribute)part).Name);
                }
            }
            Console.ReadLine();
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;Now, if I can just look this up in the documentation, why bother with this code? It was fun, what can I say?&lt;/p&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=39618" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/338210240" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/C_2300_/default.aspx">C#</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2008/03/09/identifying-control-templates-parts-in-wpf.aspx</feedburner:origLink></item></channel></rss>
