<?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:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" version="2.0"><channel><title>LeeDumond.com</title><link>http://leedumond.com/</link><description>My musings about .NET and what not</description><generator>Graffiti CMS 1.2 (build 1.2.0.2308)</generator><lastBuildDate>Mon, 02 Nov 2009 01:52:00 GMT</lastBuildDate><creativeCommons:license>http://creativecommons.org/licenses/by-sa/2.0/</creativeCommons:license><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/leedumond" type="application/rss+xml" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">leedumond</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fleedumond" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fleedumond" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fleedumond" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://feeds.feedburner.com/leedumond" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fleedumond" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fleedumond" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fleedumond" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Dynamic Help Removed From Visual Studio 2010</title><link>http://leedumond.com/blog/dynamic-help-removed-from-visual-studio-2010/</link><pubDate>Mon, 02 Nov 2009 03:52:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/dynamic-help-removed-from-visual-studio-2010/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>7</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;Been going blind looking for the Dynamic Help window in the new VS 2010 Beta 2? Me too&amp;hellip; until I learned this bit of bad news from a inside source.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;Like many of you, I&amp;rsquo;ve been messing around with the &lt;a target="_blank" href="http://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx"&gt;Visual Studio 2010 &lt;/a&gt;Beta 2. VS 2010 contains a number of long-awaited IDE improvements, like multiple monitor support, new editing and design tools, and a cleaner, more responsive WPF-based interface.&lt;/p&gt;
&lt;p&gt;So far, I&amp;rsquo;m loving all of it. Well, &lt;em&gt;almost&lt;/em&gt; all of it.&lt;/p&gt;
&lt;p&gt;I happen to be a huge fan of Visual Studio&amp;rsquo;s &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/f88ctah3.aspx"&gt;Dynamic Help&lt;/a&gt; feature. This is a window containing links to related Help topics based on where you are in the IDE.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="dynamic_help" border="0" alt="dynamic_help" width="604" height="389" src="http://leedumond.com/files/media/image/WindowsLiveWriter/DynamicHelpRemovedFromVisualStudio2010_1259D/dynamic_help_3.gif" /&gt;&lt;/p&gt;
&lt;p&gt;In fact, I recently wrote a blog post explaining &lt;a target="_blank" href="http://leedumond.com/blog/integrating-exception-handling-into-the-development-cycle/"&gt;how to integrate exception handling into the development cycle&lt;/a&gt;. The process I presented in that post&amp;nbsp;makes good use of this handy feature.&lt;/p&gt;
&lt;p&gt;In previous versions of Visual Studio, I&amp;rsquo;ve always placed the Dynamic Help window to the right side in Auto-Hide mode, ready at a moment&amp;rsquo;s notice. However, when I went to set up VS 2010 in the same way, I noticed that the Dynamic Help window appeared to have been left off the Help menu.&lt;/p&gt;
&lt;p&gt;&amp;quot;Okay, no big deal,&amp;quot; I thought. It is &lt;em&gt;beta &lt;/em&gt;software after all. You can't really&amp;nbsp;complain if a beta appears a little half-baked, right?&lt;/p&gt;
&lt;p&gt;Nevertheless, this was still disappointing to me. I was tempted to report this as a bug, but just didn&amp;rsquo;t feel like dealing with the massive vortex of suck that is &lt;a target="_blank" href="http://connect.microsoft.com/"&gt;Microsoft Connect&lt;/a&gt;. So instead, I did what most other malcontented developers do &amp;ndash; I &lt;a target="_blank" href="http://twitter.com/LeeDumond/status/5349332955"&gt;complained on Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" width="304" height="246" src="http://leedumond.com/files/media/image/WindowsLiveWriter/DynamicHelpRemovedFromVisualStudio2010_1259D/image_3.png" /&gt;&lt;/p&gt;
&lt;p&gt;A few hours later -&amp;nbsp;much to my chagrin - I&amp;nbsp;received the &lt;a target="_blank" href="http://twitter.com/ccsjeba/status/5352109398"&gt;following reply&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" width="304" height="246" src="http://leedumond.com/files/media/image/WindowsLiveWriter/DynamicHelpRemovedFromVisualStudio2010_1259D/image_6.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Whaaaaaa?&lt;/em&gt; This made absolutely no sense to me. I figured it couldn&amp;rsquo;t be true&amp;hellip; until I learned that &lt;a target="_blank" href="http://twitter.com/ccsjeba"&gt;Charles Christian&lt;/a&gt; is actually a Project Manager on the Visual Studio Help Experience Team. So, there you go. I guess if anyone would be in a position to know, he&amp;rsquo;d be the guy.&lt;/p&gt;
&lt;p&gt;Sure enough, a quick visit to the MSDN seemed to confirm it. Check it out below &amp;ndash; no link to 4.0 up there near the top.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/DynamicHelpRemovedFromVisualStudio2010_1259D/msdn_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="msdn" border="0" alt="msdn" width="604" height="443" src="http://leedumond.com/files/media/image/WindowsLiveWriter/DynamicHelpRemovedFromVisualStudio2010_1259D/msdn_thumb.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It looks like Visual Studio 2010 will definitely take some getting used to &amp;ndash; because of all the new features added, and for at least one that was taken away.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve asked Charles to provide an explanation as to why Dynamic Help was removed. As soon as I get a reply, I&amp;rsquo;ll update this post. Stay tuned.&lt;/p&gt;
&lt;p style="color: #ff0000"&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: Charles' explanation appears below in the comments.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=_aQR6aUsxjY:NsiQS_slMvo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=_aQR6aUsxjY:NsiQS_slMvo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=_aQR6aUsxjY:NsiQS_slMvo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_aQR6aUsxjY:NsiQS_slMvo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/_aQR6aUsxjY" height="1" width="1"/&gt;</description></item><item><title>Dr. Explain Gives Your Software a Brain</title><link>http://leedumond.com/blog/dr-explain-gives-your-software-a-brain/</link><pubDate>Wed, 28 Oct 2009 13:11:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/dr-explain-gives-your-software-a-brain/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>6</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;Thorough, detailed, and up-to-date documentation is one of the keys to success for any software application. Dr. Explain makes it easy (almost &lt;em&gt;too&lt;/em&gt; easy) to create and maintain CHM help files, web-based HTML documentation, and even printable manuals.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;Ask any developer to name his or her least favorite development-related tasks, and there&amp;rsquo;s a good chance that &amp;ldquo;creating documentation&amp;rdquo; will appear very close to the the top of that list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/wizardofoz1_2.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 15px 15px; display: inline; border-top: 0px; border-right: 0px" title="wizardofoz1" border="0" alt="wizardofoz1" align="right" width="244" height="167" src="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/wizardofoz1_thumb.jpg" /&gt;&lt;/a&gt;While writing docs may not be nearly as sexy as architecting or slinging code, it&amp;rsquo;s a critically important component to any successful software project.&lt;/strong&gt; Skimpy, incomplete, or disorganized documentation is not only a major impediment to new user adoption, it reflects poorly on the &lt;em&gt;rest&lt;/em&gt; of the application, and even on your company as a whole. Despite what you may have heard, people &lt;em&gt;do&lt;/em&gt; &lt;a target="_blank" href="http://en.wikipedia.org/wiki/RTFM"&gt;RTFM&lt;/a&gt;. Your software&amp;rsquo;s help file is invariably the first place users turns for assistance; if they can&amp;rsquo;t make head or tails of it, your chances of converting that trial download to a cash sale just went down considerably.&lt;/p&gt;
&lt;p&gt;On the other hand, well-documented software is easier to sell, easier for your customers to train new users on, and &lt;em&gt;much&lt;/em&gt; easier for you to support. Thorough, detailed, up-to-date help is one of the keys to helping users be productive, and productive users are happy users.&lt;/p&gt;
&lt;p&gt;Of course, documenting software is time-consuming and tedious, right? I used to think so too. That was until I discovered a solution that makes the entire process easier and quicker than I ever thought possible.&lt;/p&gt;
&lt;h3&gt;Help That Practically Writes Itself&lt;/h3&gt;
&lt;p&gt;&lt;a target="_blank" href="http://www.drexplain.com/"&gt;Dr. Explain&lt;/a&gt; from &lt;a target="_blank" href="http://www.indigobyte.com/"&gt;Indigo Byte Systems&lt;/a&gt; is a software help authoring tool. It provides a powerful, intuitive user interface for composing a tree-navigable help system for Windows/WPF, Java, and Flash applications, as well as Web sites. From a single source file, it can export to &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help"&gt;CHM&lt;/a&gt;, HTML, and rich text format (RTF). This helps you maintain all of your docs in one place while keeping everything consistent and timely &amp;ndash; whether you electronically distribute help with your application, host it online, or deliver printed copies in the box.&lt;/p&gt;
&lt;p&gt;While Dr. Explain has all the features you&amp;rsquo;d expect from a comprehensive help authoring system, it does &lt;em&gt;one special thing amazingly well&lt;/em&gt;, which in my mind places it head and shoulders above other offerings in this category. &lt;strong&gt;Dr. Explain takes the most difficult, time-consuming, and tedious part of the documentation process &amp;ndash; the annotation of user interfaces &amp;ndash; and totally automates it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, you read that right. Let the built-in object capture tool take a screenshot of &lt;em&gt;any&lt;/em&gt; part of your application &amp;ndash; from a simple dialog, to a full window, to a web form&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" width="575" height="484" src="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image_thumb.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;and from there it &lt;em&gt;analyzes&lt;/em&gt; the structure, &lt;em&gt;finds&lt;/em&gt; all the significant GUI elements, and &lt;em&gt;automatically creates&lt;/em&gt; numbered callouts for all of them!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" width="575" height="484" src="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image4_thumb.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It optionally allows you to associate a definable portion of the screenshot with each annotation, and displays it (along with the descriptive text you provide) at the bottom. This provides helpful visual cues to your readers, as you can see from the CHM output.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image8.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" width="575" height="484" src="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image8_thumb.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A screenshot of the HTML output shows how a consistent look and feel is maintained between the CHM and HTML output.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image12.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" width="575" height="484" src="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/image12_thumb.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Providing guidance for all the different screens in your application lies at the heart of effective documentation.&lt;/strong&gt; Even with the drawing tools provided by many authoring systems, this process can take hours, even days. By scaffolding screenshot-based help topics in mere &lt;em&gt;minutes,&lt;/em&gt; Dr. Explain dramatically cuts the time required to accomplish this task. Capture the screenshot, add the necessary descriptive text to the automatically generated annotations, and you&amp;rsquo;re practically done.&lt;/p&gt;
&lt;h3&gt;But Wait, There&amp;rsquo;s More&amp;hellip;&lt;/h3&gt;
&lt;p&gt;Despite its amazing screenshot annotation abilities, Dr. Explain is no one-trick pony. It facilitates many other help-building functions as well, including the integration of context-sensitive (F1) help directly into any application; navigation tree management; creation of keyword indexes; full-featured RTF text editing with Unicode support; templating, theme, and CSS support; and lots more. All of this is included in the $125 standard license.&lt;/p&gt;
&lt;p&gt;For an additional $40, an &amp;ldquo;advanced license&amp;rdquo; is available which unlocks some very spiffy features, the slickest of which is the ability to have Dr. Explain automatically crawl the entire submenu structure of a Win32 application on one go:&lt;/p&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 15px 0px 0px; display: inline; border-top: 0px; border-right: 0px" title="menu-submenus-capturing-annotation_image_0" border="0" alt="menu-submenus-capturing-annotation_image_0" width="244" height="196" src="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/menusubmenuscapturingannotation_imag%5B2%5D.png" /&gt; &lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="menu-submenus-capturing-annotation_image_1" border="0" alt="menu-submenus-capturing-annotation_image_1" width="401" height="196" src="http://leedumond.com/files/media/image/WindowsLiveWriter/Dr.ExplainGivesYourSoftwareaBrain_D0D9/menusubmenuscapturingannotation_imag.png" /&gt;&lt;/p&gt;
&lt;p&gt;Other advanced features include the ability to invoke the Dr. Explain engine from the command line; the creation of pop-up tooltips; and a tool to generate Google sitemaps from HTML help pages.&lt;/p&gt;
&lt;p&gt;To learn more; feel free to avail yourself of any of the following handy resources:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Dr. Explain &lt;a target="_blank" href="http://www.drexplain.com/software-documentation-tool/"&gt;features overview&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;A &lt;a target="_blank" href="http://www.youtube.com/watch?v=F-PUmFdeJlI"&gt;six-minute YouTube video&lt;/a&gt; demonstrating Dr. Explain in action&lt;/li&gt;
    &lt;li&gt;The Dr. Explain &lt;a target="_blank" href="http://www.drexplain.com/forum/"&gt;user forum&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a target="_blank" href="http://www.drexplain.com/order/"&gt;Pricing and licensing options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Whether your goal is to sell more software, reduce the burden on your help desk staff, or simply to pave an easier path to adoption for your open-source project, producing and providing excellent help documentation is critically important.&lt;/strong&gt; Dr. Explain is an incredibly useful tool for this purpose, especially if your help files rely heavily on UI illustrations. Its automatic annotation capabilities perform nearly flawlessly, and cut the time required to generate screenshot-based help topic by several orders of magnitude.&lt;/p&gt;
&lt;p&gt;A &lt;a target="_blank" href="http://www.drexplain.com/download/"&gt;trial version&lt;/a&gt; is available that you may use as long as you wish. Until you register, you&amp;rsquo;ll be limited to five help topics per project, and all screen captures will be watermarked. While obviously not suitable for production work, it&amp;rsquo;s more that enough to let you try out the many features for yourself.&lt;/p&gt;
&lt;p&gt;At $125 for a single-user license, Dr. Explain could easily pay for itself several times over in the scope of a single project, merely based on the amount of time saved. For $165, the Advanced License unlocks additional features you&amp;rsquo;re sure to find useful as well.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=jDyjwqV4caI:YKIhxuYHIqo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=jDyjwqV4caI:YKIhxuYHIqo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=jDyjwqV4caI:YKIhxuYHIqo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=jDyjwqV4caI:YKIhxuYHIqo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/jDyjwqV4caI" height="1" width="1"/&gt;</description></item><item><title>Wrox Blogs Are Now Live!</title><link>http://leedumond.com/blog/wrox-blogs-are-now-live/</link><pubDate>Thu, 22 Oct 2009 14:25:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/wrox-blogs-are-now-live/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>3</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;Wrox Press has added a blog site, featuring posts from authors and key staff, to its lineup of great programmer resources.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;Just a quick post to let you all know that as of this week, the long-awaited &lt;a target="_blank" href="http://p2p.wrox.com/content/blogs"&gt;Wrox Blogs&lt;/a&gt; are now live at the &lt;a target="_blank" href="http://www.wrox.com/WileyCDA/"&gt;Wrox Press&lt;/a&gt; website. The next time you visit, be sure to note the prominent link on the home page menu.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="wrox-homepage" border="0" alt="wrox-homepage" width="604" height="501" src="http://leedumond.com/files/media/image/WindowsLiveWriter/WroxBlogsAreNowLive_80AD/wrox-homepage_thumb_2.gif" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are only a few of us there right now, but that number is sure to grow as more of your favorite Wrox authors jump on board.&lt;/p&gt;
&lt;p&gt;The guidelines that Wrox has given us in regards to content is pretty wide open, as long as the topics are programming-related, or related to our writing or editing activities. I hope to use &lt;a target="_blank" href="http://p2p.wrox.com/content/blogs/lee-dumond"&gt;my own little corner on the Wrox Blogs&lt;/a&gt; to supplement the material I&amp;rsquo;m publishing here, especially that having to do with Wrox stuff that I&amp;rsquo;m reading, writing, or editing.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re a subscriber to &lt;a target="_blank" href="http://feeds2.feedburner.com/leedumond"&gt;LeeDumond.com&lt;/a&gt; (and if you are, I sincerely thank you), you might want to consider subscribing to the Wrox blog as well, to make sure you&amp;rsquo;re getting all the good stuff!&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a target="_blank" href="http://p2p.wrox.com/content/blogs/lee-dumond/feed"&gt;Subscribe&lt;/a&gt; to &lt;em&gt;my&lt;/em&gt; Wrox Blog&lt;/li&gt;
    &lt;li&gt;&lt;a target="_blank" href="http://p2p.wrox.com/content/blog/feed"&gt;Subscribe&lt;/a&gt; to &lt;em&gt;all&lt;/em&gt; the Wrox Blogs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I hope to be starting on a new book very soon, I&amp;rsquo;m sure I&amp;rsquo;ll have lots of cool things to write about. Stay tuned!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=_XeWw9NGQpw:tkOf5RNyXSg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=_XeWw9NGQpw:tkOf5RNyXSg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=_XeWw9NGQpw:tkOf5RNyXSg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=_XeWw9NGQpw:tkOf5RNyXSg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/_XeWw9NGQpw" height="1" width="1"/&gt;</description></item><item><title>Integrating Exception Handling Into the Development Cycle</title><link>http://leedumond.com/blog/integrating-exception-handling-into-the-development-cycle/</link><pubDate>Wed, 14 Oct 2009 13:46:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/integrating-exception-handling-into-the-development-cycle/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>12</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;The time to start thinking about exception handling is&amp;nbsp;right after you click File&amp;nbsp;&amp;gt; New Project. Exception handling shouldn't be something you &amp;quot;tack-on&amp;quot; to an application after the fact.&amp;nbsp;Here, I discuss a practical approach to incorporating exception handling into the normal code-writing process.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;Recently, my friend &lt;a target="_blank" href="http://jclaes.blogspot.com/"&gt;Jef Claes&lt;/a&gt; wrote me via my contact page. In part, his inquiry reads:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In which part of the development cycle, do you have to start thinking about exception handling? How and when do you decide which exceptions to handle specifically, so they won't kill your whole page?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Geesh&amp;hellip; I &lt;a target="_blank" href="http://leedumond.com/tags/exception/"&gt;post a few articles&lt;/a&gt; and &lt;a target="_blank" href="http://www.wrox.com/WileyCDA/WroxTitle/Robust-ASP-NET-Exception-Handling.productCd-047050367X.html"&gt;write a book&lt;/a&gt; about exception handling, and all of a sudden I&amp;rsquo;m Mr. Exception Guy. ;)&lt;/p&gt;
&lt;p&gt;In all seriousness though, this is a great question. There are lots of resources out there that provide information about exception handling from a theoretical or academic point of view, but very few that present a &lt;strong&gt;practical approach to integrating exception handling into your day-to-day development cycle.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here, I&amp;rsquo;d like to present my own general approach to exception handling.&lt;/p&gt;
&lt;h3&gt;Examine the Possibilities&lt;/h3&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 15px 15px; display: inline; border-top: 0px; border-right: 0px" title="magnifying_glass" border="0" alt="magnifying_glass" align="right" width="104" height="141" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/magnifying_glass_3.jpg" /&gt; I have written before about the &lt;a target="_blank" href="http://leedumond.com/blog/friends-dont-let-friends-catch-exception/"&gt;importance of handling only specific exceptions&lt;/a&gt;. Of course, you can&amp;rsquo;t do that unless you know what exceptions could be thrown from your code. That means the first thing you should do is to &lt;strong&gt;discover which exceptions are possible.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;How you do that depends on the framework or API you&amp;rsquo;re using. If you&amp;rsquo;re using the .NET Framework, the MSDN can tell you which exceptions might be thrown from any given method, constructor, property, event, or indexer.&lt;/p&gt;
&lt;p&gt;Consider the following simple code, which writes a string of text to a text file. The string of text to write (&lt;tt&gt;txtEntry.Text&lt;/tt&gt;), as well as a portion of the path value (&lt;tt&gt;txtPath.Text&lt;/tt&gt;), is supplied by the user.&lt;/p&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
private void LogEntry()
{
   string workingDirectory = ConfigurationManager.AppSettings[&amp;quot;directoryToLog&amp;quot;];

   if (!string.IsNullOrEmpty(workingDirectory))
   {
      string path = workingDirectory + txtPath.Text;

      using (StreamWriter writer = File.AppendText(path))
      {
         writer.WriteLine(DateTime.Now.ToString());
         writer.WriteLine(&amp;quot;Entry: {0}&amp;quot;, txtEntry.Text);
         writer.WriteLine(&amp;quot;--------------------&amp;quot;);
      }

      lblMessage.Text = &amp;quot;The entry &amp;quot; + txtEntry.Text + &amp;quot; was logged successfully.&amp;quot;;
   }
   else
   {
      lblMessage.Text = &amp;quot;The required configuration setting is missing. The entry &amp;quot; + 
         txtEntry.Text + &amp;quot; was not logged.&amp;quot;;
   }      
}&lt;/pre&gt;
&lt;p&gt;We can see the first call is to &lt;tt&gt;ConfigurationManager.AppSettings&lt;/tt&gt;. If you place your cursor on the method in the IDE, the Dynamic Help window will show you a link to the method in the MSDN.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="screenshot1" border="0" alt="screenshot1" width="604" height="389" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/screenshot1_3.gif" /&gt;&lt;/p&gt;
&lt;p&gt;Clicking on this link will take you to the relevant MSDN page. The MSDN will show you any exceptions that could possibly be encountered from accessing this property.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="screenshot2" border="0" alt="screenshot2" width="604" height="572" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/screenshot2_3.gif" /&gt;&lt;/p&gt;
&lt;p&gt;Doing the same with the &lt;tt&gt;File.AppendText&lt;/tt&gt; method yields the following result:&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="screenshot3" border="0" alt="screenshot3" width="604" height="605" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/screenshot3_3.gif" /&gt;&lt;/p&gt;
&lt;p&gt;Finally, the &lt;tt&gt;WriteLine&lt;/tt&gt; method shows the following:&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="screenshot4" border="0" alt="screenshot4" width="604" height="605" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/screenshot4_3.gif" /&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the Visual Studio IDE and accompanying documentation makes this pretty easy. Keep in mind that when you&amp;rsquo;re calling a third party API, your experience will definitely vary. A well-written API should include &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/b2s063f7(loband).aspx"&gt;XML documentation&lt;/a&gt; that exposes via Intellisense any exceptions that could be thrown; and if you&amp;rsquo;re lucky, compiled documentation created by a tool such as &lt;a target="_blank" href="http://www.codeplex.com/Sandcastle"&gt;Sandcastle&lt;/a&gt;. If not, you have to rely on whatever the API provides, or perhaps use &lt;a target="_blank" href="http://www.red-gate.com/products/reflector/"&gt;Reflector&lt;/a&gt; to disassemble the binary.&lt;/p&gt;
&lt;h3&gt;Program Defensively&lt;/h3&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 15px 15px; display: inline; border-top: 0px; border-right: 0px" title="17_AggressiveDriving" border="0" alt="17_AggressiveDriving" align="right" width="172" height="104" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/17_AggressiveDriving_3.jpg" /&gt; Now that we have a list of all the possible exceptions that can be thrown from our code, the next step is to &lt;strong&gt;determine which exceptions we can prevent, and which we can safely ignore.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In this case, we are supplying part of the path in the configuration file, and this branch of code only runs if that value is not null or empty. Therefore, we can be 100% certain that the argument we pass to &lt;tt&gt;File.AppendText&lt;/tt&gt; will never be null. This lets us safely ignore &lt;tt&gt;ArgumentNullException&lt;/tt&gt; from the &lt;tt&gt;File.AppendText&lt;/tt&gt; method.&lt;/p&gt;
&lt;p&gt;Next, we can employ &lt;a target="_blank" href="http://leedumond.com/blog/defensive-programming-or-why-exception-handling-is-like-car-insurance/"&gt;defensive programming techniques&lt;/a&gt; to prevent most of the remaining exceptions that can be thrown from &lt;tt&gt;File.AppendText&lt;/tt&gt;. By restricting and validating the user input, you can assure that the path supplied by the user can never be too long, contain invalid characters, or be in an invalid format. This relieves us from having to handle &lt;tt&gt;ArgumentException&lt;/tt&gt;, &lt;tt&gt;PathTooLongException&lt;/tt&gt;, or &lt;tt&gt;NotSupportedException&lt;/tt&gt;. That leaves us two possible exceptions we might have to deal with.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s consider the two exceptions that can be thrown from the &lt;tt&gt;TextWriter.WriteLine&lt;/tt&gt; method. The first, &lt;tt&gt;ObjectDisposedException&lt;/tt&gt;, can&amp;rsquo;t happen in this code because all of the &lt;tt&gt;WriteLine&lt;/tt&gt; calls are made prior to closing the writer; so we&amp;rsquo;ll ignore it. The second, &lt;tt&gt;IOException&lt;/tt&gt;, would normally be thrown in response to a disk or path error. Since we can&amp;rsquo;t prevent this from happening in code, this exception is a good candidate for handling.&lt;/p&gt;
&lt;h3&gt;Determine Which Exceptions To Handle&lt;/h3&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 15px 15px; display: inline; border-top: 0px; border-right: 0px" title="Dylan_wrestling_belt1" border="0" alt="Dylan_wrestling_belt1" align="right" width="104" height="137" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/Dylan_wrestling_belt1_3.jpg" /&gt; So far, we&amp;rsquo;ve taken two steps. First, we &lt;strong&gt;identified all possible exceptions&lt;/strong&gt;. Second, we determined &lt;strong&gt;which exceptions can be either effectively prevented or safely ignored.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The remaining exceptions we have to worry about are:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;tt&gt;ConfigurationErrorsException&lt;/tt&gt; (from &lt;tt&gt;ConfigurationManager.AppSettings&lt;/tt&gt;)&lt;/li&gt;
    &lt;li&gt;&lt;tt&gt;UnauthorizedAccessException&lt;/tt&gt; (from &lt;tt&gt;File.AppendText&lt;/tt&gt;)&lt;/li&gt;
    &lt;li&gt;&lt;tt&gt;DirectoryNotFoundException&lt;/tt&gt; (from &lt;tt&gt;File.AppendText&lt;/tt&gt;)&lt;/li&gt;
    &lt;li&gt;&lt;tt&gt;IOException&lt;/tt&gt; (from &lt;tt&gt;writer.WriteLine&lt;/tt&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, we must decide which of these we can and should handle, and why.&lt;/p&gt;
&lt;p&gt;There are legitimate reasons for handling exceptions. Among these are:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Notifying the user, and if appropriate, allowing them to retry the operation&lt;/li&gt;
    &lt;li&gt;Wrapping the exception in a new exception, appending additional relevant detail&lt;/li&gt;
    &lt;li&gt;Wrapping a specific exception in a more general exception to prevent revealing sensitive details, such as exceptions thrown from a Web service&lt;/li&gt;
    &lt;li&gt;Using a finally block to clean up resources that might be abandoned if an exception occurs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this simple example, notifying the user is probably sufficient.&lt;/p&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
private void LogEntry()
{
   string workingDirectory = null;

   try
   {
      workingDirectory = ConfigurationManager.AppSettings[&amp;quot;directoryToLog&amp;quot;];
   }
   catch (ConfigurationErrorsException)
   {
      lblMessage.Text = &amp;quot;There was a problem accessing the configuration settings. The entry &amp;quot; +
                        txtEntry.Text + &amp;quot; was not logged.&amp;quot;;
      return;
   }

   if (!string.IsNullOrEmpty(workingDirectory))
   {
      string path = string.Empty;

      try
      {
         path = workingDirectory + txtPath.Text;

         using (StreamWriter writer = File.AppendText(path))
         {
            writer.WriteLine(DateTime.Now.ToString());
            writer.WriteLine(&amp;quot;Entry: {0}&amp;quot;, txtEntry.Text);
            writer.WriteLine(&amp;quot;--------------------&amp;quot;);
         }

         lblMessage.Text = &amp;quot;The entry &amp;quot; + txtEntry.Text + &amp;quot; was logged successfully.&amp;quot;;
      }
      catch (UnauthorizedAccessException)
      {
         lblMessage.Text = &amp;quot;You do not have the required permissions to access the path &amp;quot; +
                           path + &amp;quot; . The entry &amp;quot; + txtEntry.Text + &amp;quot; was not logged.&amp;quot;;
      }
      catch (DirectoryNotFoundException)
      {
         lblMessage.Text = &amp;quot;Part of the path &amp;quot; + path + &amp;quot; was not found. The entry &amp;quot; +
                           txtEntry.Text + &amp;quot; was not logged.&amp;quot;;
      }
      catch (IOException)
      {
         lblMessage.Text = &amp;quot;There was a problem accessing the path &amp;quot; + path + &amp;quot; . The entry &amp;quot; +
                           txtEntry.Text + &amp;quot; was not logged.&amp;quot;;
      }
   }
   else
   {
      lblMessage.Text = &amp;quot;The required configuration setting is missing. The entry &amp;quot; + txtEntry.Text +
                        &amp;quot; was not logged.&amp;quot;;
   }
}&lt;/pre&gt;
&lt;p&gt;Note that we&amp;rsquo;re tailoring the message sent back to the UI to be as informative as possible, &lt;em&gt;without&lt;/em&gt; using the original &lt;tt&gt;Message&lt;/tt&gt; property from the handled exception. While the &lt;tt&gt;Message&lt;/tt&gt; property is quite useful for logging and debugging purposes, I generally find it&amp;rsquo;s &lt;em&gt;not a good idea to pass a framework-generated exception message to your end users&lt;/em&gt;. For one, they often tend to be rather cryptic to non-developers. More importantly, it&amp;rsquo;s possible they could contain sensitive information. While the .NET Framework itself is pretty good at not revealing sensitive information in &lt;tt&gt;Message&lt;/tt&gt;, you&amp;rsquo;ll find that many third-party APIs are not nearly as conscientious in this regard.&lt;/p&gt;
&lt;p&gt;Also note that the order in which you handle exceptions can be important. Here we&amp;rsquo;re handling &lt;tt&gt;DirectoryNotFoundException&lt;/tt&gt; before &lt;tt&gt;IOException&lt;/tt&gt;. This is because &lt;tt&gt;DirectoryNotFoundException&lt;/tt&gt; is a derived type of &lt;tt&gt;IOException&lt;/tt&gt;, and derived types should always be handled first.&lt;/p&gt;
&lt;h3&gt;Do or Do Not. There is No Try.&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 15px 15px; display: inline; border-top: 0px; border-right: 0px" title="YODA" border="0" alt="YODA" align="right" width="104" height="134" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/YODA_3.jpg" /&gt; If you can&amp;rsquo;t successfully handle an exception in code, it is best to let the application fail as quickly as possible.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I can hear some of you now: &amp;ldquo;&lt;em&gt;What&lt;/em&gt;? Are you suggesting that we should &lt;em&gt;let our applications fail&lt;/em&gt;?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The answer is &lt;em&gt;yes&lt;/em&gt;&amp;hellip; that is, in fact, &lt;em&gt;exactly what I am suggesting&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Part of handling exceptions successfully is facing the fact that &lt;a target="_blank" href="http://leedumond.com/blog/friends-dont-let-friends-catch-exception/"&gt;you cannot successfully handle everything&lt;/a&gt;. Remember, an exception being thrown means your application has &lt;em&gt;already&lt;/em&gt; crashed. Sometimes it is possible to handle the exception, giving the application a chance to recover or to &lt;a target="_blank" href="http://leedumond.com/blog/retrying-mail-operations-in-net/"&gt;retry the operation&lt;/a&gt;. Quite often though, you will encounter exceptions for which &lt;em&gt;no sensible handling strategy exists&lt;/em&gt;, in which case &lt;em&gt;catching the exception is totally pointless&lt;/em&gt;. Only catch exceptions which you are prepared to handle; otherwise let them go.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you catch exceptions which you subsequently do not handle &amp;ndash;&lt;/strong&gt; usually through the use of general catch blocks &lt;strong&gt;&amp;ndash; you merely postpone the inevitable.&lt;/strong&gt; Allowing an application to continue in the face of an unhandled exception is not only wasteful, it&amp;rsquo;s dangerous. Values might be corrupted. Resources might be left in an unstable or unknown state. This is &lt;em&gt;exactly why exceptions are thrown in the first place&lt;/em&gt; &amp;ndash; to &lt;em&gt;prevent&lt;/em&gt; a program from continuing under these conditions. If you can somehow correct or recover from the condition, then fine. If you cannot, then failing quickly is the best option.&lt;/p&gt;
&lt;h3&gt;Fail Gracefully&lt;/h3&gt;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 15px 15px; display: inline; border-top: 0px; border-right: 0px" title="kerri-strug-8_6" border="0" alt="kerri-strug-8_6" align="right" width="104" height="153" src="http://leedumond.com/files/media/image/WindowsLiveWriter/IntegratingExceptionHandlingIntotheDevel_11122/kerri-strug-8_6_3.jpg" /&gt; The fact is that in a production application, you never truly let any exception remain &amp;ldquo;unhandled&amp;rdquo; in a technical sense &amp;ndash; the &lt;em&gt;real&lt;/em&gt; question is not &lt;em&gt;whether&lt;/em&gt; to handle exceptions, but &lt;em&gt;where&lt;/em&gt; to handle them.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;m saying here is that &lt;strong&gt;you need to make absolutely sure you have a global exception handling mechanism in place.&lt;/strong&gt; In a Windows application, that usually means handling the &lt;tt&gt;AppDomain.CurrentDomain.UnhandledException&lt;/tt&gt; event. In an ASP.NET application, it means handling the &lt;tt&gt;HttpApplication.Error&lt;/tt&gt; event, either manually or via the built-in ASP.NET default exception handler. This &amp;ldquo;last-chance&amp;rdquo; global handler lets you provide a friendly user experience when unrecoverable errors occur, as well as a central location from which to log exceptions that weren&amp;rsquo;t handled by your code.&lt;/p&gt;
&lt;p&gt;Of course, once an exception reaches your global exception handler, it means execution has stopped and your application has failed. That happens &amp;ndash; and as we&amp;rsquo;ve learned, sometimes there&amp;rsquo;s nothing you can do about it. But there&amp;rsquo;s no reason your application can&amp;rsquo;t fail &lt;em&gt;gracefully&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;In this post, I&amp;rsquo;ve outlined a series of steps you can use to sensibly and effectively &lt;strong&gt;integrate exception handling into the development cycle.&lt;/strong&gt; These can be summarized as follows:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Use the available documentation to discover which exceptions are possible.&lt;/li&gt;
    &lt;li&gt;Determine which exceptions you can safely ignore, based on current state.&lt;/li&gt;
    &lt;li&gt;Where possible, use defensive programming techniques to prevent exceptions from being thrown.&lt;/li&gt;
    &lt;li&gt;Determine which of the remaining exceptions you should handle, and develop a strategy for doing so.&lt;/li&gt;
    &lt;li&gt;Allow any exceptions you cannot completely handle in code to propagate to your default exception handler.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This, in a nutshell, pretty much sums up how I approach exception handling as I write code. Hopefully, you&amp;rsquo;ll find this useful in your day-to-day routine as well.&lt;/p&gt;
&lt;p&gt;Questions? Constructive criticism? Suggestions for improvement? Please let me know what you think in the comments below.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=tH9KSPGNPgY:JP1lZG-pALo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=tH9KSPGNPgY:JP1lZG-pALo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=tH9KSPGNPgY:JP1lZG-pALo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tH9KSPGNPgY:JP1lZG-pALo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/tH9KSPGNPgY" height="1" width="1"/&gt;</description></item><item><title>ASP.NET Profiles in Web Application Projects</title><link>http://leedumond.com/blog/asp-net-profiles-in-web-application-projects/</link><pubDate>Thu, 08 Oct 2009 11:45:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/asp-net-profiles-in-web-application-projects/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>11</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;Accessing ASP.NET profiles from a web application project is remarkably easy once you know how. Here&amp;rsquo;s how it&amp;rsquo;s done, along with a fully working implementation that you can download.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;Earlier this year, I blogged about how to create a &lt;a target="_blank" href="http://leedumond.com/blog/getting-strongly-typed-profile-properties-from-a-class-library/"&gt;strongly-typed Profile that could be accessed from a class library&lt;/a&gt;. In response to popular demand, today I&amp;rsquo;m presenting a similar (but more substantial) example geared specifically toward &lt;strong&gt;accessing profiles in web application projects.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are plenty of blog posts that &lt;em&gt;talk&lt;/em&gt; about this, but unfortunately very few that show &lt;em&gt;how to do it&lt;/em&gt;. Most of them instead refer to &lt;a target="_blank" href="http://www.codeplex.com/WebProfile"&gt;this relatively obscure add-in for Visual Studio 2005&lt;/a&gt;&amp;nbsp;(apparently. you&amp;rsquo;re out of luck if you&amp;rsquo;re using Visual Studio 2008). However, the good news is &lt;strong&gt;you don&amp;rsquo;t need a third party add-in or build task for this&lt;/strong&gt;, as implementing this functionality yourself is not difficult at all.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re reading this, I&amp;rsquo;ll assume you&amp;rsquo;re aware of the differences between an ASP.NET web &lt;em&gt;site&lt;/em&gt; and a web &lt;em&gt;application&lt;/em&gt;, so I won&amp;rsquo;t go into the various differences in great detail (feel free to &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/aa730880(VS.80).aspx"&gt;consult the MSDN&lt;/a&gt; for more information). For our purposes, it&amp;rsquo;s just important to understand that in a web &lt;em&gt;application&lt;/em&gt; project, there is no &lt;tt&gt;ProfileCommon&lt;/tt&gt; class or &lt;tt&gt;Page.Profile&lt;/tt&gt; property to work with, as we&amp;rsquo;re accustomed to seeing in web &lt;em&gt;site&lt;/em&gt; projects &amp;ndash; hence the problem.&lt;/p&gt;
&lt;p&gt;Web site projects accomplish this bit of magic through dynamic compilation &amp;ndash; essentially creating the needed objects at runtime, &amp;ldquo;on the fly&amp;rdquo; as it were. In effect we will be doing the exact same thing, but the old-fashioned way &amp;ndash; with a simple hand-written proxy class.&lt;/p&gt;
&lt;h3&gt;Writing a Profile Proxy Class&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s assume for the sake of discussion that we have several bits of user information we want to store in profile.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;first name&lt;/li&gt;
    &lt;li&gt;last name&lt;/li&gt;
    &lt;li&gt;date of birth&lt;/li&gt;
    &lt;li&gt;gender&lt;/li&gt;
    &lt;li&gt;the user&amp;rsquo;s time zone&lt;/li&gt;
    &lt;li&gt;the user&amp;rsquo;s preferred culture&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, we could store these as separate value types, but in practice I find it easier to group related properties together in a class. So let&amp;rsquo;s create a class &lt;tt&gt;Personal&lt;/tt&gt; to store the first four properties, and a class &lt;tt&gt;Preferences&lt;/tt&gt; to store the time zone and culture. Make sure to decorate these classes with the &lt;tt&gt;[Serializable]&lt;/tt&gt; attribute.&lt;/p&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
namespace LD.Sample.BLL
{
   using System;

   [Serializable]
   public class Personal
   {
      public string FirstName { get; set; }

      public string LastName { get; set; }

      public DateTime DateOfBirth { get; set; }

      public Gender Gender { get; set; }
   }
}&lt;/pre&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
namespace LD.Sample.BLL
{
   using System;

   [Serializable]
   public class Preferences
   {
      public string TimeZone { get; set; }
      
      public string Culture { get; set; }
   }
}&lt;/pre&gt;
&lt;p&gt;Next, we&amp;rsquo;ll write a class that will define the profile we want, incorporating the two custom types shown above as properties. This class will inherit &lt;tt&gt;ProfileBase&lt;/tt&gt; . Let&amp;rsquo;s call it &lt;tt&gt;CustomProfile&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
namespace LD.Sample.BLL
{
   using System.Web;
   using System.Web.Profile;

   public class CustomProfile : ProfileBase
   {
      public Personal Personal
      {
         get { return (Personal) GetPropertyValue(&amp;quot;Personal&amp;quot;); }
      }

      public Preferences Preferences
      {
         get { return (Preferences) GetPropertyValue(&amp;quot;Preferences&amp;quot;); }
      }

      /// &amp;lt;summary&amp;gt;
      /// Get the profile of the currently logged-on user.
      /// &amp;lt;/summary&amp;gt;      
      public static CustomProfile GetProfile()
      {
         return (CustomProfile) HttpContext.Current.Profile;
      }

      /// &amp;lt;summary&amp;gt;
      /// Gets the profile of a specific user.
      /// &amp;lt;/summary&amp;gt;
      /// &amp;lt;param name=&amp;quot;userName&amp;quot;&amp;gt;The user name of the user whose profile you want to retrieve.&amp;lt;/param&amp;gt;
      public static CustomProfile GetProfile(string userName)
      {
         return (CustomProfile) Create(userName);
      }
   }
}&lt;/pre&gt;
&lt;p&gt;Note that I&amp;rsquo;ve also included two overloaded static &lt;tt&gt;GetProfile&lt;/tt&gt; methods. &lt;tt&gt;GetProfile()&lt;/tt&gt;&amp;nbsp; lets us obtain the profile of the current user, while &lt;tt&gt;GetProfile(string userName)&lt;/tt&gt; lets us get the profile of a specific user (for administrative purposes, or when creating a new member, for example).&lt;/p&gt;
&lt;p&gt;One more thing &amp;ndash; and this is very important &amp;ndash; we need to define the provider in web.config.&lt;/p&gt;
&lt;pre class="brush: xml; auto-links: false;"&gt;
&amp;lt;profile defaultProvider=&amp;quot;LD.SampleWAP.ProfileProvider&amp;quot; inherits=&amp;quot;LD.Sample.BLL.CustomProfile&amp;quot;&amp;gt;
&amp;lt;providers&amp;gt;
   &amp;lt;add name=&amp;quot;LD.SampleWAP.ProfileProvider&amp;quot;
   type=&amp;quot;System.Web.Profile.SqlProfileProvider&amp;quot;
   applicationName=&amp;quot;/&amp;quot;
   connectionStringName=&amp;quot;LocalSqlServer&amp;quot;/&amp;gt;
&amp;lt;/providers&amp;gt;&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll see that our provider is of type &lt;tt&gt;System.Web.Profile.SqlProfileProvider&lt;/tt&gt;. Of course, this assumes that the database to which this is pointing has been configured with the schema required to support &lt;tt&gt;SqlProfileProvider&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Also note the &lt;tt&gt;inherits&lt;/tt&gt; attribute in &lt;tt&gt;&amp;lt;profile&amp;gt;&lt;/tt&gt;. This is what tells the provider where to obtain the profile properties &amp;ndash; in our case, from the &lt;tt&gt;CustomProfile&lt;/tt&gt; class. When you do this, &lt;em&gt;you do not want to define the properties declaratively&lt;/em&gt; in web.config, as you would in a website project. If you do, you&amp;rsquo;ll get a &lt;tt&gt;System.Configuration.ConfigurationException&lt;/tt&gt;, informing you that the profile property has already been defined.&lt;/p&gt;
&lt;h3&gt;Usage&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;And that, believe it or not, is all there is to setting up a strongly-typed profile for use in a web application project.&lt;/strong&gt; Now, let&amp;rsquo;s take a look at how you can use this newly-implemented goodness.&lt;/p&gt;
&lt;p&gt;Here is some code that shows &lt;strong&gt;setting profile values for the currently logged-on user.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
CustomProfile profile = CustomProfile.GetProfile();

profile.Personal.FirstName = &amp;quot;Tami&amp;quot;;
profile.Personal.LastName = &amp;quot;Gharst&amp;quot;;
profile.Personal.DateOfBirth = new DateTime(1972, 7, 10);
profile.Personal.Gender = Gender.Female;
profile.Preferences.TimeZone = &amp;quot;W. Europe Standard Time&amp;quot;;
profile.Preferences.Culture = &amp;quot;de-DE&amp;quot;;

profile.Save();&lt;/pre&gt;
&lt;p&gt;Here is some code that shows &lt;strong&gt;setting profile values for a specific user&lt;/strong&gt; with the user name &amp;ldquo;Lee&amp;rdquo;.&lt;/p&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
CustomProfile profile = CustomProfile.GetProfile(&amp;quot;Lee&amp;quot;);

profile.Personal.FirstName = &amp;quot;Lee&amp;quot;;
profile.Personal.LastName = &amp;quot;Dumond&amp;quot;;
profile.Personal.DateOfBirth = new DateTime(1961, 10, 9);
profile.Personal.Gender = Gender.Male;
profile.Preferences.TimeZone = &amp;quot;Central Standard Time&amp;quot;;
profile.Preferences.Culture = &amp;quot;en-US&amp;quot;;

profile.Save();&lt;/pre&gt;
&lt;p&gt;If you like, you can make this even simpler by adding a &lt;tt&gt;Profile&lt;/tt&gt; property to the page you&amp;rsquo;re working with &amp;ndash; or even better, inherit your pages from a base type and add it there, so it&amp;rsquo;s available to all of your pages. This lets you &lt;strong&gt;set and retrieve profile properties with the familiar ASP.NET web site syntax&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
// set profile properties

Profile.Personal.FirstName = &amp;quot;Lee&amp;quot;;
Profile.Personal.LastName = &amp;quot;Dumond&amp;quot;;
Profile.Personal.DateOfBirth = new DateTime(1961, 10, 9);
Profile.Personal.Gender = Gender.Male;
Profile.Preferences.TimeZone = &amp;quot;Central Standard Time&amp;quot;;
Profile.Preferences.Culture = &amp;quot;en-US&amp;quot;;

Profile.Save();&lt;/pre&gt;
&lt;pre class="brush: csharp; auto-links: false;"&gt;
// display profile properties

lblDisplay.Text =
   string.Format(
      &amp;quot;User {0} had a real name of {1} {2}, was born on {3}, lives in the {4} time zone, and has a preferred culture of {5}.&amp;quot;,
      Profile.UserName, 
      Profile.Personal.FirstName, 
      Profile.Personal.LastName,
      Profile.Personal.DateOfBirth.ToShortDateString(),
      Profile.Preferences.TimeZone,
      Profile.Preferences.Culture);&lt;/pre&gt;
&lt;h3&gt;Sample Application&lt;/h3&gt;
&lt;p&gt;As I mentioned, I&amp;rsquo;ve included a downloadable web application solution that demonstrates web application profiles in action. When you run it, you&amp;rsquo;ll be greeted by the following screen:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/ASP.NETProfilesinWebApplicationProjects_A73B/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" width="304" height="264" src="http://leedumond.com/files/media/image/WindowsLiveWriter/ASP.NETProfilesinWebApplicationProjects_A73B/image_thumb_1.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are screens that let you display a profile, edit a profile, and create a new one.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/ASP.NETProfilesinWebApplicationProjects_A73B/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" width="304" height="264" src="http://leedumond.com/files/media/image/WindowsLiveWriter/ASP.NETProfilesinWebApplicationProjects_A73B/image_thumb_2.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/ASP.NETProfilesinWebApplicationProjects_A73B/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" width="304" height="317" src="http://leedumond.com/files/media/image/WindowsLiveWriter/ASP.NETProfilesinWebApplicationProjects_A73B/image_thumb_3.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Examining the source code, along with the preceding explanation, should make understanding these concepts a snap.&lt;/p&gt;
&lt;p&gt;I hope this helps the next time you find yourself needing access to profile properties&amp;nbsp;from a web application!&lt;/p&gt;
&lt;p&gt;Download sample code: &lt;a target="_blank" href="http://leedumond.com/files/downloads/WebApplicationProfileSample.zip"&gt;WebApplicationProfileSample.zip&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=tPcD5Ss0zmQ:4LCNC2c6tt4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=tPcD5Ss0zmQ:4LCNC2c6tt4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=tPcD5Ss0zmQ:4LCNC2c6tt4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=tPcD5Ss0zmQ:4LCNC2c6tt4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/tPcD5Ss0zmQ" height="1" width="1"/&gt;</description></item><item><title>One Year Later – What I’ve Learned About Blogging</title><link>http://leedumond.com/blog/one-year-later-what-ive-learned-about-blogging/</link><pubDate>Thu, 01 Oct 2009 13:00:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/one-year-later-what-ive-learned-about-blogging/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>6</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;Today marks the one year anniversary since I started this blog. That being the case, I guess it&amp;rsquo;s time for the obligatory blogiversary retrospective.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="first_birthday_cake" border="0" alt="first_birthday_cake" align="right" width="304" height="310" src="http://leedumond.com/files/media/image/WindowsLiveWriter/HappyBlogiversary_BDA0/first_birthday_cake_3.jpg" /&gt; October 1, 2008 was the day I arrived &lt;a target="_blank" href="http://leedumond.com/okay-so-i-finally-caved/"&gt;rather late and somewhat grudgingly&lt;/a&gt; to the blogosphere. One year later, I can honestly say that &lt;strong&gt;starting a blog was the best thing I&amp;rsquo;ve ever done for my career.&lt;/strong&gt; My only regret is that I didn&amp;rsquo;t do it &lt;em&gt;a whole lot sooner&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A year ago, I found myself in a somewhat awkward position. As a developer, I had welcomed and fully embraced the Web 2.0 concept; but as a user, not so much. The whole MySpace craze totally passed me by. I didn&amp;rsquo;t have a Facebook page (still holding out on that one), nor a Twitter account (&lt;a target="_blank" href="http://twitter.com/LeeDumond"&gt;I finally got one&lt;/a&gt; this past May). Social networking was just not my thing, thank you very much, and up until then I had been perfectly fine with that. But I was now starting to realize that the lack of interaction with the rest of the development community at large was holding me back.&lt;/p&gt;
&lt;p&gt;Blogging was something I wanted to try. But whenever I gave the idea any serious consideration, I found it much easier to come up with reasons why starting a blog &lt;em&gt;was just a bad idea&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What if I can&amp;rsquo;t think of anything to write about?&lt;/strong&gt; The web is littered with the dusty, desiccated remnants of broken blogger dreams &amp;ndash; good folks who I&amp;rsquo;m sure had the best of intentions, but just ran out of stuff to say.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What if nobody cares?&lt;/strong&gt; In many ways, the blogosphere is like a college frat party &amp;ndash; obnoxious, kind of smelly, and &lt;em&gt;entirely too loud&lt;/em&gt;. What would be the point of shouting over the din if no one is listening?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What if I don&amp;rsquo;t have the time, patience, and dedication it takes?&lt;/strong&gt; To me, starting a blog meant I was taking on a responsibility &amp;ndash; to myself, and to my readers. I knew I would have to approach this thing like I do everything else &amp;ndash; &lt;em&gt;all in,&lt;/em&gt; or &lt;em&gt;not at all&lt;/em&gt;. I set myself a goal of one post per week, which I hoped wasn&amp;rsquo;t too unreasonable given my already-overflowing schedule.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What if I&amp;rsquo;m just not smart enough?&lt;/strong&gt; The fear of being wrong is probably the number one reason I hesitated for so long. I was afraid that by publishing a blog, I would discover how truly ignorant I really was. Worse yet, I would be broadcasting that fact to the entire world in the process! It&amp;rsquo;s one thing to be stupid, but nobody wants to &lt;em&gt;look&lt;/em&gt; stupid &amp;ndash; especially in front of their peers.&lt;/p&gt;
&lt;h3&gt;What I&amp;rsquo;ve Learned&lt;/h3&gt;
&lt;p&gt;Running this blog has been a wonderful learning experience. The past year has granted me a good deal more perspective &amp;ndash; on the blogging process, on the developer community, and on myself as a human being. It&amp;rsquo;s been both frustrating and rewarding, discouraging and enlightening, in ways I never imagined. It has taken sacrifice, and brought pleasure and joy; both in great measure.&lt;/p&gt;
&lt;p&gt;So, were my initial trepidations justified? In some cases, they were. In case you&amp;rsquo;re wondering, here&amp;rsquo;s how it&amp;rsquo;s all turned out so far.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I have more things to write about than I&amp;rsquo;ll ever have time to get to.&lt;/strong&gt; Looking back, it&amp;rsquo;s hard to believe now that this was ever a concern &amp;ndash; quite frankly, once the ball got rolling, ideas started hitting me on the head like seagull shit at a French-fry factory. Software development is such a vast, all-encompassing field that I don&amp;rsquo;t see how it&amp;rsquo;s possible to run out of topics. For every blog post I actually publish, there are probably half a dozen others that won&amp;rsquo;t ever leave the confines of my brain, simply for lack of time. I believe if you are curious, open to learning new things, and try to remain aware of developments in your chosen field, coming up with blog post ideas should be the least of your problems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nobody cares, and that&amp;rsquo;s okay.&lt;/strong&gt; As a blogger, I think the sooner you come to grips with this, the better &amp;ndash; &lt;em&gt;nobody cares what you have to say&lt;/em&gt;. You aren&amp;rsquo;t changing the world. You aren&amp;rsquo;t curing cancer. Hell, you&amp;rsquo;re not even curing toe fungus. If you never wrote another post, the world would keep on turning and people would keep on living their lives like you never even existed.&lt;/p&gt;
&lt;p&gt;If you can get your head around that fact, and keep on writing anyway, then you have a shot at becoming a successful* blogger.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It&amp;rsquo;s a lot of work, but it&amp;rsquo;s worth it.&lt;/strong&gt; How much of a time commitment is really involved? There&amp;rsquo;s a lot of variation here &amp;ndash; some posts take an hour, others take days &amp;ndash; but I&amp;rsquo;d say on average, a decent blog post takes me about four hours to write. That&amp;rsquo;s not a trivial consideration. I have been posting about once a week this far, which is about &lt;em&gt;two full work weeks a year&lt;/em&gt;. Something has to give. For me, it&amp;rsquo;s meant fewer long bike rides, less watching TV, and in some cases less time with friends and family. If you run a blog, how much of a sacrifice you&amp;rsquo;re willing to make is up to you; just be aware that you &lt;em&gt;will&lt;/em&gt; have to make one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I don&amp;rsquo;t know could fill a bus.&lt;/strong&gt; I have found blogging a very humbling experience. If I could sum up what I&amp;rsquo;ve learned about myself through blogging in one sentence, it would be this: &lt;em&gt;I know a hell of a lot less about software development than I ever realized.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In fact, with each passing day, the amount of stuff &lt;em&gt;I know I don&amp;rsquo;t know&lt;/em&gt; seems to increase. That may not sound like progress, but actually &lt;em&gt;it is&lt;/em&gt;. As former Defense Secretary &lt;a target="_blank" href="http://politicalhumor.about.com/cs/quotethis/a/rumsfeldquotes.htm"&gt;Donald Rumsfeld&lt;/a&gt; once said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;hellip; as we know, there are known knowns; there are things we know we know. We also know there are known unknowns; that is to say we know there are some things we do not know. But there are also unknown unknowns -- the ones we don't know we don't know.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a concept so stupid, it&amp;rsquo;s brilliant. I don&amp;rsquo;t think I could sum it up any better.&lt;/p&gt;
&lt;h3&gt;The Meaning of Success&lt;/h3&gt;
&lt;p&gt;*In blogging, like in any activity, determining whether you&amp;rsquo;re &amp;ldquo;successful&amp;rdquo; depends on exactly how you define success.&lt;/p&gt;
&lt;p&gt;Am I a successful blogger like &lt;a target="_blank" href="http://codinghorror"&gt;Jeff Atwood&lt;/a&gt; is a successful blogger, or like &lt;a target="_blank" href="http://computerzen.com"&gt;Scott Hanselman&lt;/a&gt; is a successful blogger? Of course not. I harbor no delusions in this regard, current or future. Sure, I&amp;rsquo;ve built a pretty loyal subscriber base and I&amp;rsquo;m getting good traffic; and yes, I&amp;rsquo;m proud of that. Subscriber counts and traffic are certainly valid ways to measure success, but they aren&amp;rsquo;t the only way.&lt;/p&gt;
&lt;p&gt;How about community recognition? I see that Jurgen Appelo recently published this quarter&amp;rsquo;s &lt;a target="_blank" href="http://www.noop.nl/2009/09/top-200-blogs-for-developers-q3-2009.html"&gt;Top 200 Blogs for Developers&lt;/a&gt; list. Am I unsuccessful because I didn&amp;rsquo;t appear on it? I don&amp;rsquo;t think so, though I vow to keep trying (you hear that, Jurgen? ;) Despite that, a few of my posts have garnered a good deal of attention, and that&amp;rsquo;s pretty awesome. The validation of your peers is another valid way to measure success &amp;ndash; but again, it&amp;rsquo;s not the only way.&lt;/p&gt;
&lt;p&gt;If the efforts I&amp;rsquo;ve made on this blog can be considered &lt;em&gt;successful in any sense&lt;/em&gt;, it is this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Today is October 1, 2009 --&amp;nbsp; exactly one year later &amp;ndash; and I&amp;rsquo;m still at it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Happy Blogiversary to me. ;)&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=AVemDNjVxCA:ggSl5xUeM2o:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=AVemDNjVxCA:ggSl5xUeM2o:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=AVemDNjVxCA:ggSl5xUeM2o:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=AVemDNjVxCA:ggSl5xUeM2o:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/AVemDNjVxCA" height="1" width="1"/&gt;</description></item><item><title>Orphans at the Bookstore</title><link>http://leedumond.com/blog/orphans-at-the-bookstore/</link><pubDate>Mon, 28 Sep 2009 19:32:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/orphans-at-the-bookstore/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>0</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;What do the companies who publish technical books &amp;ndash; and the authors who write them &amp;ndash; &lt;em&gt;really&lt;/em&gt; owe their readers?&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="lonely_book" border="0" alt="lonely_book" align="right" width="304" height="229" src="http://leedumond.com/files/media/image/WindowsLiveWriter/BookSupport_C29E/lonely_book_3.jpg" /&gt;It&amp;rsquo;s rare to find an instance in which you pay good money for software, and are subsequently unable to find any kind of support whatsoever.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re not talking about freeware or open-source here (you can&amp;rsquo;t rightfully demand much handholding if you&amp;rsquo;re not paying for the product). No, we&amp;rsquo;re talking commercial software from well-established companies. If you&amp;rsquo;ve laid your money down, you rightfully expect the company to provide a modicum of support. If they don&amp;rsquo;t provide access to real live humans via telephone (&lt;a target="_blank" href="http://leedumond.com/blog/its-a-self-self-self-serve-world/"&gt;fewer and fewer companies do these days&lt;/a&gt;), at least there&amp;rsquo;s an email address or support forum, often supplemented by a FAQ, knowledgebase, or wiki of some kind. Most of the time, that&amp;rsquo;s more than you need to get a question answered.&lt;/p&gt;
&lt;p&gt;Software companies have to support the products they sell. Developers are expected to support the software they write.&lt;/p&gt;
&lt;p&gt;So, &lt;strong&gt;why don&amp;rsquo;t technical publishers and authors feel obligated to support their own books?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re like me, you&amp;rsquo;ve probably spent a pretty decent chunk of change on tech books, so you know what I&amp;rsquo;m talking about. Of course, there&amp;rsquo;s always the pretty sales page with a synopsis, table of contents, a place to download errata or sample code &amp;ndash; and oh yes, that big shiny &amp;ldquo;Buy Now&amp;rdquo; button. But far too often, &lt;strong&gt;publishers provide no medium with which to provide meaningful feedback, to interact with the author(s), or to even ask a simple question pertaining to the book&amp;rsquo;s content.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It is unfathomable to me that,&lt;strong&gt; &lt;/strong&gt;&lt;em&gt;in an industry that relies so heavily on repeat business&lt;/em&gt;, &lt;strong&gt;publishers and authors have such little grasp on the concept of providing &amp;ldquo;service after the sale.&amp;rdquo; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To be fair, some publishers &lt;em&gt;do&lt;/em&gt; take the extra step. Both &lt;a target="_blank" href="http://manning.com/"&gt;Manning&lt;/a&gt; and &lt;a target="_blank" href="http://www.wrox.com/WileyCDA/"&gt;Wrox&lt;/a&gt;, for example, publish online forums for the titles they sell. This goes a long way toward letting readers help other readers; sometimes, even mini-communities are formed. Unfortunately, neither company compels the authors themselves to participate or contribute. Other publishers seem to rely on the authors to &amp;ldquo;support&amp;rdquo; the book themselves &amp;ndash; by supplying a link to an author&amp;rsquo;s blog, for example. Sometimes these authors oblige, though the level of enthusiasm, dedication, and responsiveness varies greatly. Sometimes, they don&amp;rsquo;t bother at all.&lt;/p&gt;
&lt;p&gt;I suspect the reason publishers don&amp;rsquo;t obligate the authors to answer questions about their own books is a financial one. During my years as a contributing editor at &lt;a target="_blank" href="http://www.recordingmag.com/"&gt;Recording Magazine&lt;/a&gt;, authors were paid by the article. An email address was printed at the end of every piece, and most articles solicited a number of follow up questions from readers. Though the publisher forwarded these questions to the author, it was made abundantly clear that they were &lt;em&gt;in no way obligated to answer them, because the company would not pay them extra to do so. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a target="_blank" href="http://www.wrox.com/WileyCDA/Section/id-WROX_SEARCH_RESULT.html?query=lee%20dumond"&gt;stuff I&amp;rsquo;ve written for Wrox&lt;/a&gt; has solicited a fair number of questions, many of which come through the contact page of my blog. Wrox doesn&amp;rsquo;t pay me to answer them &amp;ndash; but &lt;strong&gt;I do anyway, out of sheer pride and a sense of obligation to my readers.&lt;/strong&gt; However, it&amp;rsquo;s painfully clear that many authors feel no such obligation. Once the advance is spent, the final draft is turned in, and the royalty checks start coming, they seem all too willing to put the project behind them. They just don&amp;rsquo;t feel as though the owe their readers anything.&lt;/p&gt;
&lt;h3&gt;What Can You Do? What &lt;em&gt;Should&lt;/em&gt; You Do?&lt;/h3&gt;
&lt;p&gt;Given the current economic climate, asking publishers to shell out more dough probably won&amp;rsquo;t get us very far. But, depending on where you stand in the technical book food chain, you can play an active role.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you&amp;rsquo;re a reader:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Reward publishers who &lt;strong&gt;provide opportunities to interact&lt;/strong&gt; with authors and other readers, by making this part of your purchasing decision.&lt;/li&gt;
    &lt;li&gt;Favor authors who &lt;strong&gt;actively participate&lt;/strong&gt; in publisher-provided forums.&lt;/li&gt;
    &lt;li&gt;Favor authors who &lt;strong&gt;supply supplemental or ancillary book material&lt;/strong&gt; on their personal blogs.&lt;/li&gt;
    &lt;li&gt;Support authors &lt;strong&gt;who encourage feedback and are responsive&lt;/strong&gt; to reader questions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="adoptabook" border="0" alt="adoptabook" align="right" width="304" height="229" src="http://leedumond.com/files/media/image/WindowsLiveWriter/BookSupport_C29E/adoptabook_5.jpg" /&gt;If you&amp;rsquo;re a publisher:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Provide an &lt;strong&gt;forum for readers to interact&lt;/strong&gt; with editors, authors, and other readers.&lt;/li&gt;
    &lt;li&gt;Ask authors in advance if they intend to voluntarily &lt;strong&gt;support the book post-publication&lt;/strong&gt;, and how they plan to do that. Make authors put this in writing as part of the book proposal.&lt;/li&gt;
    &lt;li&gt;Encourage authors to &lt;strong&gt;treat their work as a living, breathing project&lt;/strong&gt;, and give them the means to help them do so.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;If you&amp;rsquo;re an author:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Writing a book is like having a baby. Remember that the &amp;ldquo;construction phase&amp;rdquo; &amp;ndash; difficult though it may be &amp;ndash; is only the beginning.&lt;/li&gt;
    &lt;li&gt;Understand that &lt;strong&gt;technical books undergo a &amp;ldquo;life cycle&amp;rdquo;&lt;/strong&gt; after they are published, and that the first few months after it hits the streets are the most critical. Actively engaging and interacting with readers early in this life cycle will pay off once the market for your book matures.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Seek out the places your book is being discussed&lt;/strong&gt; &amp;ndash; on the publisher&amp;rsquo;s website, on Amazon, on Twitter, and in the personal blogs of your readers. Remember, readers won&amp;rsquo;t always come directly to you with their thoughts, comments, and questions, but they &lt;em&gt;will&lt;/em&gt; have them.&lt;/li&gt;
    &lt;li&gt;If you&amp;rsquo;ve published a sample application with your book, &lt;strong&gt;consider hosting your code in a online repository&lt;/strong&gt; such as CodePlex. Encourage readers to submit bug reports and suggestions for improvements, and solicit their help in maintaining the codebase.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Keep the book alive on your own blog!&lt;/strong&gt; If you&amp;rsquo;ve identified a pain-point readers are having, a particular section that bears further explanation, or an assertion that&amp;rsquo;s being challenged, put up a post about it. Justify the decisions you&amp;rsquo;ve made and the conclusions you&amp;rsquo;ve drawn, and be open-minded to reader comments expressing other points of view.&lt;/li&gt;
    &lt;li&gt;Think of your own bottom line! If you aren&amp;rsquo;t proud enough of your work to support it for any other reason, do it because it will help &lt;strong&gt;sell more books.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You wouldn&amp;rsquo;t think of buying a car, a refrigerator, or a piece of software without the promise of some kind of support if you need it, would you? Yet for some reason, we do this all the time when buying technical books, seemingly without hesitation.&lt;/p&gt;
&lt;p&gt;Think about that the next time you&amp;rsquo;re about to carry your new-found tome to the cash register, or click that big shiny Buy Now button. Otherwise, the book you&amp;rsquo;re purchasing may barely be worth the paper it&amp;rsquo;s printed on.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=OM3z7lz8-Hs:2X0ftiW-vJA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=OM3z7lz8-Hs:2X0ftiW-vJA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=OM3z7lz8-Hs:2X0ftiW-vJA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=OM3z7lz8-Hs:2X0ftiW-vJA:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/OM3z7lz8-Hs" height="1" width="1"/&gt;</description></item><item><title>Chocolate Salty Bools</title><link>http://leedumond.com/blog/chocolate-salty-bools/</link><pubDate>Tue, 22 Sep 2009 22:42:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/chocolate-salty-bools/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>15</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;A couple of Boolean-related anti-patterns, and what to do about them.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;You&amp;rsquo;ve probably noticed a lot of bloggers use their platform to vent their frustrations. This is one of those posts.&lt;/p&gt;
&lt;p&gt;I happen to be working on a &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Brownfield_land"&gt;brownfield&lt;/a&gt; application that manages a repair shop for motorcycles. I don&amp;rsquo;t mind telling you that this particular application is a &lt;em&gt;deep, dark shade of brown&lt;/em&gt;, and I don&amp;rsquo;t mean because it just came back from Disney World.&lt;/p&gt;
&lt;p&gt;Modeling a business process like this often involves tracking the current state of various domain objects. The code here uses enumerations to express those states, which is a good thing. Enumerations are much more expressive than integers, far more type-safe than magic strings, and can help eliminate a lot of messy switch statements and such from your code. But one of the issues with this app is that it&amp;rsquo;s full of &lt;em&gt;two-valued&lt;/em&gt; enumerations, like this:&lt;/p&gt;
&lt;pre class="brush: csharp; toolbar: false; auto-links: false;"&gt;
namespace RepairShop
{
   public enum ServiceStatus
   {
      InService,
      ServiceComplete
   }
}&lt;/pre&gt;
&lt;p&gt;Upon first glance, this makes sense. The repair status of a motorcycle can have two states. When you take in a broken one, you mark it &amp;ldquo;InService&amp;rdquo;. When you finish fixing it, you mark it &amp;ldquo;ServiceComplete&amp;rdquo;.&lt;/p&gt;
&lt;pre class="brush: csharp; toolbar: false; auto-links: false;"&gt;
public class Motorcycle
{
   public ServiceStatus ServiceStatus { get; set; }
   public string TagNumber { get; set; }

   public void TakeInForService()
   {
      this.ServiceStatus = ServiceStatus.InService;
      this.Update();
   }
   
   public void MarkServiceComplete()
   {
      this.ServiceStatus = ServiceStatus.ServiceComplete;
      this.Update();
   }

   public void Update()
   {
      MotorcycleData.Update(this);
   }      
}&lt;/pre&gt;
&lt;h3&gt;Oooo, That Smell&lt;/h3&gt;
&lt;p&gt;Looking at several of these enumerations, something didn&amp;rsquo;t seem quite right. It was then I realized something &amp;ndash; &lt;strong&gt;two-valued enumerations are&lt;/strong&gt; &lt;strong&gt;a &lt;/strong&gt;&lt;a target="_blank" href="http://en.wikipedia.org/wiki/Code_smell"&gt;&lt;strong&gt;code smell&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt; I&amp;rsquo;ve never seen this in any code smell list I&amp;rsquo;ve ever read, but it definitely needs to be included.&lt;/p&gt;
&lt;p&gt;A little bit of refactoring lets us simplify things, and eliminate the enumeration type from the codebase altogether.&lt;/p&gt;
&lt;pre class="brush: csharp; toolbar: false; auto-links: false; highlight: [3,8,14];"&gt;
public class Motorcycle
{
   public bool ServiceStatus { get; set; }
   public string TagNumber { get; set; }

   public void TakeInForService()
   {
      this.ServiceStatus = true;
      this.Update();
   }
   
   public void MarkServiceComplete()
   {
      this.ServiceStatus = false;
      this.Update();
   }

   public void Update()
   {
      MotorcycleData.Update(this);
   }      
}&lt;/pre&gt;
&lt;p&gt;The simple fact is that &lt;strong&gt;when any property has two and only two states, that property can &lt;em&gt;always&lt;/em&gt; be typed as a Boolean.&lt;/strong&gt; In or Out. On or Off. Black or White. If you&amp;rsquo;ve only got two choices, &lt;em&gt;why not use a perfectly good, built-in two-valued type&lt;/em&gt; instead of making up a new one?&lt;/p&gt;
&lt;h3&gt;He Who Smelt It, Dealt It&lt;/h3&gt;
&lt;p&gt;But hold on a minute &amp;ndash; this refactoring isn&amp;rsquo;t quite done. When examining the value of &lt;tt&gt;ServiceStatus&lt;/tt&gt;&amp;nbsp; in a &lt;tt&gt;Motorcycle&lt;/tt&gt; object, one might naturally assume that &lt;tt&gt;ServiceStatus = true&lt;/tt&gt; means &amp;ldquo;it&amp;rsquo;s bring worked on&amp;rdquo; and &lt;tt&gt;ServiceStatus = false&lt;/tt&gt; means &amp;ldquo;it&amp;rsquo;s done.&amp;rdquo; However, this isn&amp;rsquo;t totally obvious, or even semantically meaningful. This leads us to &lt;strong&gt;another new code smell: Boolean Jeopardy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Why &amp;ldquo;Boolean Jeopardy?&amp;rdquo; That&amp;rsquo;s because Boolean values are either &lt;tt&gt;true&lt;/tt&gt; or &lt;tt&gt;false&lt;/tt&gt;; and semantically speaking, &lt;tt&gt;true&lt;/tt&gt; and &lt;tt&gt;false&lt;/tt&gt; are &lt;em&gt;responses to a yes-or-no question.&lt;/em&gt; Therefore, &lt;strong&gt;anything of type Boolean should always be named &lt;em&gt;in the form of a question&lt;/em&gt; &amp;ndash;&lt;/strong&gt; more specifically, &lt;strong&gt;a binary (yes-or-no) question.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="brush: csharp; toolbar: false; auto-links: false; highlight: [3,8,14];"&gt;
public class Motorcycle
{
   public bool IsInService { get; set; }
   public string TagNumber { get; set; }

   public void TakeInForService()
   {
      this.IsInService = true;
      this.Update();
   }
   
   public void MarkServiceComplete()
   {
      this.IsInService = false;
      this.Update();
   }

   public void Update()
   {
      MotorcycleData.Update(this);
   }      
}&lt;/pre&gt;
&lt;p&gt;You should apply this naming rule to &lt;em&gt;anything&lt;/em&gt; that&amp;rsquo;s a Boolean: including fields, properties, bool-returning methods, even bit columns in database tables. A good way to do this is to try to &lt;em&gt;start with the word &amp;lsquo;Is&amp;rsquo; for booleans that apply to single entities, and &amp;lsquo;Are&amp;rsquo; for collections.&lt;/em&gt;&lt;/p&gt;
&lt;pre class="brush: csharp; toolbar: false; auto-links: false; highlight: [7,13,17];"&gt;
internal class CookieProgram
{
   private static void Main()
   {
      IList&amp;lt;Cookie&amp;gt; cookies = Cookie.GetCookieBatch();

      if (AreCookiesDone(cookies))
      {
         RemoveFromOven(cookies);
      }
   }

   private static bool AreCookiesDone(IEnumerable&amp;lt;Cookie&amp;gt; cookies)
   {
      foreach (Cookie cookie in cookies)
      {
         if (!cookie.IsDone)
         {
            return false;
         }
      }

      return true;
   }

   private static void RemoveFromOven(IEnumerable&amp;lt;Cookie&amp;gt; cookies)
   {
      // blah blah blah
   }
}&lt;/pre&gt;
&lt;h3&gt;Get the Funk Out&lt;/h3&gt;
&lt;p&gt;Okay, so we&amp;rsquo;ve identified a couple of Boolean-related whiffs, and come up with a couple of associated refactorings.&lt;/p&gt;
&lt;p&gt;I call the first one &lt;strong&gt;Two-Valued Enumeration.&lt;/strong&gt; Enumerations are very handy, but can be tricky to deal with in code, and can lead to unnecessary complexity when overused. Any two-valued enumeration can and should be expressed as a Boolean, which is a built-in, dual-valued primitive type. To eradicate this smell, apply the &lt;strong&gt;Replace Two-Valued Enumeration With Boolean&lt;/strong&gt; refactoring.&lt;/p&gt;
&lt;p&gt;When you do that, pay attention to the name you give your new Boolean, lest you end up with the &lt;strong&gt;Boolean Jeopardy&lt;/strong&gt; smell. Since the values that a Boolean can hold are &lt;tt&gt;true&lt;/tt&gt; or &lt;tt&gt;false&lt;/tt&gt;, the names of Boolean entities (fields, properties, methods, database columns, and so forth) carry more semantic meaning when they appear in the form of a question. Apply the &lt;strong&gt;Rename Boolean As Binary Question&lt;/strong&gt; refactoring to any offenders you find.&lt;/p&gt;
&lt;p&gt;Happy refactoring, and thanks for letting me vent.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=Y0lPTR648gI:NAy0RbgOdC4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=Y0lPTR648gI:NAy0RbgOdC4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=Y0lPTR648gI:NAy0RbgOdC4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=Y0lPTR648gI:NAy0RbgOdC4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/Y0lPTR648gI" height="1" width="1"/&gt;</description></item><item><title>It’s a Self, Self, Self Serve World</title><link>http://leedumond.com/blog/its-a-self-self-self-serve-world/</link><pubDate>Fri, 18 Sep 2009 17:37:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/its-a-self-self-self-serve-world/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>6</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;How and why today&amp;rsquo;s companies boost productivity by using technology to tap a vast reserve of willing, free labor &amp;ndash; you.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;I&amp;rsquo;ll never forget the first time I got fired.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Gomer_Pyle" border="0" alt="Gomer_Pyle" align="right" width="304" height="229" src="http://leedumond.com/files/media/image/WindowsLiveWriter/WebSlaves_1019E/Gomer_Pyle_3.jpg" /&gt;I was a kid in Portland, Maine, working as a gas station attendant. (Remember gas station attendants? Probably not, unless you&amp;rsquo;re over 35.)&lt;/p&gt;
&lt;p&gt;Anyway, after a long and arduous ten-hour shift standing in the rain and sucking fumes, I balanced my &amp;ldquo;cash drawer&amp;rdquo; (which was in reality the pockets of my jeans) and came up 50 cents short. &lt;em&gt;Fifty cents&lt;/em&gt;. I had pumped nearly 2,000 gallons of gas that day, but that didn&amp;rsquo;t matter. In the eyes of my boss, fifty cents short was fifty cents too much.&lt;/p&gt;
&lt;p&gt;The rule at this place was simple &amp;ndash; if your cash didn&amp;rsquo;t balance out, you were &lt;em&gt;gone&lt;/em&gt;, &lt;em&gt;period&lt;/em&gt;. The company who owned this station ran several dozen other stations just like it, and I guess they figured that two bits here and two bits there might&amp;nbsp;eventually, somehow,&amp;nbsp;add up to real money.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It was a few years later that this company installed self-serve automated pumps in all of their stations, and fired every attendant in their employ.&lt;/strong&gt; No more attendant wages. No more of the associated worker&amp;rsquo;s comp premiums, unemployment premiums, or matching FICA payments.&lt;/p&gt;
&lt;p&gt;Productivity swelled. The company literally saved millions, which they eagerly pocketed as profit. And guess what? They never came up short on a shift again, either.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Did these automated pumps eliminate the actual task of getting the gasoline out of the ground and into the cars?&lt;/strong&gt; Of course not. But now, &lt;em&gt;the station was able to demand that customers do that&lt;/em&gt;. Oh sure, some were reluctant at first. But as soon as they realized that every station in town was jumping on the self-serve bandwagon (hey, gas station owners are no dummies), the options were pretty clear &amp;ndash; open your own petroleum refinery, take the bus, or learn to deal with the indignity of being coerced into service as a lowly part-time pump jockey. &lt;em&gt;Suck fumes or walk&lt;/em&gt;, pal.&lt;/p&gt;
&lt;p&gt;Little did we know that self-service gasoline was only the tip of the iceberg.&lt;/p&gt;
&lt;p&gt;The first automated pumps were expensive and s &amp;ndash; l &amp;ndash; o - w, communicating at 300 baud over regular lines leased from the local telephone company. But like all technology, pumps became much cheaper, much faster, and much more capable. Running a station became more profitable than ever. More and more stations opened, and larger stations soon became the norm.&lt;/p&gt;
&lt;h3&gt;The Great Productivity Myth&lt;/h3&gt;
&lt;p&gt;It was not long before other industries sat up and took notice.&lt;/p&gt;
&lt;p&gt;Today&amp;rsquo;s businesses aren&amp;rsquo;t saddled with the burden of massively expensive hardware and dog-slow data transmission. PCs are practically disposable, servers are dirt cheap, and bandwidth is now a commodity. This revolution in hardware, combined with the big ol&amp;rsquo; Inter-tubes and the technologies that run on it &amp;ndash; the World Wide Web, email, and the rest &amp;ndash; is allowing enterprises of all kinds, from the airlines to your local grocery store, do what the gas stations did.&lt;/p&gt;
&lt;p&gt;They too have enjoyed unprecedented gains in productivity. If you asked their accountants how, they&amp;rsquo;d tell you they did it the old-fashioned way &amp;ndash; by reducing costs. From an &lt;em&gt;financial&lt;/em&gt; point of view, that's technically correct. But from a &lt;em&gt;societal &lt;/em&gt;point of view, &lt;strong&gt;true costs are not being reduced at all, but merely shifted off the books &amp;ndash;&lt;/strong&gt; a macroeconomic sleight-of-hand that places inputs outside the purview of the enterprise.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="jamielynn" border="0" alt="jamielynn" align="left" width="163" height="244" src="http://leedumond.com/files/media/image/WindowsLiveWriter/WebSlaves_1019E/jamielynn_3.jpg" /&gt;In any capitalistic endeavor, the &lt;em&gt;most expensive input by far is labor.&lt;/em&gt; Here in the US and elsewhere throughout the developed world, the cost of labor per dollar&amp;rsquo;s worth of output is dropping precipitously. Is this because there&amp;rsquo;s less work to be done? Or is it because &lt;strong&gt;true labor costs aren&amp;rsquo;t being accounted for?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Think of it this way &amp;ndash; if I pay a high-school kid to put &lt;em&gt;my&lt;/em&gt; gas into &lt;em&gt;your&lt;/em&gt; car, that&amp;rsquo;s a cost to me. If I get &lt;em&gt;you&lt;/em&gt; to do it, it&amp;rsquo;s not. &lt;em&gt;The gas is still getting into the car&lt;/em&gt;, but this way, nowhere on my books do I have to account for that fact. See how that works?&lt;br clear="left" /&gt;
&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Artificial Artificial Intelligence&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/WebSlaves_1019E/frustrated_2.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="frustrated" border="0" alt="frustrated" align="right" width="244" height="168" src="http://leedumond.com/files/media/image/WindowsLiveWriter/WebSlaves_1019E/frustrated_thumb.jpg" /&gt;&lt;/a&gt; With each passing year, &lt;strong&gt;American consumers are becoming increasingly pressed into a form of consumption-based indentured servitude&lt;/strong&gt;, made possible by cheap hardware, cheap connectivity, and cheap, ubiquitous Internet access, and businesses are reaping the benefits.&lt;/p&gt;
&lt;p&gt;Twenty years ago, if you had an issue with your bank account, you&amp;rsquo;d ask a teller. Today, you are instructed on how to find that information yourself; in fact, many banks now &lt;em&gt;charge a fee to even speak to a human teller&lt;/em&gt;. Fifteen years ago, most people wouldn&amp;rsquo;t have dreamed of booking their own airline flight. Today, not only are we expected to book our own travel as a matter of course, we print our own itineraries and our own boarding passes, and check our own bags, too. Grocery stores with manual checkouts are served by one casher per terminal. In those now installing self-serve checkouts, a cashier handles six terminals. May God help you if the sticker falls off your banana.&lt;/p&gt;
&lt;p&gt;In the tech world, not all that long ago, it was just &lt;em&gt;assumed&lt;/em&gt; that knowledgeable, competent technical support was never more than a phone call away. Today, if you are fortunate, the company you&amp;rsquo;re dealing with may offer a support &amp;ldquo;package&amp;rdquo; &amp;ndash; one that requires you to &lt;em&gt;pay&lt;/em&gt; for the privilege of speaking to a human, and pay even more if you want to assure that human speaks the same language as you. Free technical support has now been pushed entirely online, to be found in the form of incomprehensible wikis, outdated FAQs, esoteric so-called &amp;ldquo;knowledge&amp;rdquo; bases, or online forums where customers are not only required to help &lt;em&gt;themselves&lt;/em&gt;, but are encouraged to devote their spare time helping &lt;em&gt;each other,&lt;/em&gt; perhaps predicated on the belief that when frustrated users find themselves in the same boat, they will attempt to row together.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="turk" border="0" alt="turk" align="right" width="242" height="167" src="http://leedumond.com/files/media/image/WindowsLiveWriter/WebSlaves_1019E/turk_3.jpg" /&gt; The Web has &lt;strong&gt;turned us into our own bankers, our own travel agents, and our own support desks.&lt;/strong&gt; It has turned &lt;strong&gt;investors into their own brokers&lt;/strong&gt;, &lt;strong&gt;students into their own teachers&lt;/strong&gt;, and &lt;strong&gt;patients into their own doctors.&lt;/strong&gt; While many of us continue to perceive the Web as a communications/entertainment/social networking medium, many businesses clearly see it as something else &amp;ndash; a means of leveraging a motivated, compliant, highly scalable workforce on-demand; in effect, a giant &lt;a target="_blank" href="https://www.mturk.com/mturk/welcome"&gt;Mechanical Turk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;br clear="right" /&gt;
&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m certainly not saying that this is &lt;em&gt;all&lt;/em&gt; bad. Like most people, I enjoy the convenience of being able to check my bank balance online, for example. That is what the Web is good at &amp;ndash; pushing data around. &lt;em&gt;That is&lt;/em&gt;, in fact, &lt;em&gt;the&lt;/em&gt; &lt;em&gt;only thing the Web is good at&lt;/em&gt;. If you can take a problem and accurately express in terms of a simple data transaction, then that&amp;rsquo;s a good Web application.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/WebSlaves_1019E/robot-teacher-315_2.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 15px 15px 0px; display: inline; border-top: 0px; border-right: 0px" title="robot-teacher-315" border="0" alt="robot-teacher-315" align="left" width="242" height="174" src="http://leedumond.com/files/media/image/WindowsLiveWriter/WebSlaves_1019E/robot-teacher-315_thumb.jpg" /&gt;&lt;/a&gt; &lt;strong&gt;The problem lies in how organizations are attempting to shove increasingly complex domains into this simple exchange-of-data paradigm.&lt;/strong&gt; Consider, for example, the fast-growing trend among colleges and universities toward &lt;em&gt;self-service education&lt;/em&gt; &amp;ndash; supplanting the traditional classroom lecture with online &amp;ldquo;instruction.&amp;rdquo; Standardized, cookie-cutter lesson plans allow the use of lower-paid, less qualified faculty. More students can be registered per session. There are fewer facilities to maintain, and no classroom to heat or light. The school then uses the &amp;ldquo;convenience factor&amp;rdquo; to justify exacting an additional &amp;ldquo;technology fee.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;In this scenario, &lt;em&gt;the university wins, but the students lose&lt;/em&gt;. That's because online instruction is an imperfect, incomplete model of&amp;nbsp;the real-time, physical, face-to-face interaction that normally takes place between students and teachers, and among students themselves.&amp;nbsp;Forums, chat rooms, and email are merely tools used to emulate&amp;nbsp;the organic nature of a&amp;nbsp;&lt;em&gt;real&lt;/em&gt; classroom. In this case, the exchange of &lt;em&gt;data&lt;/em&gt; simply cannot truly replicate the exchange of &lt;em&gt;knowledge&lt;/em&gt;, or of ideas, or of service; but can only serve as&amp;nbsp;a dim digital approximation thereof.&lt;/p&gt;
&lt;h3&gt;Pay No Attention to the Man Behind the Curtain&lt;/h3&gt;
&lt;p&gt;In a world where institutions of all kinds have long ago&amp;nbsp;squeezed every penny out of the supply chain, those institutions are being compelled to automate more and more of their processes in order to boost productivity, which brings us to the real issue &amp;ndash; &lt;strong&gt;the inexact and imperfect art of modeling complex &amp;ldquo;meat-world&amp;rdquo; business processes and transactions in software.&lt;/strong&gt; Since all&amp;nbsp;software can do is manipulate data, the success of a given solution lies in how well it models its problem domain as data.&lt;/p&gt;
&lt;p&gt;When it comes to checking my bank balance or transferring funds, the Web is great. That&amp;rsquo;s a pretty simple transaction; one that can be expressed perfectly in terms of ones and zeros.&lt;/p&gt;
&lt;p&gt;However, with more complex processes such as educating our students, as we&amp;rsquo;ve just seen, technological models often fall short.&lt;/p&gt;
&lt;p&gt;And in those frequent situations &lt;strong&gt;when a piece of the domain puzzle can&amp;rsquo;t be modeled inside the system at all&lt;/strong&gt; (think gas pumps here), &lt;strong&gt;it then falls upon the actor in that particular use case&lt;/strong&gt; (read: &lt;em&gt;you&lt;/em&gt;) &lt;strong&gt;to provide the missing &amp;ldquo;functionality.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Futurists once told us that &amp;ldquo;smart machines&amp;rdquo; would one day open up a utopian world of decadent leisure, but that's not happening.&amp;nbsp;Let's not kid ourselves.&amp;nbsp;We&amp;rsquo;ve seen the future, in which the old dreams of artificial intelligence are being replaced by a new reality in which &lt;strong&gt;&amp;ldquo;intelligent&amp;rdquo; systems use &lt;em&gt;thier own users &lt;/em&gt;as &lt;em&gt;actual components &lt;/em&gt;in the application.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Welcome ladies and gentlemen, to the super-duper, ultra-convenient, self, self, self serve world. It appears we have truly found the ghost in the machine, and it is us.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=U7ih59-ahNI:guhGfEbSqZo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=U7ih59-ahNI:guhGfEbSqZo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=U7ih59-ahNI:guhGfEbSqZo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=U7ih59-ahNI:guhGfEbSqZo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/U7ih59-ahNI" height="1" width="1"/&gt;</description></item><item><title>Balsamiq – It’s Not Just For Salad Anymore</title><link>http://leedumond.com/blog/balsamiq-its-not-just-for-salad-anymore/</link><pubDate>Fri, 04 Sep 2009 19:51:00 GMT</pubDate><guid isPermaLink="true">http://leedumond.com/blog/balsamiq-its-not-just-for-salad-anymore/</guid><dc:creator>Lee Dumond</dc:creator><slash:comments>7</slash:comments><category domain="http://leedumond.com/blog/">Blog</category><description>&lt;p&gt;A true balsamic vinegar &amp;ndash; the traditional, top-shelf, aged for 12 years stuff &amp;ndash; is highly prized by foodies all over the world. Balsamiq Mockups, while it doesn&amp;rsquo;t taste nearly as good on salad, is quickly becoming just as invaluable to developers, designers, PMs, and anyone else involved in the creation of software. Here&amp;rsquo;s why.&lt;/p&gt;&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/mockups_fpa_2.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mockups_fpa" border="0" alt="mockups_fpa" align="right" width="300" height="231" src="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/mockups_fpa_thumb.jpg" /&gt;&lt;/a&gt;&lt;a target="_blank" href="http://www.balsamiq.com/products/mockups"&gt;Balsamiq Mockups&lt;/a&gt; is the flagship product from startup ISV &lt;a target="_blank" href="http://www.balsamiq.com/"&gt;Balsamiq Studios&lt;/a&gt;. The &lt;a target="_blank" href="http://www.balsamiq.com/products/mockups/desktop"&gt;desktop version&lt;/a&gt; (which I&amp;rsquo;m reviewing here) runs on any platform supported by &lt;a target="_blank" href="http://www.adobe.com/products/air/"&gt;Adobe Air&lt;/a&gt;, including Windows, Mac, and Linux (yes, finally, an Adobe Air application that&amp;rsquo;s not a &lt;a target="_blank" href="http://twitter.com/"&gt;Twitter&lt;/a&gt; client &amp;ndash; go figure). There are also plug-in versions available that integrate with popular wiki and bug-tracking tools such as Confluence, JIRA, XWiki, and FogBugz. A online, subscription-based version is reportedly in the works as well.&lt;/p&gt;
&lt;h3&gt;What&amp;rsquo;s the Problem?&lt;/h3&gt;
&lt;p&gt;This is the point where most reviewers would drag out the elaborate dog-and-pony show, but I&amp;rsquo;d prefer not to waste time better spent &lt;del&gt;abusing&lt;/del&gt; evaluating the &lt;a target="_blank" href="http://www.balsamiq.com/products/mockups/desktop#download"&gt;demo&lt;/a&gt; on your own. Rather than delve too deeply into all the little tricks Balsamiq can &lt;em&gt;do&lt;/em&gt;, let&amp;rsquo;s consider for a moment the &lt;em&gt;problem it is intended to solve&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Pretend if you will you&amp;rsquo;re a software developer (if you&amp;rsquo;re reading this, that shouldn&amp;rsquo;t be too much of a stretch, right?) and you&amp;rsquo;re meeting with a few client reps to toss around some early prototype ideas for an application. You (or someone from your design team) have labored long and hard to put together a few slick-looking layouts, hoping to impress.&lt;/p&gt;
&lt;p&gt;You hook your laptop to the conference room projector, fire it up, hit F12, and&amp;hellip;&lt;/p&gt;
&lt;div style="margin-left: 40px"&gt;
&lt;p&gt;&lt;strong&gt;Developer (you)&lt;/strong&gt;: &lt;em&gt;Here&amp;rsquo;s an initial idea of what we thought should be included on the home page&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Client1&lt;/strong&gt;: Oooh &amp;ndash; what shade of green is that? I don&amp;rsquo;t like that green background at all. Who said we were going with green?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: &lt;em&gt;We don&amp;rsquo;t have to go with green. Keep in mind, this is just a sample. The important thing is to focus on the elements in general at this point.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Client2&lt;/strong&gt;: Our old site had small, boring-looking buttons. I like that you&amp;rsquo;re using image buttons, but those are still much too small.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: &lt;em&gt;Bigger image buttons. Got it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Client2&lt;/strong&gt;: Can we see what a larger image button would look like there at the bottom?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: &lt;em&gt;Well, not right this minute. We don&amp;rsquo;t have any larger images prepared, but I&amp;rsquo;ll make a note of that for the next meeting.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Client1&lt;/strong&gt;: What color are the image buttons going to be? They can&amp;rsquo;t be red, especially with that green background.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: &lt;em&gt;As I said before, the colors aren&amp;rsquo;t really that important for the time being. We&amp;rsquo;re just trying to get an idea of&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Client3&lt;/strong&gt;: Speaking for myself, I&amp;rsquo;d say this is right on the mark. Looks pretty much finished to me. Maybe a couple of small tweaks here and there. Do you think we can go live with this by the end of the week?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: &lt;em&gt;No no no, this isn&amp;rsquo;t even&lt;/em&gt; close &lt;em&gt;to being done. I know it may&lt;/em&gt; look &lt;em&gt;complete, but&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Client1&lt;/strong&gt;: Sorry. I&amp;rsquo;m trying to focus here, but I just can&amp;rsquo;t get past that green background. Can we tone it down a bit? Maybe a drab olive would be nice.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Sound familiar?&lt;/p&gt;
&lt;p&gt;As far as you&amp;rsquo;re concerned, the UI is just another piece of the software construction puzzle. But oftentimes, &lt;strong&gt;to the people who are signing the checks, &lt;em&gt;the UI is the software&lt;/em&gt;.&lt;/strong&gt; It is the piece of that puzzle they have the firmest grasp on, and thus is the aspect of the project over which they will want to exercise the most control. And because so much of the client&amp;rsquo;s focus is on the UI, a finished-looking front-end can easily give the impression that your mockup has actual code behind it, and is &amp;ldquo;practically done.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The beauty of Balsamiq Mockups is that it&amp;rsquo;s a &amp;ldquo;wireframing&amp;rdquo; tool that &lt;em&gt;intentionally uses hand-drawn UI elements&lt;/em&gt;. It&amp;rsquo;s quick-and-dirty, rough, and definitely lo-fi, and with good reason.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/wiki_2.gif"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="wiki" border="0" alt="wiki" width="400" height="317" src="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/wiki_thumb.gif" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/bmeeting_2.gif"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="bmeeting" border="0" alt="bmeeting" width="400" height="293" src="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/bmeeting_thumb.gif" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/iPhoneExamples_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="iPhoneExamples" border="0" alt="iPhoneExamples" width="400" height="238" src="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/iPhoneExamples_thumb.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;These mockups make it abundantly clear at which point you are in the development process.&lt;/strong&gt; Nobody gets too hung up on pretty (or not so pretty) colors, shapes, or sizes, which &lt;strong&gt;lets stakeholders focus on &lt;em&gt;functionality&lt;/em&gt; rather than looks&lt;/strong&gt;. And the first-draft, &amp;ldquo;we just threw this together quickly&amp;rdquo; vibe encourages feedback &amp;ndash; people will feel freer to offer criticism at this point, where they might be more reluctant to do so with something that looks like someone slaved over it for days. What&amp;rsquo;s more, &lt;em&gt;you haven&amp;rsquo;t written a single line of code&lt;/em&gt;, or &lt;em&gt;wasted a single minute of developer productivity &lt;/em&gt;creating fancy prototypes that will eventually find themselves consigned to the dustbin.&lt;/p&gt;
&lt;p&gt;On many past projects, I&amp;rsquo;ve tried to create the same effect with pencil and paper. Unfortunately, I happen to be so artistically challenged that drawing even straight lines is tough for me, which means I end up going through a lot more erasers than pencils. Using Balsamiq &lt;em&gt;feels&lt;/em&gt; like drawing. Balsamiq is just as &lt;em&gt;fast&lt;/em&gt; as drawing (for me, it&amp;rsquo;s actually much faster). But since it&amp;rsquo;s &lt;em&gt;digital&lt;/em&gt;, you can tweak, rearrange, and erase to your heart&amp;rsquo;s content.&lt;/p&gt;
&lt;p&gt;While Balsamiq Mockups is a great tool for getting a lot of ideas down on &amp;ldquo;paper&amp;rdquo; quickly and cheaply, it really shines as a collaborative tool. Because the program is so responsive and simple to use, you can work on designs &lt;em&gt;right in front of the client in real time&lt;/em&gt;. Can you make that button bigger? Done. Move that column? Done. How would the menu look on the left side instead of the top? There you go. It&amp;rsquo;s child&amp;rsquo;s-play-easy to iterate over a design in the course of a meeting, where PMs, designers, developers &amp;ndash; and yes, even clients &amp;ndash; can all throw in their two cents. Mockups can be exported as PNG images and shared or emailed, or coupled with online file-sharing tools for remote collaboration scenarios.&lt;/p&gt;
&lt;p&gt;Besides the 75 ready-to-use controls that come with the application&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/tour_controls_2.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="tour_controls" border="0" alt="tour_controls" width="400" height="212" src="http://leedumond.com/files/media/image/WindowsLiveWriter/BalsamiqItsNotJustForSaladAnymore_8113/tour_controls_thumb.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;you can create and add your own images &amp;ndash; everything from custom controls specific to your project, to image-based backgrounds, entire layouts, and even screenshots of existing applications.&lt;/p&gt;
&lt;h3&gt;A Nit Or Two&lt;/h3&gt;
&lt;p&gt;You may be asking &amp;ldquo;can I export mockups to HTML, MXML, XAML, Ruby, etc.?&amp;rdquo; The answer is no&amp;hellip; and yes. The program doesn&amp;rsquo;t offer native export capabilities to any other format than PNG. However, it cleverly leverages an open, well-documented file format (a variant of XML they&amp;rsquo;ve dubbed BMML) that lets third-parties (or even &lt;em&gt;you&lt;/em&gt;, if you&amp;rsquo;re feeling froggy) provide such features. One such example is &lt;a target="_blank" href="http://www.napkee.com/"&gt;Napkee&lt;/a&gt;, which lets you turn your wireframes into fully-functioning HTML/CSS or Adobe Flex prototypes. Obviously, these third parties have employees who like to eat and have become accustomed to sleeping indoors, so these extensions will cost you a bit of extra scratch if you need them.&lt;/p&gt;
&lt;p&gt;For the time being at least, users cannot add elements directly to the UI library, although the image import feature will suffice in most cases. Balsamiq includes a &amp;ldquo;sketch-ize&amp;rdquo; command that can wireframe imported images, imparting on them the same look and feel as the rest of the application.&lt;/p&gt;
&lt;p&gt;Also, there&amp;rsquo;s no &amp;ldquo;Mockups Viewer&amp;rdquo; application which would allow the sharing of sets of linked prototypes with stakeholders who don&amp;rsquo;t have Mockups installed. This does inhibit collaboration to some degree; though once Balsamiq get the Mockups web version up and running, this should become a non-issue. No pricing for the web version has yet been announced, though I&amp;rsquo;ve heard rumors that peg it in the $12-or-so per month range (again, just rumors &amp;ndash; please don&amp;rsquo;t hold them to it just because I said so).&lt;/p&gt;
&lt;p&gt;One more thing &amp;ndash; as you might have been able to tell from the screenshots above, Balsamiq makes heavy use of the Comic Sans font on Windows and Linux (Mercifully, Mac users get the Chalkboard font on OSX). I probably don&amp;rsquo;t have to tell you how much some people &lt;a target="_blank" href="http://bancomicsans.com/home.html"&gt;hate Comic Sans&lt;/a&gt;. Fortunately, the desktop version lets you swap out Comic Sans MS for any font on your system. If you do this, you&amp;rsquo;ll want to check out some &lt;a target="_blank" href="http://www.hongkiat.com/blog/40-free-high-quality-hand-drawn-fonts/"&gt;hand-drawn alternatives&lt;/a&gt;, as not to lose Balsamiq&amp;rsquo;s low-fidelity GUI goodness.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re still reading this, I have to ask: &lt;em&gt;why&lt;/em&gt;? Check out the &lt;a target="_blank" href="http://www.youtube.com/watch?v=zLysy3IPfFI"&gt;quick 3 minute introduction video&lt;/a&gt;, try the &lt;a target="_blank" href="http://www.balsamiq.com/demos/mockups/Mockups.html"&gt;interactive Flash demo&lt;/a&gt;, &lt;a target="_blank" href="http://www.balsamiq.com/products/mockups/desktop#download"&gt;download and install the demo version&lt;/a&gt;, or dispense with the formalities and just &lt;a target="_blank" href="http://www.balsamiq.com/products/mockups/desktop#buy"&gt;buy the damn thing for only $79&lt;/a&gt; &amp;ndash; that&amp;rsquo;s coffee money compared to what we spend on other tools that aren&amp;rsquo;t nearly as useful as this one. And while you&amp;rsquo;re at it, check out &lt;a target="_blank" href="http://mockupstogo.net/"&gt;MockupsToGo&lt;/a&gt;, a user-contributed collection of UI components from which you can download additional controls or share those you&amp;rsquo;ve created.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t review or endorse very many tools on this blog, but &lt;strong&gt;Balsamiq Mockups has become a must-have application in my development process, and one I feel confident in recommending. It&amp;rsquo;s a fantastic product from a great little company, that addresses a significant issue that almost all development and design teams have, and solves it beautifully.&lt;/strong&gt; When it comes to developer tools, you can&amp;rsquo;t ask for much more than that.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:Dh-6e3sOTMo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=Dh-6e3sOTMo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=6sr8pzzX-3o:UKDViC1CzpU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=6sr8pzzX-3o:UKDViC1CzpU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?i=6sr8pzzX-3o:UKDViC1CzpU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:l6gmwiTKsz0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=l6gmwiTKsz0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/leedumond?a=6sr8pzzX-3o:UKDViC1CzpU:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/leedumond?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/leedumond/~4/6sr8pzzX-3o" height="1" width="1"/&gt;</description></item></channel></rss>
