<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4909529313564310898</id><updated>2012-02-16T05:04:11.802-08:00</updated><category term='mobile'/><category term='domain model'/><category term='dialog'/><category term='interview'/><category term='tools'/><category term='java'/><category term='message'/><category term='workflow'/><category term='ipod'/><category term='object oriented'/><category term='user interface'/><category term='design'/><category term='performance'/><category term='error'/><category term='usability'/><category term='gui'/><category term='types'/><title type='text'>Order In The Software Universe</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-3280636203506544225</id><published>2009-06-09T20:11:00.000-07:00</published><updated>2009-06-09T20:48:06.868-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='interview'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='object oriented'/><title type='text'>Interviewing</title><content type='html'>&lt;span style="font-family: arial;"&gt;Yep, its another blog/article on interviewing. I just searched on google for "interview programming" and got 21.8M hits. So what's so bad about one more? :)&lt;br /&gt;&lt;br /&gt;I wanted to have a few words about interviewing for mid-level and senior developers. I do this for my company as one of my many functions (including software architect and lead developer). The reason I feel compelled to write is disappointment. I just cannot reconcile how good some resumes look and how poor the results are off the paper.&lt;br /&gt;&lt;br /&gt;When I interview, I &lt;span style="font-weight: bold;"&gt;*never* *ever*&lt;/span&gt; go the puzzle/trick route. I think those have very little to do with our jobs at best and give misleading results at worst. To me, you should focus where the big cost items are in software - in its (lack of) structure and in its (lack of) flexibility. Does the code smell?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;It is how easily the software can be changed over time that determines its real cost.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So when I interview, I first establish that they have good grasp of object orient design fundamentals. Then I focus on the key area of "best practices." Does the candidate understand when they are creating a mess? Do they recognize conceptual pollution when they see it?&lt;br /&gt;&lt;br /&gt;To ascertain this, I give them a take home (java) "test." I want them to not feel a great deal of time pressure (when was the last time your boss dropped a programming task in your lap and said it needed to be done in 20 minutes?). I give them overnight to complete the test, but in reality it should only take them 20 minutes.&lt;br /&gt;&lt;br /&gt;The actual test is short. It's a two page code sample for them to critique. I tell them that their boss is interested in hiring the developer of that code and boss wants their feedback. The test shows the following kinds of problems:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;embedding strings directly in code&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;mixing of abstractions&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;blocks of code commented out (with no other explanation as to why it was commented out)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;the use of public virtual functions called in a constructor (a questionable practice)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;complete lack of comments&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;errors in relationships (coder assumed 1:1 when its really 1:N)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;missing abstractions (over use of string data)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;over-reliance on open-ended integers (instead of enums)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family: arial;"&gt;In all, there are about a dozen issues that could be flagged. I have had several candidates tell me that everything looked good to them. My average score is probably 5 issues. I tend to get interested in a candidate if they score 7 or more. The best I have seen was from a really, really good developer who did it sight-unseen in about 10 minutes and got 14 issues (I give credit if they raise and can defend most technical concerns).&lt;br /&gt;&lt;br /&gt;I don't consider this tricky questioning. It basically boils down to me having developers that don't keep me awake at night wondering what messes they are making. I feel that a competent developer ought to be able to get most of this almost by instinct.&lt;br /&gt;&lt;br /&gt;So why do 90% of the candidates not make the bar?&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-3280636203506544225?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/3280636203506544225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=3280636203506544225' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/3280636203506544225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/3280636203506544225'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2009/06/interviewing.html' title='Interviewing'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-2803243480594126244</id><published>2009-04-08T20:01:00.000-07:00</published><updated>2009-04-08T20:26:06.609-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='error'/><category scheme='http://www.blogger.com/atom/ns#' term='user interface'/><category scheme='http://www.blogger.com/atom/ns#' term='dialog'/><title type='text'>Third Life, Fourth Life, ...</title><content type='html'>I was in a discussion today with a colleague of mine (I'll call him Jim). He was asking my opinion of an important message he put at the end of his application installer. I suggested some minor tweaks, which he appreciated. But I also asked him to emphasize things, possibly by an alert or by an extra dedicated panel (most installers are wizards). His comment was that doing so would only aid maybe 10% more of the users.&lt;br /&gt;&lt;br /&gt;What sad but true observation.&lt;br /&gt;&lt;br /&gt;I was taken back about a year earlier when I remember standing at the back of a training class watching one of our sales engineers using a product I designed. He was working his way through a guided work flow. When an error message came up (you know, the one with the big red X on it), he couldn't click it away fast enough. Breaking with best practices, I interrupted him asking him what the error message was and he didn't know.&lt;br /&gt;&lt;br /&gt;This was truly an eye-opener for me. To him, an interrupting dialog/alert was a nuisance to be disposed of as quickly as possible. It was impeding his work flow. I try to put a lot of effort into the information content of error messages to be as helpful as possible to the end user. Was all that effort wasted? I liken careful error handling to putting guard rails on a winding mountainous road.&lt;br /&gt;&lt;br /&gt;Back to my conversation with Jim.&lt;br /&gt;&lt;br /&gt;We were discussing possible changes to user interfaces. I remarked that maybe with virtual reality becoming commonplace, we could actually be more effective in informing users of the severity of problems. Maybe a future application would have a user traveling down a path, say a winding mountain path. When a severe error occurs, rather than a dialog, we could actually push them off a virtual cliff. At least the experience would be hard to dismiss and might even be memorable.&lt;br /&gt;&lt;br /&gt;Maybe instead of giving the user the Ok/Cancel button of today, such a future application might present a button with the label "Respawn?"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-2803243480594126244?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/2803243480594126244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=2803243480594126244' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/2803243480594126244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/2803243480594126244'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2009/04/third-life-fourth-life.html' title='Third Life, Fourth Life, ...'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-7510808062992820509</id><published>2009-01-15T18:22:00.000-08:00</published><updated>2009-01-15T19:03:25.022-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='domain model'/><category scheme='http://www.blogger.com/atom/ns#' term='types'/><title type='text'>Primitive Types and the Domain Model</title><content type='html'>I was at the No Fluff Just Stuff conference this year (5th year in a row for me), listening to Neal Ford talk about development concepts. He made a casual remark that caught and held my attention far after he had moved on to other topics. He said&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                Never use primitive types in your domain model&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As you veteran developers know, the core of many well-built applications is a clear, concise domain model. This forms the basis for key abstractions and is the framework around which you typically hang your business logic. Most of my experience over the years has been with developing large, complex desktop applications where a good domain model is key. I assume that for medium-to-large enterprise web applications, a good domain model is also highly valued.&lt;br /&gt;&lt;br /&gt;So what exactly does the quote above mean? I'll give you some examples. The first is from one of our early domain models where we represented network topology elements (computers, routers, etc). One of the data members of our network representation was bandwidth, as in set-the-bandwidth-of-this-network-to-X. We assumed that the number was megabits per second. Of course, we wrote some independent utility scaling routines to go to kilobits per second and gigabits per second.&lt;br /&gt;&lt;br /&gt;Do you see the inferior design? Of course, we should never have used a primitive type (like double) to represent bandwidth. What we should have done was create a Bandwidth class and passed this to the "set" and "get" routines. This class would have had the concept of units (possibly a class like BitRate) and would have encapsulated all the conversion routines in one nice package. Maybe you would find lines of code like&lt;br /&gt;&lt;br /&gt;     double capacity = bw.inMegabitsPerSec();&lt;br /&gt;&lt;br /&gt;And importantly constructed like this&lt;br /&gt;&lt;br /&gt;     Bandwidth bw = new Bandwidth (3.5, MegabitsPerSec);&lt;br /&gt;&lt;br /&gt;That is so much easier to read and is far clearer than&lt;br /&gt;&lt;br /&gt;     double bw = 3.5;&lt;br /&gt;&lt;br /&gt;A second example comes from some code that I trapsed across not a month ago. We have a switchboard-like, sockets-based server that handles communications between applications within a given suite. In sending a message through this switchboard to another application, you identify the target application by a name. The application names and versions that form a suite come from a configuration file. We allow aliases/monikers for the applications as well as trying not to be case sensitive. Part of this is convenience, and part of it is because the applications are written in diverse technologies (C++, Perl, Java, C#).&lt;br /&gt;&lt;br /&gt;I was looking at this code for the first time, and I saw a lot of string manipulation going on. There was trimming (of spaces), folding of cases, and substring matching -&lt;span style="font-weight: bold;"&gt;a lot of it.&lt;/span&gt; In tracing through the code, a string that was already lower case, was set to lower case again. Clearly somewhere along the line, the programmer (or programmers) lost track of the flow of the data in the application, where messages were entering the system. The string hacking was so prolific that it made the code harder to read.&lt;br /&gt;&lt;br /&gt;So what was missing here? Instead of using a string primitive type, how about a class called ApplicationName. It would encapsulate all the concepts of case insensitivity and of aliases. I even found code later on that emitted information to logs and to the end user, so it could even encapsulate the concept of "pretty name" (a standard, human-consumable name).&lt;br /&gt;&lt;br /&gt;I know what a few of you are thinking. You are concerned about the performance cost of allocating all those instances. With modern optimizing compilers, you'll find that performance costs won't really be an issue. The cost that will eat your lunch is the maintenance cost for the software over time.&lt;br /&gt;&lt;br /&gt;So the next time you are working in your domain model, and you feel the urge to use an int, double, string, or other primitive type, think again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-7510808062992820509?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/7510808062992820509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=7510808062992820509' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/7510808062992820509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/7510808062992820509'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2009/01/primitive-types-and-domain-model.html' title='Primitive Types and the Domain Model'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-405233419868277102</id><published>2008-10-04T07:38:00.001-07:00</published><updated>2008-10-04T08:01:32.332-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='usability'/><category scheme='http://www.blogger.com/atom/ns#' term='user interface'/><title type='text'>Usability of London's Tube Map</title><content type='html'>A colleague of mine just got back from London, where use of "the tubes" (subway) is highly encouraged. As a newbie to the system, she relied heavily on the tube map to get around.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_xlyyXEioAEg/SOeBIEKVHRI/AAAAAAAAAAY/PRxBssutEK0/s1600-h/london-tube-map.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_xlyyXEioAEg/SOeBIEKVHRI/AAAAAAAAAAY/PRxBssutEK0/s320/london-tube-map.jpg" alt="" id="BLOGGER_PHOTO_ID_5253309465906978066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;She had good things to say about this map (it's aesthetically pleasing, it's easy to use). But her biggest complaint was that she could not tell that a certain destination was going to be twice as far as the last one.&lt;br /&gt;&lt;br /&gt;Not being one to take a challenge lying down, I thought about it. The map crams a lot of information into a fairly small space (the image above is reduced a lot). It is fairly information rich. What could be added to that map that would still preserve its aesthetics and simplicity?&lt;br /&gt;&lt;br /&gt;How about we give up our preconception that every map has only one scale? (A scale is a ratio of say map miles to real inches of map distance.) What if a map had multiple scales? What if it had a variable scale? Could we present a solution that would service both users who want to get real distances and those who want relative?&lt;br /&gt;&lt;br /&gt;Here is what I came up with. Suppose that we put tick marks on the tracks. Each tick mark would represent a distance (say 2 km). This would be true for the whole map. This would allow users to quickly eyeball a source and a destination and either visually compare or actually count the distance. Notice that the actual map inches for each tick is variable. Check out a small section that I blew up and modified.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_xlyyXEioAEg/SOeFGyOUGQI/AAAAAAAAAAg/pYDnBM0VVxA/s1600-h/london-tube-map-blowup.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_xlyyXEioAEg/SOeFGyOUGQI/AAAAAAAAAAg/pYDnBM0VVxA/s400/london-tube-map-blowup.png" alt="" id="BLOGGER_PHOTO_ID_5253313841958492418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I think the idea is ready for usability testing!   ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-405233419868277102?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/405233419868277102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=405233419868277102' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/405233419868277102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/405233419868277102'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2008/10/usability-of-londons-tube-map.html' title='Usability of London&apos;s Tube Map'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_xlyyXEioAEg/SOeBIEKVHRI/AAAAAAAAAAY/PRxBssutEK0/s72-c/london-tube-map.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-3858363344235347776</id><published>2008-08-15T19:21:00.000-07:00</published><updated>2008-08-15T19:25:46.885-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='usability'/><category scheme='http://www.blogger.com/atom/ns#' term='gui'/><category scheme='http://www.blogger.com/atom/ns#' term='workflow'/><title type='text'>The Problem with Thinking Additively</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;How does your company decide how to improve your products? If yours is like most, you have product managers who survey selected customers, soliciting feedback on improvements. Between their suggestions and your development staff, you come up with a list of new features for that next development cycle.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Maybe this works for your company, but it is a flawed process. By focusing on your existing product and thinking additively, you effectively warp your process into being tool-centric. The Next Great Release is only a few new features away. Developers think this way, product managers think this way, and existing customers think this way (potential customers may not).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;So what exactly is wrong with this picture? Everyone is focused on the tool. It is a distraction from what is important, namely solving the user's problem. If you could really see how your tool is used by end users, you might notice that there is a lot of interaction between the user, the tool, and other things. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I'll call this workflow. It is the sequence of steps that the user is following in going from nothing to solution. It might involve using your tool multiple times in different ways. It might involve generating intermediate workproducts. It might involve interacting with others at certain points. Ultimately, it might be all this activity around your tool that determines its success, rat more than its feature set.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Workflow may not be prominent in all problem domains, but the more complex the domain, the more likely that workflow is significant. Consider my company's domain for example. We provide tools to allow technical people to work with network and server data, to build a models of their system, and to predict the behavior of the system under various loads. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Recipes&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;One day one of our consultants passed by and proudly flopped a meaty document on my desk and informed me that he had finally codified a methodology to solve one of our users' most common modeling problems. It was a masterpiece at 90 pages, was well organized, was valuable to our users, and made an impressive sound hitting my desk.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;In a later meeting, while developers and product managers argued about getting SAN support into our tools, I was still thinking about that sound. If the problem domain was that complex, surely we should be selling guidance to our users, right? And we couldn't ship a consultant in every box, could we? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;In a sense, the methodology was a recipe, and arguably was as valuable as the tool. If we could productize it, users would see real value in a productivity boost. The analogy to a cooking recipe is apt. It has ingredients (preconditions), a step by step description of what to do (a process), and a view of the expected result. Users might choose different recipes, depending on what they are trying to do. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;One of the most valuable things a recipe can do is to establish context. By knowing context, any support you give the user can be made more relevant. Maybe your user has filtered a network traffic report and it is empty. Is that an error condition? Maybe. Is there sage advice to offer them - only if you know what they are trying to do. If you build tools without context, in a way, you can only offer abstract options and abstract advice. It becomes much harder to embed domain knowledge in your tool.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Steps&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Steps are the building blocks of recipes. Our product is composed of more than one application, and some steps control these other applications, launching them with the appropriate inputs and outputs when appropriate. Some kinds of steps generate workproducts. Some steps encompass critique of data or state, sometimes encompassing expert advice. Some steps allow declaration of data (like a list of server names). A lot of steps have fixed or parameterized functionality, but one type of step is very highly customizable in terms of both its behavior and its designable user interface.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Flow and Dependency&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;There is a concept of information flow involved in recipes. Since recipes have multiple steps and steps might have inputs and outputs, there is a flow among the steps. The inputs and outputs of each step are typed and the flow matches up by type. This brings up one of the strengths of this approach, namely the managing of dependencies. If a user makes a change farther up in the recipe, all downstream steps that share that flow are now out-of-date, meaning that the steps need to be executed again to bring their outputs up-to-date. As long as this out-of-date state is visible to users, it is a simple matter of making sure that required changes propagate correctly.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Tracability&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;In our problem domain, users are making business decisions on modeling results, involving potentially millions of dollars. Confidence in the results is paramount, requiring an understanding of how those results were arrived at. If the results are unexpected, they need to work backwards in the flow to figure out where their expectations diverge from the results. Users might work backwards examining not only intermediate workproducts, but also look at assumptions along the way.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Consider this requirement in the context of a loop. Whether in a conventional programming language or a flow chart, a loop has a conditional, a loop body, and a loop terminator. There are undesirable characteristics of this representation. First, it assumes that the logic associated with the loop body is the same for each pass through the loop. When you consider that each pass might represent the analysis of a different set of data, and that the user might want to tweak each pass, the flow chart style logic is not flexible enough. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;A way to represent this is to unroll the loop. That is, represent the loop body explicitly for each iteration of the loop. It takes more space to do this certainly, but it meets the traceability requirement and allows the user to modify each pass independently. There is also a dynamic reconfiguration aspect here. Maybe the loop is a pass for each test case in the collected data. So if the user adds a test case, a new series of steps might dynamically come into existence representing the new pass through the loop.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;A final benefit in explicitly representing all steps required in a recipe, is that the user has a roadmap that tells them how far they need to go. They can tell how far they have come by a "done flag" that each step displays.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Business Politics&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;An easily overlooked issue with introducing workflow into your products involves business politics. You might have to champion a fairly sizable change to how you are going to spend your development dollars. If introducing workflow competes for the same resources that would be used to develop new features, you might meet resistance.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;In my company, I started the sales pitch at the customer advisory council level. Being composed entirely of our biggest customers, the council readily bought into the concept. This should be expected, as users are the ones who ultimately pay the price for lack of workflow support through lost productivity. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Next up was an internal presentation that included developers, consultants, and product managers. The development staff was positive towards the idea. The product managers were uncertain about this; the workflow solution came out of some creative thinking in development, which is backwards from what they expected. The really interesting responses came from the consulting staff, who are effectively very advanced users. Most were favorable to the idea, but consultants have a history of being mavericks. As subject matter experts, each might have their own way of solving problems.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;One consultant stood up in this meeting and gave the most negative response, saying something like "Tell me why I would ever use something like this. Why would we build this application?" I'm happy to say that the same consultant caught me in the hall about a year after the product was released and told me, "I don't know how I got along without this!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I'd like to close this with an admission. To this day, I never have read every page of that original methodology. Just don't tell that consultant.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-3858363344235347776?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/3858363344235347776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=3858363344235347776' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/3858363344235347776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/3858363344235347776'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2008/08/problem-with-thinking-additively.html' title='The Problem with Thinking Additively'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-2729081781159900572</id><published>2008-08-07T18:45:00.000-07:00</published><updated>2008-08-07T18:48:10.108-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='usability'/><category scheme='http://www.blogger.com/atom/ns#' term='gui'/><category scheme='http://www.blogger.com/atom/ns#' term='ipod'/><title type='text'>The Touch</title><content type='html'>&lt;span style="font-family: trebuchet ms;"&gt;On another topic, I picked up an Apple iPod Touch, the one with the big touch screen and a cousin to the iPhone. Man, that is a nice piece of engineering. The user interface is very interesting. I have not really used touch devices before, but I can see that user interfaces will not translate to mobile touch devices very well at all.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;Consider these…&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;Screen real estate is at a premium. The balance between being efficient and being rich without being cluttered is very narrow, and they have done a good job at the user interface. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;One of the fun user interfaces involves scrolling through lists (think of artist/album lists). As a user, you think of pressing your finger on the list and flicking it in a direction. This sends the list rolling in the direction your finger directed. The fun thing is that the faster you flick, the faster the list scrolls. And the list has friction! Its velocity decays over time. And if you hit the end of the list, it kind of compresses a bit then rebounds, kind of like its made of rubber. I’m ashamed to admit that even after having the Touch a week, I still sometimes play around with flick-scrolling.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;One thing that I ran into was the lack of tool tips. With a mouse-based interface, you can linger over items to get a hint to pop up as to the  function of the widget. But with touch screens, there is no lingering. You press on a button with a finger. That’s it. I missed the ability to browse the functionality that tool tips provide. A possible compromise might be to have a tool tip pop up while the press down occurs. A user might move off a widget without releasing, hence restoring the viewing of tool tips without activating the widget. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;Another slight surprise was how much your finger actually obscures. Apple did a good job of averaging a hotspot to represent the center point of your finger, so I rarely missed items, even as a newbie user. But your finger tip is quite large. When you click say on a small keyboard, or a small control, its nice to know what you hit. This happens with several forms of feedback. If you hit a lone control and pick your finger up, you often see the control glow for a couple of seconds, indicating that is was hit. This is a “nice touch” (sorry, I couldn’t resist). When clicking on a virtual keyboard, when you click the letter, a larger representation of that letter jumps up above your finger while it is pressed, allowing visual confirmation of your choice.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;One of the really glitzy user interface features is controlling zooming. The Touch uses the Safari web browser. When you navigate to a page, you see the whole page (usually as you’d see it rendered on your computer screen) only shrunk down to fit the mobile screen. This makes actually using this sized page dubious. Most users will zoom in and then move around by dragging the screen with their finger tip. The zooming is what’s interesting. If you want to blow up a screen, you put two fingers on the screen and spread them out. The screen zooms bigger in real time in proportion to how much you spread your fingers. Zooming back out is the opposite; use two fingers and squeeze them together. Very, very slick. The obvious usability defect I ran into was that the zooming factor was not preserved when jumping to a new page. This means you keep having to zoom in every time you follow a link.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;The Touch also has real orientation sensor. (Please pardon my printer jargon to follow.) If you are viewing a web page in portrait mode, and you rotate the Touch to landscape mode, the screen will reorient itself so you are no longer looking at it sideways! That one is a real crowd pleaser. Some applications take advantage of this; for example, the drawing programs allow you to erase a screen by shaking the Touch. Ah, that takes me back to the old Etch-a-sketch days. I ran into an interesting usability issue with this feature. I took the Touch to the gym, where I primarily listen to music (you know, to keep the old forty-something body going). The Touch would not deactivate the screen (to save power) because I was doing sit-ups, causing the screen to switch between portrait and landscape mode with each grunt of effort. Thankfully once it went into screen deactivate, no amount of sit-ups would reactivate the screen (there is a separate gesture to wake it up).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;I guess the moral of the story is that even a multi-billion dollar company that thrives on slick user interfaces makes usability mistakes. The second moral of the story is that touch-based interfaces are a new challenge to those of us who create mouse-based applications. The final moral of the story is to go out and get an iPod Touch – now.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-2729081781159900572?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/2729081781159900572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=2729081781159900572' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/2729081781159900572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/2729081781159900572'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2008/08/touch.html' title='The Touch'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-6892804581354990947</id><published>2008-08-01T17:48:00.000-07:00</published><updated>2008-08-01T17:49:42.079-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='gui'/><title type='text'>What About User Interface Performance?</title><content type='html'>&lt;span style="font-family: trebuchet ms;"&gt;What process do you use in determining product requirements for an upcoming release? It probably goes something like the product manager collaborates with the sales department to write up an MRS (marketing requirements document), the product manager writes up a PRD (product requirements document), and then development takes that input and generates an SRS (software requirements document). The MRS describes the required enhancements in terms of features, benefits, and their expected impact on sales. The PRD should describe new and changed features that support the improved vision. The SRS should specify enough detail that a developer can implement changes to support the PRD.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;This pipeline can work well. But it is not perfect. As a pipeline, it is only as good as the information that is feeding it. In particular, missing information often results in software which may not meet the originally envisioned requirements. (Anyone who has had a brush with dealing with an outsourced team can appreciate this in spades.) One often neglected area concerns performance, particularly in user interfaces. Those who are developing web applications are less likely to suffer from this lack than those who are working on desktop client applications. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;What might performance specification look like? This can take the form of a maximum time for a certain action, a minimum throughput specification (events per second), or a specification of expected volumes. These are typically lacking in most projects, or are injected very late in the development cycle, where the workable responses available to the development team are going to be limited. If you are unlucky, there are no performance requirements, and this lack causes you to choose an architecture that does not scale well. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;To avoid this, you should try whenever possible to specify performance requirements in your SRS. It is unlikely that you’ll be able to find hard numbers in terms of time constraints. This is partly due to the cost of determining these (think of the time and expense of canvassing your customer base), but also human tolerance of delay is vague. If a dialog takes 500 milliseconds to come up, versus 200 milliseconds, is anyone really going to complain? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;One easy specification to include should be the average and expected maximum sizes of things. Image your user interface includes a dialog that shows a list of items. The average and maximum length of that list should be specified; even a guess is better than nothing, but take care to get several considered opinions. In a product that I worked on, when I asked our subject matter expert what an average and maximum value for our list would be, I was told 7 and 12 (these were big abstract things in the list). Knowing that, we never saw any problematic performance during development. We knew that the implementation was probably n^2, but were unconcerned. Our QA stress test case was 30 items. Image our chagrin when handling a customer call where said customer had 600 items in their list. Trust me when I say that you do not want customers going in your product where your QA team has not.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;Another easy specification is concerns response time and cancelling long operations. First, make sure that you never do real work in your event dispatch thread; this is the main thread that runs your user interface. Doing real work there means that your application becomes unresponsive. So your SRS should specify places that progress indicators should be used (a wait cursor, a status bar message, or a full blown progress dialog). This has the implication that at least one extra thread should be doing the real work in the background. If your user interface operation is expected to take more than a certain amount of time (say a handful of seconds), you should specify that it be cancellable by the user.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: trebuchet ms;"&gt;These sound like common sense, and for many practitioners they are. But in the press to get product out the door, try hard to avoid performance concerns from getting pushed back into the next release.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-6892804581354990947?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/6892804581354990947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=6892804581354990947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/6892804581354990947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/6892804581354990947'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2008/08/what-about-user-interface-performance.html' title='What About User Interface Performance?'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-3308224116641651936</id><published>2008-07-29T17:46:00.000-07:00</published><updated>2008-07-29T17:50:26.409-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='usability'/><category scheme='http://www.blogger.com/atom/ns#' term='error'/><category scheme='http://www.blogger.com/atom/ns#' term='message'/><title type='text'>The Forgotten User Interface</title><content type='html'>&lt;span style="font-family: trebuchet ms;"&gt;Today, I’m going to ramble on about a critical, but often overlooked user interface. This user interface is present in almost all programs. It receives very little design effort. It is usually implemented in a casual manner, almost as an afterthought. Yet it is highly visible to end users and can have a big influence over users’ perception of product quality.&lt;/span&gt;&lt;p style="font-family: trebuchet ms;"&gt;&lt;/p&gt;&lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;At this point in the riddle, you hear “what am I?” Yep, you guessed it – error messages. (This diatribe can be applied to warnings and informational messages too)&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;Error messages are a legitimate and primary facet to a user interface. We as product designers conceive of a products to solve a problem or perform a service to users. We strive to make our product feel intuitive and natural. We always end up asking our users to assume a manner of interaction with our program. But no matter how well we do, we designers never get a perfect score, for we do not live in the user’s world. &lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;Expectations that our users have of our product may not be met, and the reasons may be numerous. Maybe we weren’t as good at conceptualizing as we thought. Maybe what we wanted to build was too expensive in effort or time. Maybe someone in the decision chain is deciding things they ought to delegate. Whatever the reason, when the user deviates enough from the Chosen Path, an error message is likely to ensue.&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;The primary down side of error messages is that they interrupt the flow of work that the user is orchestrating. The user’s momentum is broken and they are reminded that the product they are working with cannot read their mind, and that it may not fit very well into their problem space. The user’s focus moves from the getting real work done to focusing on the error. This often results in annoyance or even anxiety.&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;To help convey the user’s anxiety level to developers, I describe an informal Angst Temperature Scale. In this scale, the lowest, cooler end represents a user’s lack of anxiety when they are moving along smoothly through your product. If any warning message shows up, the scale goes to pale yellow. If any error message shows up, the scale shows intense yellow. If the user sees a sloppy, unhelpful, or confusing error, the scale temperature is orange. The first intrusion into red occurs when a product has a silent error, which often is accompanied by puzzling application behavior. The anxiety scale tops out at a sizzling red when a product has a crash, usually accompanied by loss of data.&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;So what is going on in a user’s head when they see an error message? The answer is captured in two simple questions: “&lt;i&gt;what just happened to me&lt;/i&gt;” and “&lt;i&gt;what can be done about this by me&lt;/i&gt;.” I like to call this &lt;i&gt;Me-centricity&lt;/i&gt;. It is a concept that developers either fail to recognize or under-appreciate. After all, developers historically write the error messages for self-consumption, right? So how do we correct this sorry state?&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;Recognize that error messages play to many consumers. Each has its own needs, own expectations, and own world view. These players are developers, technical writers, technical support, training, and everyone else! (You’ve got to love the irony in this taxonomy.) Each needs something different from an error message.&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;Before we get much farther into how to correct things, let me digress into some real-world, commercial examples of message (with a commentary in parenthesis):&lt;/p&gt;  &lt;ul style="margin-top: 0in; font-family: trebuchet ms;" type="disc"&gt;&lt;li class="MsoNormal" style=""&gt;&lt;b&gt;&lt;span style=""&gt;Changes are not saved!&lt;/span&gt;&lt;/b&gt;&lt;span style=""&gt; &lt;i&gt;(It would be really      nice to know why)&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;b&gt;&lt;span style=""&gt;You changes have been saved!&lt;/span&gt;&lt;/b&gt;&lt;span style=""&gt; &lt;i&gt;(A misspelling and      why put this message up at all?)&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;b&gt;&lt;span style=""&gt;Your project name has been saved!&lt;/span&gt;&lt;/b&gt;&lt;span style=""&gt; &lt;i&gt;(Hmmm, I wonder what      happened to the rest of the project?)&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;b&gt;&lt;span style=""&gt;16 &gt;= 16&lt;/span&gt;&lt;/b&gt;&lt;span style=""&gt; &lt;i&gt;(I’m not making this up – this is a real error      message)&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;b&gt;&lt;span style=""&gt;Confirm to cancel, continue?&lt;/span&gt;&lt;/b&gt;&lt;span style=""&gt; &lt;i&gt;(This is my all time      favorite)&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;That last one is a real winner. I think it really is a diabolical way to paralyze your user into a permanent state of indecision.&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;So let’s take a look at critiquing this error message from an application called Navigator. This message is so typical of what a developer might produce without careful consideration.&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-left: 0.5in; font-family: trebuchet ms;"&gt;&lt;b&gt;&lt;span style="line-height: 115%;font-size:12;" &gt;&lt;span style="font-size:100%;"&gt;The following Navigator file had an unexpected version: myproject.npj&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;This error message is marginal at best. It raises more questions than it answers. A user might be asking these questions:&lt;/p&gt;  &lt;ul style="margin-top: 0in; font-family: trebuchet ms;" type="disc"&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;What does a file represent in Navigator?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;What was the found version? Expected version?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Why would I hit this problem?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;How do I get past this problem?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;A totally cool, enlightened developer might produce instead the following error message. Note that the underlined items represent hyperlinks to more information for the user.&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 0in 1in 10pt 49.5pt; font-family: trebuchet ms;"&gt;&lt;b&gt;The Navigator &lt;u&gt;project&lt;/u&gt; below cannot be opened because it is incompatible with the current version of Navigator.&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 0in 1in 10pt 49.5pt; font-family: trebuchet ms;"&gt;&lt;b&gt;          Myproject.npj&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 0in 1in 10pt 49.5pt; font-family: trebuchet ms;"&gt;&lt;b&gt;Details – the project was created by Navigator 2.4 (with project version 1.1) while the current version of Navigator is 3.0 (with project version 1.2). A list of Navigator releases and corresponding project versions can be found &lt;u&gt;here&lt;/u&gt;. &lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 0in 1in 10pt 49.5pt; font-family: trebuchet ms;"&gt;&lt;b&gt;If you need more information, contact technical support at &lt;u&gt;&lt;a href="mailto:support@hyperformix.com"&gt;support@hyperformix.com&lt;/a&gt;&lt;/u&gt; or send this file as an &lt;u&gt;attachment.&lt;/u&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;This version of the error message is far superior to the original by almost any measure you choose, except the effort to create it. But what rules do we follow in creating better error messages?&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;Let me introduce you to the &lt;b&gt;Jedi Master’s Guide to Error Messages&lt;/b&gt;. This is mostly a common sense set of rules to follow:&lt;/p&gt;  &lt;ul style="margin-top: 0in; font-family: trebuchet ms;" type="disc"&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Watch out for typos – it looks really sloppy. You don’t      want your user thinking that they were the first ones to ever see this      message on display.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Use clear language. There is nothing worse than a      confusing error message. Well, I guess there are worse things, but not      many.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Avoid slang.  Nuff said.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Do not mix languages.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Do not introduce new concepts. Do not refer to concepts      in your messages that are not supported in the user interface.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Do not introduce new terminology. This one is      frequently violated. Use the same terminology that is used in your user      interface. This needs to be consistent with help too. There is nothing      worse than multiple names for the same thing.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;All messages must have a unique identifier. This helps      users quickly look up an explanation in the help.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Easy access to support information. This might take the      form of hyperlinks.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Support “sendability”. Screen dumps can work after a      fashion, but it’d be more convenient if users can copy the text of an      error message as text and forward it in email.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Let users drill down to details. In other words, the      first part of the error message should be clear and simple. It is targeted      at the end user. Let more sophisticated users read more or actually expand      more detail if they actually need to.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;So what is actually impeding the creation of more usable error messages? There are two things to consider. The first is a lack of technical support. The second is a development process issue. On the technical side of things:&lt;/p&gt;  &lt;ul style="margin-top: 0in; font-family: trebuchet ms;" type="disc"&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;Developers typically use simple functions to show      simple strings.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;The use of property files (a common technique for      handling internationalization issues) favors simple string messages.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;There is very little if any support for hyperlinks in error      messages. Some of this could be addressed by moving to a richer      expression, such as HTML.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style=""&gt;There is no email support. So users are rarely      presented with options like directly contacting technical support.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;On the process side of things, there usually is none. That is, there is rarely anything in the development process to support better usability of messages. Often the other stakeholders (other developers, technical support, training, etc.) do not even review the messages or do so in an ad hoc fashion.&lt;/p&gt;  &lt;p style="font-family: trebuchet ms;" class="MsoNormal"&gt;I’d like to close with one final thought. When was the last time you saw a usability study that focused on error messages?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-3308224116641651936?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/3308224116641651936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=3308224116641651936' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/3308224116641651936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/3308224116641651936'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2008/07/forgotten-user-interface.html' title='The Forgotten User Interface'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4909529313564310898.post-7395438019460800959</id><published>2008-07-28T19:56:00.001-07:00</published><updated>2008-07-28T20:03:16.680-07:00</updated><title type='text'>Welcome</title><content type='html'>Oh, no! Not another software blogger! Why does the blogosphere need yet-another-software-guru-wannabe?&lt;br /&gt;&lt;br /&gt;Actually it doesn't - I need one. This is my therapy for living in software development. Besides letting me vent, this will hopefully show things from unconventional angles. If you are not in software development yourself, you will likely get little from this blog. If you are a developer or a manager, help yourself to seconds.&lt;br /&gt;&lt;br /&gt;I have been in the software business as a developer for over 20 years now, so I have my share of bumps, bruises, and most importantly, scars. From the mid to late nineties, I ran the C++ Tips website, which can still be found &lt;a href="http://cpptips.com"&gt;here&lt;/a&gt;. That site is mostly archival in purpose, but one of these days, I'll write some Perl and clean it up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4909529313564310898-7395438019460800959?l=orderlysw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://orderlysw.blogspot.com/feeds/7395438019460800959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4909529313564310898&amp;postID=7395438019460800959' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/7395438019460800959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4909529313564310898/posts/default/7395438019460800959'/><link rel='alternate' type='text/html' href='http://orderlysw.blogspot.com/2008/07/welcome.html' title='Welcome'/><author><name>OrderlySW</name><uri>http://www.blogger.com/profile/00197306552133619758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_xlyyXEioAEg/SI6I6muWATI/AAAAAAAAAAM/p6nArMV2agM/s1600-R/allan2000.jpg'/></author><thr:total>0</thr:total></entry></feed>
