Tim Scott's Blog

November 30, 2009

A Question Of Astonishment

Filed under: FluentHtml, Programming — Tim Scott @ 5:26 pm

Steve Michelotti recently found a very subtle bug in MvcContrib.FluentHtml.   It provides us with a rather interesting case of applying the Principle Of Least Astonishment (a.k.a. Rule Of Least Surprise).

It turns out that FluentHtml’s select helper lets the user express his intent vaguely.  Consider whether this test should pass:

public void when_determining_selected_values_select_should_ignore_selected_method_if_any_options_are_marked_selected()
    var list = new List<SelectListItem>
        new SelectListItem { Text = "Acura", Value = "1", Selected = true },
        new SelectListItem { Text = "BMW", Value = "2" },

    var select = new Select("foo.Bar").Selected(2).Options(list);

    var optionNodes select.ToString().ShouldHaveHtmlNode("foo_Bar").ShouldHaveChildNodesCount(2);
    optionNodes[0].ShouldBeSelectedOption(1, "Acura");
    optionNodes[1].ShouldBeUnSelectedOption(2, "BMW");

See what we have done here? We have allowed the user to express which options should be selected in two, possibly contradictory ways. In the call to Options, the user has specified that Acura should be selected. In the call to Selected, she has specified that BMW should be selected. How should we interpret what she really wants?

The first path to consider is to change the API to remove the chance for vaugeness. In most cases this is highly preferable. In this case, however, the cat is already out of the bag so to speak. That is, changing the API in this way would be a big breaking change.  Furthermore, it is deliberate and I believe very useful that the API offers a lot of ways to specify select options.

That leaves us to invoke the Rule Of Least Surprise. When a user specifies vague intent, in the manner that we have described, I can see five reasonable outcomes:

  1. Selected items are only those expressed via Selected
  2. Selected items are only those expressed via Options
  3. Selected items are a union of those expressed via Selected and Options
  4. Selected items are only those expressed via Options or Selected, whichever is called last
  5. Selected items are only those expressed via Options unless none, then those expressed via Selected

I will reject #4 out of hand.  FluentHtml helpers are essentially builders.  And with builders, order should never be important.  #1 and #2 are the next to go.  I cannot think of a better argument for either, and so the choice would be arbitrary.  It’s a rather close call between #3 and #5, but I will choose #5.  Here is the thinking.   If the user has specified selected items within the options themselves, then calling Selected is clearly a mistake on his part and he should expect it to be ignored.  On the other hand, if he did not specify selected items within the options list, then he could reasonably expect the call to Selected to be honored.

Would you make a different choice?

1 Comment »

  1. Hello, Tim!

    First of all, a disclaimer; I haven’t used, nor even seen your FluentHtml library. I arrived here after building my own Fluent Html classes. (Thought I’d see what everyone else was doing!) It appears from the samples I’ve seen in your blog postings that what you’ve built is remarkably similar to my own code.

    Now regarding your question… I agree with your rejections of options 1, 2, and 4. However, it seems to me that one might reasonably want to be able to choose between 3 and 5, depending on the scenario, or maybe even option #6… option 5, with reverse priority.

    How difficult would it be to provide this functionality via an interface? The framework could provide the default implementation of option 5, with the option to override using a different or even custom implementation…

    Just a thought! Personally I would like to have the ability to choose between the different methods to interpret the given unit test.


    Comment by T. Lewis — May 19, 2011 @ 8:35 pm

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: