PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/_posts/archived/2008-11-06-usability-vs-discoverability.aspx.markdown

https://gitlab.com/Blueprint-Marketing/haacked.com
Markdown | 167 lines | 140 code | 27 blank | 0 comment | 0 complexity | e293cadd2c3c591c777d48bff99b7ea5 MD5 | raw file
  1. ---
  2. layout: post
  3. title: "A Case Study In Design Tradeoffs: Usability vs Discoverability"
  4. date: 2008-11-06 -0800
  5. comments: true
  6. disqus_identifier: 18549
  7. categories: [asp.net,code,asp.net mvc]
  8. ---
  9. Usability and Discoverability (also referred to as Learnability) are
  10. often confused with one another, but they really are distinct concepts.
  11. In Joel Spolskys wonderful [User Interface Design for
  12. Programmers](http://www.amazon.com/gp/product/1893115941?ie=UTF8&tag=youvebeenhaac-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=1893115941)
  13. (go read it!), Joel provides an metaphor to highlight the difference.
  14. > It takes several weeks to learn how to drive a car. For the first few
  15. > hours behind the wheel, the average teenager will swerve around like
  16. > crazy. They will pitch, weave, lurch, and sway. If the car has a stick
  17. > shift they will stall the engine in the middle of busy intersections
  18. > in a truly terrifying fashion. \
  19. > If you did a usability test of cars, you would be forced to conclude
  20. > that they are simply unusable.
  21. [![Scary
  22. Driver](http://haacked.com/images/haacked_com/WindowsLiveWriter/ACaseStudyInDesignTradeoffsUsabilityvsDi_11DB9/learning-to-drive_thumb.jpg "Scary Driver")](http://haacked.com/images/haacked_com/WindowsLiveWriter/ACaseStudyInDesignTradeoffsUsabilityvsDi_11DB9/learning-to-drive_2.jpg)
  23. > This is a crucial distinction. When you sit somebody down in a typical
  24. > usability test, youre really testing how learnable your interface is,
  25. > not how usable it is. Learnability is important, but its not
  26. > everything. Learnable user interfaces may be extremely cumbersome to
  27. > experienced users. If you make people walk through a fifteen-step
  28. > wizard to print, people will be pleased the first time, less pleased
  29. > the second time, and downright ornery by the fifth time they go
  30. > through your rigamarole.
  31. >
  32. > Sometimes all you care about is learnability: for example, if you
  33. > expect to have only occasional users. An information kiosk at a
  34. > tourist attraction is a good example; almost everybody who uses your
  35. > interface will use it exactly once, so learnability is much more
  36. > important than usability.
  37. Rick Osborne in his post, [Usability vs
  38. Discoverability](http://rickosborne.org/blog/index.php/2007/04/19/usability-vs-discoverability/ "Usability vs Discoverability"),
  39. also covers this distinction, while Scott Berkun points out in his post
  40. on [The Myth of
  41. Discoverability](http://www.scottberkun.com/essays/26-the-myth-of-discoverability/ "The Myth of Discoverability")
  42. that you cant have everything be discoverable.
  43. These are all exmaples of the principle that there is [no such thing as
  44. a perfect
  45. design](http://haacked.com/archive/2005/05/31/ThereIsNoPerfectDesign.aspx "There is no perfect design").
  46. Design *always* consists of trade-offs.
  47. Lets look at an example using a specific feature of ASP.NET Routing
  48. that illustrates this trade-off. One of the things you can do with
  49. routes is specify constraints for the various URL parameters via the
  50. `Constraints` property of the `Route` class.
  51. The type of this property is `RouteValueDictionary` which contains
  52. string keys mapped to `object` values. Note that by having the values of
  53. this dictionary be of type `object`, the value type isnt very
  54. descriptive of what the value should be. This hurts learnability, but
  55. lets dig into why we did it this way.
  56. One of the ways you can specify the value of a constraint is via a
  57. regular expression string like so:
  58. ```csharp
  59. Route route = new Route("{foo}/{bar}", new MyRouteHandler());
  60. route.Constraints =
  61. new RouteValueDictionary {{ "{{" }}"foo", "abc.*"}, {"bar", "\w{4}"}};
  62. RouteTable.Routes.Add(route);
  63. ```
  64. This route specifies that the *foo* segment of the URL must start with
  65. abc and that the *bar* segment must be four characters long. Pretty
  66. dumb, yeah, but its just an example to get the point across.
  67. We figure that in 99.9% of the cases, developers will use regular
  68. expression constraints. However, there are several cases we identified
  69. in which a regular expression string isnt really appropriate, such as
  70. constraining the HTTP Method. We could have hard coded the special case,
  71. which we originally did, but decided to make this extensible because
  72. more cases started cropping up that were difficult to handle. This is
  73. when we introduced the `IRouteConstraint` interface.
  74. At this point, we had a decision to make. We could have changed the the
  75. type of the `Constraints` property to something where the values are of
  76. type `IRouteConstraint `rather than `object` in order to aid
  77. discoverability. Doing this would require that we then implement and
  78. include a `RegexConstraint` along with an `HttpMethodConstraint`.
  79. Thus the above code would look like:
  80. ```csharp
  81. Route route = new Route("{foo}/{bar}", new MyRouteHandler());
  82. route.Constraints =
  83. new RouteConstraintDictionary {{ "{{" }}"foo", new RegexConstraint("abc.*")},
  84. {"bar", new RegexConstraint("\w{4}")}};
  85. RouteTable.Routes.Add(route);
  86. ```
  87. Thats definitely more discoverable, but at the cost of usability in the
  88. general case (note that I didnt even include other properties of a
  89. route you would typically configure). For most users, who stick to
  90. simple regular expression constraints, weve just made the API more
  91. cumbersome to use.
  92. It wouldve been really cool if we could monkey patch an implicit
  93. conversion from `string` to `RegexConstraint` as that would have made
  94. this much more usable. Unfortunately, thats not an option.
  95. So we made the call to favor usability in this one case at the expense
  96. of discoverability, and added the bit of hidden magic that if the value
  97. of an item in the constraints dictionary is a string, we treat it as a
  98. regular expression. But if the value is an instance of a type that
  99. implements `IRouteConstraint`, wed call the `Match` method on it.
  100. Its not quite as discoverable the first time, but after you do it once,
  101. youll never forget it and its much easier to use every other time you
  102. use it.
  103. ### Making Routing with MVC More Usable
  104. Keep in mind that Routing is a separate feature from ASP.NET MVC. So
  105. what Ive covered applies specifically to Routing.
  106. When we looked at how Routing was used in MVC, we realized we had room
  107. for improving the usability. Pretty much every time you define a route,
  108. the route handler youll use is `MvcRouteHandler` it was odd to require
  109. users to always specify that for every route. Not only that, but once
  110. you got used to routing, youd like a shorthand for defining defaults
  111. and constraints without having to go through the full [collection
  112. initializer
  113. syntax](http://haacked.com/archive/2008/01/06/collection-initializers.aspx "Collection Initializers")
  114. for `RouteValueDictionary`.
  115. This is when we created the set of `MapRoute` extension methods specific
  116. to ASP.NET MVC to provide a façade for defining routes. Note that if you
  117. prefer the more explicit approach, we did not remove the
  118. `RouteCollection`s `Add` method. We merely layered on the `MapRoute`
  119. extensions to `RouteCollection` to make defining routes simpler. Again,
  120. a trade-off in that the arguments to the `MapRoute` methods are not as
  121. discoverable as using the explicit approach, but they are usable once
  122. you understand how they work.
  123. ### Addressing Criticisms
  124. We spent a lot of time thinking about these design decisions and
  125. trade-offs, but it goes without saying that it will [invite
  126. criticisms](http://ayende.com/Blog/archive/2008/11/05/a-case-study-of-bad-api-design-asp.net-mvc-routing.aspx "Bad API").
  127. Fortunately, part of my job description is to have a thick skin. ;)
  128. In part, by favoring usability in this case, weve added a bit of
  129. friction for those who are just starting out with ASP.NET MVC, just like
  130. in Joels example of the teenager learning to drive. However, after
  131. multiple uses, it becomes second nature, which to me signifies that it
  132. is usable. Rather than a flaw in our API, I see this more as a
  133. deficiency in our documentation and Intellisense support, but were
  134. working on that. This is an intentional trade-off we made based on
  135. feedback from people building multiple applications.
  136. But I understand it wont please everyone. What would be interesting for
  137. me to hear is whether these usability enhancements work. After you
  138. struggle to define constraints the first time, was it a breeze the next
  139. time and the time after that, especially when compared to the
  140. alternative?