<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns: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 style="float:left;"&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;
&lt;div style="float:right;"&gt;follow &lt;a href="http://twitter.com/bennage"&gt;@bennage&lt;/a&gt; on Twitter!&lt;/div&gt;
&lt;div style="clear:both;"&gt;
 
&lt;/div&gt;
</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/ChristopherBennage" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>More On Caliburn &amp; Silverlight’s SaveFileDialog</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/3bb5TkauaNc/more-on-caliburn-amp-silverlight-s-savefiledialog.aspx</link><pubDate>Tue, 06 Oct 2009 21:20:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:52302</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=52302</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/10/06/more-on-caliburn-amp-silverlight-s-savefiledialog.aspx#comments</comments><description>&lt;p&gt;I was a bit hasty in my &lt;a title="self referencing is what I do best" href="http://devlicious.com/blogs/christopher_bennage/archive/2009/09/25/saving-files-from-silverlight-using-caliburn.aspx"&gt;earlier post&lt;/a&gt; when I called the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.savefiledialog(VS.95,loband).aspx"&gt;SaveFileDialog&lt;/a&gt; inadequate.&lt;/p&gt;  &lt;p&gt;One complaint I was going to make was simply a matter of my ignorance. It had to do with &lt;a href="http://stackoverflow.com/questions/1355078/dialogs-must-be-user-initiated-with-savefiledialog-in-silverlight-3"&gt;the dialog thinking that it was not initiated by the user&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;In particular, it was some of our &lt;a title="free WPF and Silverlight from the stone" href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt; magic obscuring this. However, it’s powerful white magic that does more good than harm. :-)&lt;/p&gt;  &lt;p&gt;The problem is this, the SaveFileDialog can only be shown as a result of a user’s action, such as clicking a button. (I’m sure this is driven by security concerns that aren’t entirely clear to me.)&lt;/p&gt;  &lt;p&gt;If your code follows this sequence:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;user clicks a button &lt;/li&gt;    &lt;li&gt;the event handler initiates a web request &lt;/li&gt;    &lt;li&gt;the callback for the web request tries to show a SaveFileDialog &lt;/li&gt;    &lt;li&gt;the world ends (not with a bang) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Then you will get the “Dialogs must be user-initiated” exception, because Silverlight doesn’t trace the web request callback back to the button click.&lt;/p&gt;  &lt;h3&gt;Deep Magic&lt;/h3&gt;  &lt;p&gt;In regards to the Caliburn magic that obscures this, I had a method that looked something like this:&lt;/p&gt;  &lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public IEnumerable&amp;lt;IResult&amp;gt; DownloadFile()
{
    var result = new Result();
    var query = new GetBinaryContent(_data.ContentId);
    yield return new ProcessQuery(query, result);

    if (result.HasErrors)
    {
        yield return Show.Errors(result);
        yield break;
    }

    var saveFileResult = new SaveFile();
    yield return saveFileResult;

    if (saveFileResult.FileStream == null) yield break;

    var content = result.FindResponse(query).Data;
    using (var writer = new BinaryWriter(saveFileResult.FileStream))
    {
        writer.Write(content);
        writer.Flush();
    }
}&lt;/pre&gt;

&lt;p&gt;This method lives on the ViewModel, and _data is part of that model. It contains the metadata for a file (name, type, last updated) as well as an id for fetching the actual binary content.&lt;/p&gt;

&lt;p&gt;First, it processing a query, which is actually an asynchronous web request. If there are errors then it displays them, otherwise it opens a save file dialog. If the users provides a file, then the binary content is written out. The problem here, that is not obvious, is that the save dialog is being opened as a result of the web request and not directly from the user’s click. If I reorder the code in the method, so that the save dialog is shown before processing the query then the exception goes away. In other words, the code below does not throw an exception.&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public IEnumerable&amp;lt;IResult&amp;gt; DownloadFile()
{
    //open the dialog _before_ the web request
    var saveFileResult = new SaveFile();
    yield return saveFileResult;

    if (saveFileResult.FileStream == null) yield break;

    var result = new Result();
    var query = new GetBinaryContent(_data.ContentId);
    yield return new ProcessQuery(query, result);

    if (result.HasErrors)
    {
        yield return Show.Errors(result);
        yield break;
    }

    var content = result.FindResponse(query).Data;
    using (var writer = new BinaryWriter(saveFileResult.FileStream))
    {
        writer.Write(content);
        writer.Flush();
    }
}&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;N.B. All of these implementations of IResult are specific to our project and are not a core part of Caliburn. However, Rob is creating similar (and improved) versions of a few in the samples.&lt;/em&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=52302" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/3bb5TkauaNc" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/10/06/more-on-caliburn-amp-silverlight-s-savefiledialog.aspx</feedburner:origLink></item><item><title>thinking out loud: asp.net mvc &amp; nhaml</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/4X33cpowIZc/thinking-out-loud-asp-net-mvc-amp-nhaml.aspx</link><pubDate>Fri, 02 Oct 2009 20:48:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:51989</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>9</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=51989</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/10/02/thinking-out-loud-asp-net-mvc-amp-nhaml.aspx#comments</comments><description>&lt;p&gt;I’ve been playing around with the view engine &lt;a title=".NET implementation of the popular Rails Haml view engine" href="http://code.google.com/p/nhaml/" target="_blank"&gt;nhaml&lt;/a&gt; and asp.net mvc. At the same time, I’m playing around with some architectural ideas in hope to benefit future projects.&lt;/p&gt;  &lt;p&gt;I’m not doing any fancy yet, but I thought that it might be interesting to show you a couple of things to see what you think. Bear in mind, this is my sandbox code. I also suspect that I’m reinventing some wheels.&lt;/p&gt;  &lt;p&gt;The context here is a page that allows a user to register for an account on the site.&lt;/p&gt;  &lt;p&gt;First, the view looks like this:&lt;/p&gt;  &lt;pre&gt;%h2 Create Account

%form{method=&amp;quot;post&amp;quot;}
  = Html.FormField&amp;lt;OpenAccount&amp;gt;(x=&amp;gt;x.AccountName)
  = Html.FormField&amp;lt;OpenAccount&amp;gt;(x=&amp;gt;x.EmailAddress)
  = Html.FormField&amp;lt;OpenAccount&amp;gt;(x=&amp;gt;x.Password)
  
  %input {type=&amp;quot;submit&amp;quot; value=&amp;quot;Save&amp;quot;}
  %button {onclick=&amp;quot;javascript:history.back()&amp;quot; type=&amp;quot;button&amp;quot;} Cancel&lt;/pre&gt;

&lt;p&gt;OpenAccount is my view model. (I hate how we’ve overloaded these&amp;#160; terms.)&lt;/p&gt;

&lt;p&gt;I really like the succinctness of the nhaml, though I’m not ready to commit to it 100%. &lt;a href="http://dev.dejardin.org/" target="_blank"&gt;Spark&lt;/a&gt; is very attractive to me as well.&lt;/p&gt;

&lt;p&gt;Html.FormField is an extension method I wrote. I’m toying with the idea of having it emit a &amp;lt;lablel /&amp;gt; paired with the &amp;lt;input /&amp;gt;. Part of my motivation here is standardizing all of the label/inputs in my forms as well as a few experimental ideas about localization. &lt;/p&gt;

&lt;p&gt;It’s rather naive at the moment, but here is the helper:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public static string FormField&amp;lt;T&amp;gt;(this HtmlHelper helper, Expression&amp;lt;Func&amp;lt;T, string&amp;gt;&amp;gt; property)
    where T : class, ICommand
{
    var model = helper.ViewData.Model as T;
    if (helper.ViewData.Model != null &amp;amp;&amp;amp; model == null) throw new InvalidOperationException();

    var expression = (MemberExpression)property.Body;
    var name = expression.Member.Name;

    var value = (model == null)
                    ? null
                    : property.Compile().Invoke(model);

    return helper.TextBox(name, value);
}&lt;/pre&gt;

&lt;p&gt;Yeah, I hardcoded to a textbox for the moment. As I said, this is just a sandbox spike.&lt;/p&gt;

&lt;p&gt;Finally, the associated controller action looks like this:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(OpenAccount form)
{
    var result = _backend.Execute(form);

    return result.Success
               ? (ActionResult) RedirectToAction(&amp;quot;WhateverIsNext&amp;quot;)
               : View(result);
}&lt;/pre&gt;

&lt;p&gt;I’m treating the incoming form as a command. The _backend is responsible for processing the command. The command is just information necessary to execute the command, not the logic to execute it. The result I’m getting back is actually an instance of the same command with information attached by the backend (e.g., did the command execute correctly, what were the validation errors). It’s not exactly &lt;a title="single responsibility principle" href="http://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank"&gt;SRP&lt;/a&gt;, however I’m influenced by the simplicity of RoR here. &lt;/p&gt;

&lt;p&gt;One more interesting bit. I really don’t like having actions in my controller that do nothing other than render the view. For example:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Create()
{
    return View();
}&lt;/pre&gt;

&lt;p&gt;So instead, I created a base controller that does this:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public class ControllerBase : Controller
{
    protected override void HandleUnknownAction(string actionName)
    {
        try
        {
            View(actionName).ExecuteResult(ControllerContext);
        }
        catch (InvalidOperationException e)
        {
            //show the error or something
        }
    }
}&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=51989" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/4X33cpowIZc" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/MVC/default.aspx">MVC</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/nhaml/default.aspx">nhaml</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/10/02/thinking-out-loud-asp-net-mvc-amp-nhaml.aspx</feedburner:origLink></item><item><title>Are Value Converters Evil?</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/RfmYfczpGKo/are-value-converters-evil.aspx</link><pubDate>Thu, 01 Oct 2009 05:17:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:51934</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>7</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=51934</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/10/01/are-value-converters-evil.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://blogs.silverlight.net/blogs/justinangel/"&gt;Justin Angel&lt;/a&gt; (who is undoubtedly a Silverlight Rock Star) decided to stir things up a bit on Twitter the other night.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img style="border-right-width:0px;display:block;float:none;border-top-width:0px;border-bottom-width:0px;margin-left:auto;border-left-width:0px;margin-right:auto;" title="Worst practices in WPF/Silverlight: Value Converters, MultiBindings, Triggers, Markup Extensions, Element to Element binding. Talk." border="0" alt="Worst practices in WPF/Silverlight: Value Converters, MultiBindings, Triggers, Markup Extensions, Element to Element binding. Talk." src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/image_5F00_682188A6.png" width="454" height="280" /&gt;&lt;/p&gt;  &lt;p&gt;I was compelled to echo &lt;a href="http://twitter.com/wardbell/status/4489534009"&gt;Ward Bell’s response&lt;/a&gt; that value converters can play legitimate role in the UI. Justin asked me to defend my position; a reasonable request. Now, I know that I am in the minority for maintaining this position. Many heavy hitters in the WPF community think &lt;a href="http://groups.google.com/group/wpf-disciples/browse_thread/thread/3fe270cd107f184f"&gt;MVVM does away with value converters&lt;/a&gt;. (I am not going to talk about the other bits here, just value converters.)&lt;/p&gt;  &lt;h3 style="direction:rtl;"&gt;בְּרֵאשִׁית&lt;/h3&gt;  &lt;p&gt;One of the early WPF examples that got my attention was &lt;a title="I don&amp;#39;t think this is the original example" href="http://richapps.wordpress.com/2009/02/12/advanced-styling-wpf/"&gt;a listbox that was styled to look like a map of the United States&lt;/a&gt;. What impressed me in this sample was the &lt;em&gt;separation of Behavior from Feel&lt;/em&gt;. I’m using the word “feel” with a very specific meaning. We often talk about Look and Feel. I think Look is shallow and Feel is deep. You can change the look of a listbox by changing the colors, the borders, the thickness of the lines, the icon that activates the dropdown, and so on. However, even by changing all of those, it stills &lt;em&gt;feels&lt;/em&gt; like a listbox. Now, once you’ve made that “listbox” into a map of a country you’ve done something deeper. You’ve changed the Feel. Pretty significantly too, I’d say.&lt;/p&gt;  &lt;p&gt;But even with the radical feeling map-listbox, one thing you haven’t changed is the Behavior. The semantics of a listbox are still in effect. Show a list of items and allow one to be selected.&lt;/p&gt;  &lt;p&gt;But alas, those primeval glories of WPF were drowned out in the drones of “where’s my datagrid?”.&lt;/p&gt;  &lt;h3&gt;Seeking Abstractions&lt;/h3&gt;  &lt;p&gt;&lt;a title="yes, he does not have a Twitter account" href="http://devlicious.com/blogs/rob_eisenberg"&gt;Rob Eisenberg&lt;/a&gt; and I were early adopters of WPF. At the same time, we were also in the feverish rush of applying Design Patterns to everything. You know, that phase of adoption where you’ve learned how to hammer and everything’s a nail. Still, it was good for us. We were digging through &lt;a href="http://martinfowler.com/eaaDev/PresentationModel.html"&gt;Fowler’s&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx"&gt;Gossman’s&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/dancre/archive/2006/10/11/datamodel-view-viewmodel-pattern-series.aspx"&gt;Crevier’s&lt;/a&gt; blogs. These sources began to shape my conceptions of ViewModel (or Presentation Model or Your Mama Model), however I was still deeply influenced by my lingering notion about the separation of Behavior and Feel.&lt;/p&gt;  &lt;p&gt;The result of this is that my idea of a ViewModel is a representation of the Behavior of the View. However, the ViewModel is agnostic about the Feel. This means I don’t build “formatting” and such into my ViewModel. I try to keep my ViewModels as “pure” and abstract as possible. This also means that I rarely take strong dependencies on WPF and Silverlight.&lt;/p&gt;  &lt;p&gt;Why go to such extremes? What’s the benefit?&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;My Fantasy World&lt;/h3&gt;  &lt;p&gt;There’s a lot of talk about &lt;a title="User Experience" href="http://en.wikipedia.org/wiki/User_experience_design"&gt;UX&lt;/a&gt; lately, and perhaps more fittinhly, &lt;a href="http://en.wikipedia.org/wiki/Interaction_design"&gt;Interaction Design&lt;/a&gt; (IxD). In reality, I fiind that there are few people are actually doing IxD. Although, I think that’s the audience that Expression Blend is targeted at (do you recall &lt;a href="http://blogs.msdn.com/tims/archive/2006/01/24/516706.aspx"&gt;what Blend was originally named&lt;/a&gt;?). These chimerical Interaction Designers are the ones that would benefit the most from this proposed separation of Behavior and Feel. &lt;/p&gt;  &lt;p&gt;Let’s imagine a we’re building a WPF application. Harkening back to that old, impressive sample of yesteryear, the behavior we need in our app is to “allow the user to select a state”. As a developer, we can create a ViewModel that embodies that behavior, we can test the ViewModel, and even build a simple, naive View (testing that the required bindings are present with &lt;a title="free WPF and Silverlight from the stone" href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt; thank you). Then we can hand it over to an interaction designer. The designer can then radically alter the Feel without changing the Behavior. In fact, if we’re using something like Caliburn’s testability framework (not available in Silverlight unfortunately), these IxD peeps can exercise a great deal of liberty in establishing the most appropriate feel for the behavior.&lt;/p&gt;  &lt;p&gt;Unfortunately, our typical approach to software development inhibits IxD’ers from working this way. The Feel is often deeply entangled in the presentation logic (or worse).&lt;/p&gt;  &lt;h3&gt;Context&lt;/h3&gt;  &lt;p&gt;I’m sure that a large majority of WPF developers might see these distinction as useless. Especially, when building Line Of Business applications. &lt;strong&gt;That’s okay&lt;/strong&gt;. Not everyone needs to do this. Many projects don’t need the additional complexity that might be introduced by thinking in this way. However, I think this is an emerging field and UX/IxD will be increasingly important. Soon it will be the distinguishing factor in commercial software.&lt;/p&gt;  &lt;h3&gt;Wait, Wasn’t This About Value Converters&lt;/h3&gt;  &lt;p&gt;Yes, and here is how they fit in. Let’s take my &lt;a href="http://devlicio.us/blogs/christopher_bennage/archive/2009/08/22/answer-the-user-s-questions.aspx"&gt;current favorite example of formatting dates&lt;/a&gt;. We have a behavior that requires communicating some date/time information to the user. Applying my philosophy to our ViewModel, the developer should expose the raw data (an actual DateTime property) on the ViewModel and leave the rest up to the IxD’er. After careful consideration, research and usability testing, the designer decides the dates need to be formatted as “[x time ago]”. (See the &lt;a href="http://devlicio.us/blogs/christopher_bennage/archive/2009/08/22/answer-the-user-s-questions.aspx"&gt;referenced post&lt;/a&gt; if that doesn’t make sense.) The designer,&lt;span title="if this is fantasy, why not go all the way"&gt; who can likely write a bit of code&lt;/span&gt;, creates a value converter to format the date value as the Feel demands.&lt;/p&gt;  &lt;p&gt;Secondly, we could conceivably have multiple Views in an application for a single ViewModel. Each View would have a different Feel, and the application (or the user) could select the most appropriate (or comfortable one). &lt;/p&gt;  &lt;p&gt;&lt;em&gt;Incidentally, when I first learned about MVC it was in the context of writing a &lt;/em&gt;&lt;a title="notice the date on this puppy!" href="http://www.adobe.com/devnet/flashcom/articles/minesweeper.html" target="_blank"&gt;&lt;em&gt;minesweeper game in Flash&lt;/em&gt;&lt;/a&gt;&lt;em&gt; where the user could switch between an isometric and top-down view.&lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;In the End&lt;/h3&gt;  &lt;p&gt;In real life, we’re not very close to this. There are few IxD’ers out there and most teams don’t need to be concerned about this. That means that for most practical purposes the Simplest Thing to Do &lt;em&gt;might &lt;/em&gt;be to forego value converters and hard code formatting in the ViewModel. Value converters, just like anything else, can be abused.&lt;/p&gt;  &lt;p&gt;Nevertheless, I definitely do &lt;em&gt;not&lt;/em&gt; consider them a worse practice.&lt;/p&gt;  &lt;p&gt;If you think I’m wrong, speak up. I am willing to listen. If you’ve been burned by the use of value converters, please share.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=51934" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/RfmYfczpGKo" 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/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UI/default.aspx">UI</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/XAML/default.aspx">XAML</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UX/default.aspx">UX</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/viewmodel/default.aspx">viewmodel</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/mvvm/default.aspx">mvvm</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/10/01/are-value-converters-evil.aspx</feedburner:origLink></item><item><title>Saving Files from Silverlight (using Caliburn)</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/n5uexU9JPlw/saving-files-from-silverlight-using-caliburn.aspx</link><pubDate>Fri, 25 Sep 2009 19:30:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:51747</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=51747</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/09/25/saving-files-from-silverlight-using-caliburn.aspx#comments</comments><description>&lt;p&gt;We’ve been working on a Silverlight project that could be classified as a Line Of Business application (whatever that means).&lt;/p&gt;  &lt;p&gt;There have been a few places where we need to allow users to save files. First, I thought I might give you a peek as to how we do this with &lt;a title="free WPF and Silverlight from the stone" href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt; .&lt;/p&gt;  &lt;p&gt;Imagine that we are displaying a table of data and that we are allowing the user to export that data to a csv file and save it to their desktop.&lt;/p&gt;  &lt;h3&gt;How We Do It&lt;/h3&gt;  &lt;p&gt;In the view, I have a button that looks like this:&lt;/p&gt;  &lt;pre class="xml:nogutter:nocontrols" name="code"&gt;&amp;lt;Button pf:Message.Attach=&amp;quot;Export&amp;quot; 
        Content=&amp;quot;Export Data&amp;quot;&amp;gt;&lt;/pre&gt;

&lt;p&gt;pf is defined as &lt;/p&gt;

&lt;pre class="xml:nogutter:nocontrols" name="code"&gt;xmlns:pf=&amp;quot;clr-namespace:Caliburn.PresentationFramework;assembly=Caliburn.PresentationFramework&amp;quot;&lt;/pre&gt;

&lt;p&gt;You can read more about Message.Attach in the &lt;a href="http://caliburn.codeplex.com/Wiki/View.aspx?title=Action%20Basics&amp;amp;referringTitle=Home"&gt;Caliburn documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The view is associated with a view model, and that view model has a method:&lt;/p&gt;

&lt;pre class="C#:nogutter:nocontrols" name="code"&gt;public IEnumerable&amp;lt;IResult&amp;gt; Export()
{
    var saveFileResult = new SaveFile { DefaultExt = &amp;quot;csv&amp;quot; };
    yield return saveFileResult;

    if (saveFileResult.FileStream == null) yield break; //null means the user clicked ‘Cancel’

    var content = FormatAsCsv();

    using (var writer = new StreamWriter(saveFileResult.FileStream))
    {
        writer.Write(content);
        Caliburn.Core.Invocation.Execute.OnUIThread(writer.Close);  
    }
}&lt;/pre&gt;

&lt;p&gt;The Message.Attach in the view binds the button to this method on our view model. IResult is a &lt;a href="http://blogs.msdn.com/ericlippert/archive/2009/07/09/iterator-blocks-part-one.aspx"&gt;poor man’s coroutine&lt;/a&gt; and you can read more about it &lt;a href="http://caliburn.codeplex.com/Wiki/View.aspx?title=IResult&amp;amp;referringTitle=Home"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It’s not that obvious when discussing the save file scenario, but this approach is really useful when dealing with asynchronous actions, such as interacting with a web service. Also by using the SaveFile abstraction, we could more easily test this method. (Though newing it up here sort of nullifies that, but I digress.)&lt;/p&gt;

&lt;p&gt;But what is the SaveFile class anyway?&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public class SaveFile : IResult
{
    public string Filter { get; set; }
    public string DefaultExt { get; set; }

    public string SafeFileName { get; private set; }
    public Stream FileStream { get; private set; }

    public void Execute(IRoutedMessageWithOutcome message, IInteractionNode handlingNode)
    {
        var dlg = new SaveFileDialog
        {
            Filter = Filter,
            DefaultExt = DefaultExt,
        };

        if (dlg.ShowDialog().GetValueOrDefault(false))
        {
            FileStream = dlg.OpenFile();
            SafeFileName = dlg.SafeFileName;
        }

        Completed(this, null);
    }

    public event Action&amp;lt;IResult,Exception&amp;gt; Completed = delegate { };
}&lt;/pre&gt;

&lt;p&gt;It a simple abstract for opening and managing the SaveFileDialog. If you want to know more, check out the Caliburn documentation and sample (or harass &lt;a title="master of time and space" href="http://devlicious.com/blogs/rob_eisenberg"&gt;Rob Eisenberg&lt;/a&gt; to post more). Rob also had an &lt;a title="really more of a teaser" href="http://devlicio.us/blogs/rob_eisenberg/archive/2009/07/10/asynchronous-execution-animation-and-more-in-mvvm-with-caliburn.aspx"&gt;introductory post on IResult&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Coming Soon&lt;/h3&gt;

&lt;p&gt;My rant about Silverlight’s inadequate SaveFileDialog.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=51747" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/n5uexU9JPlw" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/mvvm/default.aspx">mvvm</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/09/25/saving-files-from-silverlight-using-caliburn.aspx</feedburner:origLink></item><item><title>Designer Wanted</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/htefKd2kVXs/designer-wanted.aspx</link><pubDate>Tue, 22 Sep 2009 16:30:25 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:51618</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=51618</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/09/22/designer-wanted.aspx#comments</comments><description>&lt;p&gt;We need to contract a designer for our current project. I’m looking for one of those mythical beasts that has:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;some real graphics design skill&lt;/li&gt;    &lt;li&gt;understands (or at least cares about) usability&lt;/li&gt;    &lt;li&gt;works with Silverlight&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There is also a strong preference for someone in the NYC/NJ area.&lt;/p&gt;  &lt;p&gt;If you are interested or know someone who qualifies, please contact me through the blog.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=51618" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/htefKd2kVXs" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UI/default.aspx">UI</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UX/default.aspx">UX</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Usability/default.aspx">Usability</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Awesome+Opportunity/default.aspx">Awesome Opportunity</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/09/22/designer-wanted.aspx</feedburner:origLink></item><item><title>Source Control Presentation</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/-LZNsx764YE/source-control-presentation.aspx</link><pubDate>Tue, 01 Sep 2009 21:33:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:51098</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=51098</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/09/01/source-control-presentation.aspx#comments</comments><description>&lt;p&gt;I want to thank everyone that came out to my session at the &lt;a href="http://www.jaxcodecamp.com/" target="_blank"&gt;Jacksonville Code Camp&lt;/a&gt;. I had a great time and it was definitely worth the drive.&lt;/p&gt;  &lt;p&gt;Here are my slides from the presentation. They are really only useful with the accompanying notes, with are available on the &lt;a href="http://www.slideshare.net/bennage/source-control-concepts" target="_blank"&gt;slideshare site&lt;/a&gt;. You have to select to “Notes on slide X” tab underneath the presentation to see them. (I wish there was an option to embed the notes, but I didn’t see it.)&lt;/p&gt;  &lt;p&gt;I want to acknowledge &lt;a href="http://www.kuemerle.com/" target="_blank"&gt;Joe Kuemerle&lt;/a&gt; whose &lt;a href="http://www.kuemerle.com/index.php/Archived/devlink2009presentations.html" target="_blank"&gt;Get Rid of VSS presentation&lt;/a&gt; was helpful. Also, &lt;a href="http://www.ericsink.com/scm/source_control.html" target="_blank"&gt;Eric Sink&lt;/a&gt; whose blog influenced a great deal of the content.&lt;/p&gt;  &lt;p&gt;As always, any feedback is greatly appreciated.&lt;/p&gt;  &lt;div style="text-align:left;width:425px;" id="__ss_1937044"&gt;&lt;object style="margin:0px;" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=sourcecontrolconcepts-090901091409-phpapp02&amp;amp;rel=0&amp;amp;stripped_title=source-control-concepts" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always" /&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=sourcecontrolconcepts-090901091409-phpapp02&amp;amp;rel=0&amp;amp;stripped_title=source-control-concepts" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=51098" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/-LZNsx764YE" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/source+control/default.aspx">source control</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Presentations/default.aspx">Presentations</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/svn/default.aspx">svn</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Tools/default.aspx">Tools</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/09/01/source-control-presentation.aspx</feedburner:origLink></item><item><title>My Solid State Sorrow</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/55WMoV2dm00/ssd-vs-mobo.aspx</link><pubDate>Mon, 31 Aug 2009 11:44:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:50949</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=50949</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/31/ssd-vs-mobo.aspx#comments</comments><description>&lt;p&gt;I recently installed a Solid State Disk, an &lt;a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16820167015" target="_blank"&gt;Intel X25-M&lt;/a&gt; to be precise, as my operating system disk. (It was time to upgrade to Windows 7!) Despite the fact that &lt;a href="http://www.joelonsoftware.com/items/2009/03/27.html" target="_blank"&gt;it would not really increase compiles times&lt;/a&gt;, I was very excited about the other anticipated performance improvements.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.imdb.com/title/tt0856797/" target="_blank"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="Solid State Society. I&amp;#39;m a fan of Ghost in the Shell, but I haven&amp;#39;t seen this one yet." border="0" alt="Solid State Society. I&amp;#39;m a fan of Ghost in the Shell, but I haven&amp;#39;t seen this one yet." align="right" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/gitssss_5F00_144BDFD4.jpg" width="170" height="240" /&gt;&lt;/a&gt; After the installation, I had Windows 7 and Visual Studio installed quickly; less than an hour I think. However, shortly after that, my machine froze. Then it froze again. &amp;lt;heart stop/&amp;gt;&lt;/p&gt;  &lt;p&gt;It was definitely a problem with the new drive. A little bit of research turned up that my motherboard, MSI P6N SLI Platinum, uses a chipset with a known problem. Specifically, the nForce 650i and 680i.&lt;/p&gt;  &lt;p&gt;By default, the SATA controllers on these boards have a featured enabled called &lt;em&gt;command queuing&lt;/em&gt;. This is the feature that causes the problem with the ssd. However, I could not find anywhere to disable this feature.&lt;/p&gt;  &lt;p&gt;There was speculation on some forums that upgrading to the latest firmware would fix everything. I did, and it didn’t.&lt;/p&gt;  &lt;p&gt;Needless to say, I was getting a little bit concerned.&lt;/p&gt;  &lt;h4&gt;The Solution&lt;/h4&gt;  &lt;p&gt;I had not installed any vendor-specific drivers. Since this was vendor specific feature, I reasoned that that using the NVIDIA drivers might allow me to disable command queuing. It did, and now my system has&lt;em&gt; four times&lt;/em&gt; as much awesome as previously.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Install the NVIDIA nForce drivers. &lt;/li&gt;    &lt;li&gt;In Device Manager, under &lt;em&gt;IDE ATA/ATAPI controllers&lt;/em&gt;, locate the &lt;em&gt;NVIDA nForce Serial ATA Controller&lt;/em&gt; associated with your SSD and click Properties. &lt;/li&gt;    &lt;li&gt;Switch to the tab for the port that the SSD is located on. &lt;/li&gt;    &lt;li&gt;Uncheck &lt;em&gt;Enable command queuing&lt;/em&gt;. You only need to do this for the SSD drive.&lt;/li&gt;    &lt;li&gt;Rejoice! &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/8302009124102AM_5F00_64306C66.png" target="_blank"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:block;float:none;margin-left:auto;border-top:0px;margin-right:auto;border-right:0px;" title="click to enlarge" border="0" alt="click to enlarge" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/8302009124102AM_5F00_thumb_5F00_57C2493D.png" width="465" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On a side note, I built my machine based on &lt;a title="and what a wonderful trip it&amp;#39;s been" href="http://www.hanselman.com/blog/TheCodingHorrorUltimateDeveloperRigThrowdownPart2.aspx" target="_blank"&gt;The Coding Horror Ultimate Developer Rig&lt;/a&gt;. That’s right kids, it is pure rock and roll.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=50949" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/55WMoV2dm00" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Hardware/default.aspx">Hardware</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/SoYouDontHaveToHurt/default.aspx">SoYouDontHaveToHurt</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/31/ssd-vs-mobo.aspx</feedburner:origLink></item><item><title>Build Notification, Visual Studio, &amp; Snarl</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/rTk1A00RmFw/build-notification-visual-studio-amp-snarl.aspx</link><pubDate>Thu, 27 Aug 2009 10:54:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:50749</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>8</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=50749</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/27/build-notification-visual-studio-amp-snarl.aspx#comments</comments><description>&lt;p&gt;I’m not talking about build notifications from a build server. Rather, I’m talking about times when you are building locally. It’s a big project and it takes 30 seconds. So… you &lt;a href="http://xkcd.com/477/" target="_blank"&gt;flip over&lt;/a&gt; to a web browser while you wait. Then you forget about it and waste another minute or two until you remember: oh yeah, I was building.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;margin-left:0px;border-left-width:0px;margin-right:0px;" title="Snarl!" border="0" alt="Snarl!" align="right" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/8262009113723AM_5F00_63FAA6A1.png" width="287" height="337" /&gt;Ok, maybe I’m the only who does that. &lt;/p&gt;  &lt;h4&gt;Notifications&lt;/h4&gt;  &lt;p&gt;I recently (re)discovered &lt;a href="http://www.fullphat.net" target="_blank"&gt;Snarl&lt;/a&gt;. It’s a small app, inspired by Growl for OSX, and is a generic provider for system tray notifications.&lt;/p&gt;  &lt;p&gt;I also found &lt;a href="http://snarlvs.assembla.com/wiki/show/snarlvs" target="_blank"&gt;this plugin for Visual Studio&lt;/a&gt; that notifies you when a build is finished.&lt;/p&gt;  &lt;p&gt;Funny enough, all the projects I am working on right now build quickly, so I don’t &lt;em&gt;really&lt;/em&gt; need this. I just like it.&lt;/p&gt;  &lt;h4&gt;Quirk&lt;/h4&gt;  &lt;p&gt;On Vista, I would get duplicate notifications. No problems on Windows 7.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=50749" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/rTk1A00RmFw" height="1" width="1"/&gt;</description><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/Tools/default.aspx">Tools</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/27/build-notification-visual-studio-amp-snarl.aspx</feedburner:origLink></item><item><title>Lacking Confidence</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/ZvoR3pTa7gg/lacking-confidence.aspx</link><pubDate>Tue, 25 Aug 2009 11:47:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:50665</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>15</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=50665</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/25/lacking-confidence.aspx#comments</comments><description>&lt;p&gt;One of my biggest professional hindrances is a lack of confidence. I don’t have a CS degree. In fact, I have almost zero technical academic training. (My degree is in Religious Studies). In addition, I hang out with a lot of very smart and motivated programming gurus. I tend to judge myself by what they are capable of, and hence I often fail at my own standard. Add this to the fact that we men have fragile egos and it’s not hard to see how I arrive at this lack of confidence.&lt;/p&gt;  &lt;p&gt;Last week Rob and I presented at the Orlando .NET User Group.&amp;#160; Walking back to the car afterwards, I was chatting with &lt;a href="http://scottdensmore.typepad.com/"&gt;Scott Densmore&lt;/a&gt;. He mentioned that he doesn’t blog as much as he would like because he’s not convinced that he has anything of value to say. At first this surprised me. If you know Scott, then you know that he has a lot of interesting things to say. In addition, he’s very good at saying them. However, after a moment’s reflection, I recognized that I think the same thing all the time.&lt;/p&gt;  &lt;h3&gt;What Others Think&lt;/h3&gt;  &lt;p&gt;Despite the fact that I don’t &lt;em&gt;officially&lt;/em&gt; care what others think, I frequently base my actions on the anticipated responses of others. :-P&lt;/p&gt;  &lt;p&gt;I am afraid of failing in front of my peers. This has become evident to me as I have worked on &lt;a href="http://www.nhprof.com/"&gt;NHProfiler&lt;/a&gt;. Ayende is something of a Rock Star in the .NET world (though he may not believe it). I was timid to commit code. He might look it. It would suck and then he would know I was an idiot. I mean, I know that I do dumb things all the time but I didn’t want to let that out.&lt;/p&gt;  &lt;p&gt;That is the wrong attitude. Instead, I need to open and transparent. What’s the worse that can happen? I write some bad code. We have to revert a commit and then I learn how to write better code. (Yeah, this did happen and I lived.)&lt;/p&gt;  &lt;h3&gt;Bias Towards Actions&lt;/h3&gt;  &lt;p&gt;Where am I going with all of this?&lt;/p&gt;  &lt;p&gt;We often talk about the value of &lt;a href="http://en.wikipedia.org/wiki/Fail-fast"&gt;Failing Fast&lt;/a&gt;. We want to surface problems as quickly as possible, so that we are able to address them sooner. We apply this to development tasks, to project management, and even to the way we structure code.&lt;/p&gt;  &lt;p&gt;Too often I have not acted, because I was afraid that I would seem stupid, irrelevant, or inadequate. My advice: don’t be afraid to act. Sure, you might fail but that’s okay. Actually, it’s more than okay. True failure is not in falling down, but in refusing to get back up. If you aren’t failing, then you probably aren’t accomplishing anything.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=50665" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/ZvoR3pTa7gg" height="1" width="1"/&gt;</description><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/Opinion/default.aspx">Opinion</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/25/lacking-confidence.aspx</feedburner:origLink></item><item><title>Answer the User’s Questions</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/alVqffTyXVk/answer-the-user-s-questions.aspx</link><pubDate>Sat, 22 Aug 2009 16:27:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:50188</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=50188</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/22/answer-the-user-s-questions.aspx#comments</comments><description>&lt;p&gt;One little usability bit that I picked up from many of the Web 2.0 apps (in particular 37signals apps), is displaying date and times in a “how long since” format.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.silverarcade.com/community"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="Community page on Silver Arcade" border="0" alt="Community page on Silver Arcade" align="right" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/8222009120042PM_5F00_3725CF83.png" width="356" height="353" /&gt;&lt;/a&gt;Take a look at the &lt;a href="http://www.silverarcade.com/community"&gt;community page&lt;/a&gt; on Silver Arcade. I wanted to display when a user became a member of the community. Instead of displaying the actual date that they signed up, I choose to convert that date to “how long ago”.&lt;/p&gt;  &lt;p&gt;At first I did this just because I liked it. Then it began to dawn on me that there are reasons that I like it.&lt;/p&gt;  &lt;h3&gt;Questions&lt;/h3&gt;  &lt;p&gt;One primary purpose of any UI is answering the user’s questions. “How much credit is left in this account?” “Is this customer currently active?” “How many days are left before this explodes?”&lt;/p&gt;  &lt;p&gt;Frequently, when we are displaying dates and times we are really trying to answer questions that begin with “how long ago did …” or “how soon until …”. &lt;/p&gt;  &lt;p&gt;When we display a simple date and time, such as&amp;#160; “August 22, 2009 12:11 PM”, we are providing raw data to the user, but we really aren’t answering their question. We’re leaving the final step up to them. That’s translating that raw data into a meaningful answer for their ‘how long’ question. Every translation has a cognitive cost.&lt;/p&gt;  &lt;p&gt;This may not seem like much, but the cognitive cost adds up very quickly. This can be one of those subtle points that makes two seemingly similar interfaces &lt;em&gt;feel&lt;/em&gt; so different.&lt;/p&gt;  &lt;p&gt;I’m not saying to display every date and time in your application in this format. Instead I am saying to ask “what question will my users have and am I really answering it”.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;To be fair, this is purely anecdotal and is not backed up with any empirical evidence.&lt;/em&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=50188" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/alVqffTyXVk" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UI/default.aspx">UI</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UX/default.aspx">UX</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Usability/default.aspx">Usability</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/22/answer-the-user-s-questions.aspx</feedburner:origLink></item><item><title>Speaking Schedule: August/September</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/hh42I8PVrbw/speaking-schedule-august-september.aspx</link><pubDate>Tue, 18 Aug 2009 14:00:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:50123</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=50123</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/18/speaking-schedule-august-september.aspx#comments</comments><description>&lt;h3&gt;&lt;strong&gt;August 20th, &lt;/strong&gt;&lt;em&gt;Case Study: &lt;/em&gt;&lt;em&gt;Silver Arcade &lt;/em&gt;&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.onetug.org/sf/Homepage.aspx" target="_blank"&gt;Orlando .NET User Group (ONETUG)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This will mostly be &lt;a href="http://devlicious.com/blogs/rob_eisenberg/" target="_blank"&gt;Rob&lt;/a&gt;, but I’m tagging along to offer witty banter. We’ll be discussing how we built &lt;a title="Silver Arcade, a free online gaming community" href="http://www.silverarcade.com/" target="_blank"&gt;Silver Arcade&lt;/a&gt; using ASP.NET MVC, Azure, NHibernate, jQuery, and more. &lt;/p&gt;  &lt;h3&gt;&lt;strong&gt;August 29th&lt;/strong&gt;, &lt;em&gt;Source Control with Subversion &lt;/em&gt;&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.jaxcodecamp.com/" target="_blank"&gt;Jacksonville Code Camp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This is a Getting Started session for those who don’t know much about source control. &lt;/p&gt;  &lt;h3&gt;September 5th &lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.tallycodecamp.org/2009" target="_blank"&gt;Tallahassee Code Camp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I’m not 100% certain what I’ll be doing here. However, we have an awesome lineup. If you are within driving distance, come spend your Labor Day weekend with us. It’s going to be a great event. &lt;/p&gt;  &lt;h3&gt;&lt;strong&gt;September 17th&lt;/strong&gt;, &lt;em&gt;Getting Started with NHibernate &lt;/em&gt;&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://tampadev.org/" target="_blank"&gt;Tampa Bay ASP.NET MVC SIG&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I’m really excited about this one. We’ll be discussing how to get started with NHibernate specifically within the context of ASP.NET MVC applications.&lt;/p&gt;  &lt;p&gt;If you attend any of these events, please stop and and introduce yourself. I really enjoy connecting with other developers. It’s half the fun of these events.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=50123" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/hh42I8PVrbw" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Events/default.aspx">Events</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/18/speaking-schedule-august-september.aspx</feedburner:origLink></item><item><title>Refactoring Relationships</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/tIQZSDLiXAA/refactoring-relationships.aspx</link><pubDate>Sun, 09 Aug 2009 01:45:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:49911</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=49911</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/08/refactoring-relationships.aspx#comments</comments><description>&lt;p&gt;Working with people is a lot like working with code. New relationships are green fields. Over time they become brown fields and (just like code) they require maintenance. I’m sure that everyone reading this can identify some legacy relationships that they would describer as, well, complicated. Just like some legacy code.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;margin-left:0px;border-left-width:0px;margin-right:0px;" title="working together" border="0" alt="working together" align="right" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/iStock_5F00_000000810058XSmall_5F00_15B7B6E6.jpg" width="191" height="240" /&gt;I mean a lot with the word ‘relationship’. I have in mind everything from co-workers to friends to significant others. These variations all require maintenance and I think we should deliberately structure our relationships so that maintenance is easier.&lt;/p&gt;  &lt;h3&gt;Interaction Smells&lt;/h3&gt;  &lt;p&gt;So what &lt;em&gt;is&lt;/em&gt; the social equivalent of a switch\case statement?&lt;/p&gt;  &lt;p&gt;We talk about &lt;a href="http://en.wikipedia.org/wiki/Code_smell" target="_blank"&gt;code smells&lt;/a&gt; in software development as suggestive indicators that something is wrong. In our relationships, it is &lt;em&gt;interaction smells&lt;/em&gt;. I would consider these common emotional responses to be smells:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;avoidance &lt;/li&gt;    &lt;li&gt;irritation &lt;/li&gt;    &lt;li&gt;suspicion &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Personally, I have been guilty of avoiding someone because I thought I would irritate them and I didn’t want the hassle. This was in a work environment and it a negative effect on the overall efficacy of the group. My impulse to avoid was a smell and it led to a problem that needed to be addressed.&lt;/p&gt;  &lt;h3&gt;Amicability Debt&lt;/h3&gt;  &lt;p&gt;Bad code gets worse over time. We call this &lt;a href="http://martinfowler.com/bliki/TechnicalDebt.html" target="_blank"&gt;technical debt&lt;/a&gt;. Relationships that have soured do not get better by themselves. Little fractures grow over time. If we don’t address them when we smell them, the stink only gets worse. In addition, the stinky relationship can be begin affecting other parts of design, uh I mean, other social interactions (e.g., the team you are working with).&lt;/p&gt;  &lt;h3&gt;Refactoring the Relationship&lt;/h3&gt;  &lt;p&gt;Relationships are more difficult to work with than code for one primary reason:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;You cannot revert back to the last revision if your changes fail.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Nevertheless, we often need to make changes. Refactoring code doesn’t change the exposed functionality, but we make internal changes to improve it. If you are beginning to have problems with your boss, that doesn’t necessarily mean it’s time to quit (change the function) rather you might just need some relational refactoring.&lt;/p&gt;  &lt;p&gt;But what do I mean by refactoring a relationship? Well, there’s a lot to be said there and you can find a lot of practical advice on dealing with conflict and more over on &lt;a href="http://www.stevenlist.com/blog/" target="_blank"&gt;“Doc” List’s blog&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;In brief though, I mean this: &lt;/p&gt;  &lt;p&gt;Be honest and humble. “Hey, Joe, I feel like you’ve been a bit on edge with me. Did I do something to frustrate you? I’d like to clear the air.” Then talk it over. Again, refer to Doc’s blog for lots of details.&lt;/p&gt;  &lt;p&gt;I would like to qualify this further. Since you cannot revert what you say and do, you must be deliberate and thoughtful about your refactoring.&lt;/p&gt;  &lt;h3&gt;Afterword&lt;/h3&gt;  &lt;p&gt;You can see where my brain has been lately. It’s the cross-pollination of ideas from software development into all other human interests. Next week: multithreading and Italian cooking, followed up by ALT.NET and comparative religion.&lt;/p&gt;  &lt;p&gt;If any of this resonates with you, you might be interested in &lt;span title="it&amp;#39;s a Christian perspective on marriage, but I do have Justice Gray&amp;#39;s support."&gt;(a possibly controversial)&lt;/span&gt; post regarding the &lt;a href="http://blog.bennage.com/2008/07/de-matrimonium.html" target="_blank"&gt;maintenance of marriage&lt;/a&gt; on my personal blog.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=49911" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/tIQZSDLiXAA" 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/Best+Practices/default.aspx">Best Practices</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/2009/08/08/refactoring-relationships.aspx</feedburner:origLink></item><item><title>Agile Living</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/FtFyBdp3SzI/agile-living.aspx</link><pubDate>Wed, 05 Aug 2009 03:14:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:49842</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=49842</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/04/agile-living.aspx#comments</comments><description>&lt;p&gt;I yearn to be consistent. I want my professional values to be the same as my personal ones. This is why I was quick to sign the &lt;a href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt;; it aligned with my personal values.&lt;/p&gt;  &lt;p&gt;&lt;img style="display:inline;margin-left:0px;margin-right:0px;" title="The 4-Hour Workweek" alt="The 4-Hour Workweek" align="right" src="http://ecx.images-amazon.com/images/I/51FSaZaVA3L._SS500_.jpg" width="240" height="240" /&gt;I have been overcommitted for the last couple of months and the stress has forced me to do some professional reevaluation. I had&amp;#160; a number of entrepreneurial and professional books on my back log. One of the book was &lt;a href="http://www.amazon.com/4-Hour-Workweek-Escape-Live-Anywhere/dp/0307353133"&gt;The 4-Hour Workweek&lt;/a&gt; by Timothy Ferriss.&lt;/p&gt;  &lt;p&gt;I really like this book.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;That’s nice, Christopher. Thanks for sharing. What does this have to do with software development?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Not a&amp;#160; lot. Perhaps. But I think it has a lot to do with the philosophy of Agile.&lt;/p&gt;  &lt;h3&gt;Eschew BDUF&lt;/h3&gt;  &lt;p&gt;One of the first ideas in the book is that the notion that retirement is a bit silly. We spend forty something odd years saving up money to retire and for what? How do we really know what to save up for? Do we honestly know what our requirements for old age will be? The standard cultural approach to professional life is Waterfall. We spend so much time building our product, and we have one big rollout.&lt;/p&gt;  &lt;h3&gt;Iterative Design&lt;/h3&gt;  &lt;p&gt;I recently watched the film &lt;a href="http://en.wikipedia.org/wiki/Holiday_(1938_film)"&gt;Holiday&lt;/a&gt; with Cary Grant and Katharine Hepburn. In the movie, a young and savvy Johnny Case (Grant) struggles between Doing Business (because that’s sensible) and taking time off to figure out what he &lt;em&gt;wants&lt;/em&gt; out of life. Ferris makes a similar proposition in the book. He suggests planning mini-retirements. It’s a release often, release early approach to life. Discover what you want you by trying things out. It’s Life in Sprints.&lt;/p&gt;  &lt;h3&gt;Illusion of Slackness&lt;/h3&gt;  &lt;p&gt;Agile has had a bad rep for being unstructured and lacking in discipline. Of course, practitioners of Agile know the&lt;em&gt; exact opposite&lt;/em&gt; is the case (and let that be a life lesson in itself). One of the things I love about Agile is the focus on delivering value. Likewise, my initial perception of the book was that it was a guide for the lazy; just another Get Rich Quick scheme. No, it’s about being deliberate with your life. It’s not a book that most people can use, because it requires disciple.&lt;/p&gt;  &lt;h3&gt;Eliminate Waste&lt;/h3&gt;  &lt;p&gt;If I’m being technical, I guess I would say that this is a Lean principle. However, Lean and Agile are complimentary ingredients in the tossed salad that is my head. Ferris applies this principle to all of life. It’s a beautiful thing. There’s a lot of waste in our lives, hidden under the veil of busyness. Find it and eliminate it. Repeat. &lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;Okay, so I guess this turned out to be a book review of a non-technical book. If any of this stirs your brain, then I recommend that you read the book. If you are compelled by the ideas of Agile or Continuous Improvement, read the book.&lt;/p&gt;  &lt;p&gt;My Advice: be deliberate with your life, your professional, and your time.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="right"&gt;“… the unexamined life is not worth living…”      &lt;br /&gt;Socrates, &lt;a href="http://www.gutenberg.org/etext/1656"&gt;Plato’s Apology&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p align="right"&gt;“Whatever your hand finds to do, do it with all your might, for in the grave, where you are going, there is neither working nor planning nor knowledge nor wisdom.”&lt;/p&gt;    &lt;p align="right"&gt;&lt;a title="That&amp;#39;s another name for Ecclesiates. I&amp;#39;m just trying to make you curious." href="http://www.biblegateway.com/passage/?search=Ecclesiastes%209:10;&amp;amp;version=31;"&gt;Kohelet 9:10&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=49842" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/FtFyBdp3SzI" 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/Opinion/default.aspx">Opinion</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/08/04/agile-living.aspx</feedburner:origLink></item><item><title>One day with Balsamiq Mockups: a review</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/2fyhWqW8Clo/one-day-with-balsamiq-mockups-a-review.aspx</link><pubDate>Fri, 19 Jun 2009 04:03:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:47989</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>7</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=47989</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/06/19/one-day-with-balsamiq-mockups-a-review.aspx#comments</comments><description>&lt;p&gt;We’ve just started a new Silverlight project and since &lt;strike&gt;our&lt;/strike&gt; &lt;em&gt;the&lt;/em&gt; &lt;a title="if you don&amp;#39;t believe, just ask him!" href="http://ayende.com/about-me.aspx"&gt;UI guy&lt;/a&gt; is not on site with us, I ended up with the task of producing screen mockups. Some interest was expressed in using &lt;a href="http://www.balsamiq.com/"&gt;Balsamiq Mockups&lt;/a&gt;, and this seemed like a good time to really take it for a&amp;#160; test drive.&lt;/p&gt;  &lt;h3&gt;What does it do?&lt;/h3&gt;  &lt;p&gt;Balsamiq is a tool for quickly authoring mockups of applications and websites. My favorite tool for doing mockups is pencil and paper (turns out that it’s really, really good). However, we needed something that we could readily show during a review meeting and my sketches don’t photocopy well.&lt;/p&gt;  &lt;p&gt;Nevertheless, I did my brainstorming on paper and I used it for my first round of reviews with the team. This left me with about a dozen pages storyboarding the core of our application. &lt;/p&gt;  &lt;p&gt;After the first review, I began recreate it with Balsamiq.&lt;/p&gt;  &lt;p&gt;In Balsamiq you start with a blank, gridded canvas and drag various UI elements from a library onto the canvas. It reminds me of Visio a bit, but without so much pain. All of the elements are styled to look like hand-drawn. This is important because it prevents anyone from assuming that the application is “done” when you’re just presenting mockups.&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="making a web page with Balsamiq" border="0" alt="making a web page with Balsamiq" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/Untitled1_5F00_016725E9.jpg" width="646" height="667" /&gt; &lt;/p&gt;  &lt;p&gt;The elements in Balsamiq are impressively intelligent. Most elements allow you to type in some content and they react intuitively to that content. I was amazed a couple of time at how smartly they responded. Balsamiq ships with about 75 elements in its library and there are more &lt;a href="http://www.mockupstogo.net/"&gt;being posted&lt;/a&gt; all the time. You cannot really extend the library yourself however, though you can incorporate your own images.&lt;/p&gt;  &lt;p&gt;Each mockup screen is a single file. They are XML so it’s source control friendly. If you are mocking up an entire application (like I was) you can link the files together. Many of the elements have a link property that you can point to any other Balsamiq files in the same directory. Once you’ve linked up some files, you can “run” your mockups in presentation mode. This allows you to navigate around the application and toggle annotations (like the sticky note in my screen shot). The presentation mode is really cool.&lt;/p&gt;  &lt;h3&gt;Should you buy it?&lt;/h3&gt;  &lt;p&gt;I think that mocking up the UI is a very useful exercise. It helps to expose the behavior of the application that you are going to build and surfaces many insights into what it &lt;em&gt;really&lt;/em&gt; needs to do. I still prefer to use paper and pencil for the initial pass. However, I found that following this up with Balsamiq forced me to think through the entire flow of my appplication. My paper storyboards had holes in them that I did not realize until I attempted to express them in Balsamiq.&lt;/p&gt;  &lt;p&gt;The reviewers were really excited to see the Balsamiq mockups and being able to walk them through the application was a definite plus for them. The tool is easy to use. I would say that any &lt;strike&gt;designer&lt;/strike&gt; developer doing UI work should be using a tool like Balsamiq.&lt;/p&gt;  &lt;p&gt;What it offers for $79 is really hard to beat. Admittedly, I don’t know what other tools are out there and how they compare. By itself, I think it definitely worth it for anyone doing UI work.&lt;/p&gt;  &lt;p&gt;Of course, there is SketchFlow. It is coming. I think that SketchFlow looks very promising, especially for us XAML guys, but it’s not available yet. I’ll let you know what I think about the overlap once I get a change to actually use SketchFlow.&lt;/p&gt;  &lt;h3&gt;Little Things&lt;/h3&gt;  &lt;p&gt;I had a couple of annoyances that are worth pointing out. &lt;/p&gt;  &lt;p&gt;First, you cannot create reusable components. For example, I had certain elements of the application that appeared in several places. I had to clone these elements, but when I needed to change them, I had to make the change in each element. (Another reason to start with pencil).&lt;/p&gt;  &lt;p&gt;I think that it would also be nice if there was a “back button” in presentation mode. Within my mockup I had a few screens that you could get too in multiple ways, however I did not have an easy way of returning the the previous screen.&lt;/p&gt;  &lt;p&gt;I also get the impression that the community around Balsamiq likes to poke fun at us PC guys. I smile politely.&lt;/p&gt;  &lt;p&gt;Finally, Balsamiq likes to keep all of the linked files open. You’ll notice an excessive number of tabs on the bottom of the screen shot. Those are all the screens within the application I was mocking. It became a little difficult to find that right one.&lt;/p&gt;  &lt;p&gt;On the whole, Balsamiq is a smart application and I expect to see great things as it matures. Many of its features are intuitive and “just work”, and that’s how I like my software to roll.&lt;/p&gt;  &lt;pre&gt;:-P&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=47989" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/2fyhWqW8Clo" height="1" width="1"/&gt;</description><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/development+tools/default.aspx">development tools</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UI/default.aspx">UI</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UX/default.aspx">UX</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/06/19/one-day-with-balsamiq-mockups-a-review.aspx</feedburner:origLink></item><item><title>The Influence of MVC on my WPF</title><link>http://feedproxy.google.com/~r/ChristopherBennage/~3/iMG4OD_4kvA/the-influence-of-mvc-on-my-wpf.aspx</link><pubDate>Wed, 06 May 2009 19:48:01 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:46528</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>9</slash:comments><wfw:commentRss>http://devlicious.com/blogs/christopher_bennage/rsscomments.aspx?PostID=46528</wfw:commentRss><comments>http://devlicious.com/blogs/christopher_bennage/archive/2009/05/06/the-influence-of-mvc-on-my-wpf.aspx#comments</comments><description>&lt;p&gt;I was introduced to MVC as a pattern for Web development through &lt;a href="http://www.castleproject.org/monorail/" target="_blank"&gt;Castle MonoRail&lt;/a&gt;. From there I studied a bit of &lt;a href="http://rubyonrails.org/" target="_blank"&gt;Ruby on Rails&lt;/a&gt; (not enough) as well as the general philosophy of &lt;a href="http://www.37signals.com/" target="_blank"&gt;37signals&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;As I mentioned before, I thought I was moving away from Web development. However, the dive into ASP.NET MVC that &lt;a title="Silver Arcade, a free online gaming community" href="http://www.silverarcade.com/" target="_blank"&gt;Silver Arcade&lt;/a&gt; brought about has roped me back in.&lt;/p&gt;  &lt;p&gt;My work during the day (and some nights too) is still WPF though. I’ve discovered that MVC thinking has seeped into my WPF development.&lt;/p&gt;  &lt;h3&gt;Convention Over Configuration&lt;/h3&gt;  &lt;p&gt;A characteristic of most MVC frameworks is &lt;a href="http://en.wikipedia.org/wiki/Convention_over_Configuration" target="_blank"&gt;Convention Over Configuration&lt;/a&gt;. In short, it means that your “environment” makes assumptions about what you want and that you only need to be explicit about the exceptions.&lt;/p&gt;  &lt;p&gt;A practical example of this is the way that the View for an Action is inferred from the name of the Controller and Action. After creating your Action, you create a folder for the controller and and view that matches the name of the action. It just works. If you need to make exception, you can.&lt;/p&gt;  &lt;h3&gt;An Example in WPF&lt;/h3&gt;  &lt;p&gt;In our WPF development we employ a number of &lt;a title="I strongly dislike the term MVVM." href="http://msdn.microsoft.com/en-us/library/cc707862.aspx" target="_blank"&gt;Separated Presentation&lt;/a&gt; patterns. One of the more common patterns we use is MVP (in particular, the flavor of MVP implemented in &lt;a title="free WPF and Silverlight from the stone" href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt;, which is really Supervising Controller).&lt;/p&gt;  &lt;p&gt;Imagine a simple contact manager application. We can add new contacts, view a list of all contacts, and open individual contacts for viewing or editing. We can open as many individual contacts as we like.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="mvc" border="0" alt="mvc" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/mvc_5F00_313933F1.png" width="539" height="511" /&gt; &lt;/p&gt;  &lt;p&gt;Let’s say that there are buttons to open up the “Add New” view and “All Contacts” view. We can open an existing contact by double-clicking on them in the “All Contacts” view. &lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width:0px;margin:0px 8px 0px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="my imaginary solution" border="0" alt="my imaginary solution" align="left" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/56200930845PM_5F00_24D92471.png" width="271" height="341" /&gt;My solution setup for this imaginary (and highly contrived) application might look like this.&lt;/p&gt;  &lt;p&gt;ApplicationPresenter would be the root object of my UI. It would have an ObservableCollection of IPresenter that would be bound to a TabControl in Shell.xaml. Likewise, ApplicationPresenter will have a CurrentPresenter of IPresenter that will be bound to the SelectedItem on the TabControl. &lt;/p&gt;  &lt;p&gt;Shell.xaml is my only window in this example. All of the other views are user controls. I named it “shell” because I think of it as the outermost level of the views. Shell’s data context is set to ApplicationPresenter.&lt;/p&gt;  &lt;p&gt;I’m not going to dive too much deeper into this, because I want to get to my real point.&lt;/p&gt;  &lt;p&gt;My presenters don’t know anything about their views. It’s up to data binding to render each presenter with the correct view. This means that I need to create data templates for each of the presenters. Not such a big deal in a small application, but it can get tedious as the application grows.&lt;/p&gt;  &lt;p&gt;Hmmm… This structure is beginning to look a lot like an MVC app. Perhaps I can have it automatically infer my data templates for me?&lt;/p&gt;  &lt;h3&gt;Some Code&lt;/h3&gt;  &lt;p&gt;Yes we can. Here’s a &lt;em&gt;very naiveté&lt;/em&gt; bit of code that will do just that. It makes some big assumptions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;all of your presenters implement IPresenter &lt;/li&gt;    &lt;li&gt;all of your presenters are in a namespace containing “.Presenters” &lt;/li&gt;    &lt;li&gt;all of your views are in an analogous namespace containing in “.Views” &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Again, this is &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; production ready code, just my spike to prove the idea works. Please feel free to make suggestions.&lt;/p&gt;  &lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public static class MvpConfiguration
{
    /// &amp;lt;summary&amp;gt;
    /// Creates a set of data templates pair to presenter classes based on naming conventions.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;If a data template is already present in the resources, then it is skipped.&amp;lt;/remarks&amp;gt;
    /// &amp;lt;param name=&amp;quot;resources&amp;quot;&amp;gt;The ResourceDictionary that the data templates for the views will be added to.&amp;lt;/param&amp;gt;
    public static void InferViewsFromPresenters(ResourceDictionary resources)
    {
        var lookup = MatchPresentersToViews();

        foreach (var pair in lookup)
        {
            var template = CreateDataTemplate(pair.Value, pair.Key);
            if (resources.Contains(template.DataTemplateKey)) continue;
            resources.Add(template.DataTemplateKey, template);
        }
    }

    private static Dictionary&amp;lt;Type, Type&amp;gt; MatchPresentersToViews()
    {
        var presenters = from type in Assembly.GetExecutingAssembly().GetTypes()
                         where typeof (IPresenter).IsAssignableFrom(type)
                         select type;

        var first = presenters.FirstOrDefault();
        if (first == null) throw new Exception(&amp;quot;I expected to find at least one presenters!&amp;quot;);

        string viewNamespace = first.Namespace
            .Replace(&amp;quot;.Presenters&amp;quot;, &amp;quot;.Views&amp;quot;);
        viewNamespace = viewNamespace.Substring(0, viewNamespace.IndexOf(&amp;quot;.Views&amp;quot;)+6);
        //yeah, that was hackish

        var views = from view in Assembly.GetExecutingAssembly().GetTypes()
                    where !string.IsNullOrEmpty(view.Namespace)
                          &amp;amp;&amp;amp; view.Namespace.StartsWith(viewNamespace)
                    select view;

        var table = new Dictionary&amp;lt;Type, Type&amp;gt;();

        foreach (var view in views)
        {
            var presenter = GetPresenterForView(view, presenters);
            if(presenter == null) continue;

            table.Add(presenter,view);
        }

        return table;
    }

    private static Type GetPresenterForView(Type type, IEnumerable&amp;lt;Type&amp;gt; presenters)
    {
        string name = type.Name.Replace(&amp;quot;View&amp;quot;, &amp;quot;Presenter&amp;quot;);
        var presenter =
            presenters.Where(p =&amp;gt; p.Name == name).FirstOrDefault();
        return presenter;
    }

    private static DataTemplate CreateDataTemplate(Type viewType, Type dataType)
    {
        var template = new DataTemplate(dataType);

        var factory = new FrameworkElementFactory(viewType);
        template.VisualTree = factory;
        return template;
    }
}&lt;/pre&gt;

&lt;p&gt;To use this, in your App.xaml.cs within OnStartup() add:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;MvpConfiguration.InferViewsFromPresenters(Resources);&lt;/pre&gt;

&lt;p&gt;What do you think? Am I totally nuts?&lt;/p&gt;

&lt;p&gt;Oh, and I should also point out that &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.frameworkelementfactory.aspx" target="_blank"&gt;FrameworkElementFactory&lt;/a&gt; is actually deprecated. :-( Caveat emptor.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicious.com/aggbug.aspx?PostID=46528" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/ChristopherBennage/~4/iMG4OD_4kvA" 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/MVC/default.aspx">MVC</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/data+templates/default.aspx">data templates</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/UI+Patterns/default.aspx">UI Patterns</category><category domain="http://devlicious.com/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category><feedburner:origLink>http://devlicious.com/blogs/christopher_bennage/archive/2009/05/06/the-influence-of-mvc-on-my-wpf.aspx</feedburner:origLink></item></channel></rss>
