I’ve observed this phenomenon quite a few times in different API usability studies and thought it would be worth discussing.
It’s not uncommon for an API to offer multiple ways of accomplishing the same task. For example, the following two lines of code show two different ways of creating a StreamWriter that will append text to a file if it already exists:
System.IO.StreamWriter sw1 = new System.IO.StreamWriter("c:\file.txt", true);
System.IO.StreamWriter sw2 = System.IO.File.AppendText("c:\file.txt");
Quite often, the user isn’t always aware of the choices that are available to them. For example, they might choose the constructor approach because it suits the way that they work. Opportunistic programmers for example almost always create instances of objects in code when exploring what that object can do. Or they might choose the static AppendText approach since it reads better (boolean parameters aren’t very role expressive). But in this particular example, whatever choice they make won’t really affect the user experience they have. In both cases, the user ends up with a StreamWriter.
However, in some cases the impact of choosing to accomplish a task one way as opposed to another can be quite large. For example, I posted a couple of days ago about a problem I was grappling with. If I had chosen one approach, I believe that my application would have become more difficult to maintain as I would be introducing a dependency on the definition of data templates I used in my app. In contrast, the way I ended up solving the problem has fewer dependencies and is likely to be easier to maintain.
Unfortunately it wasn’t obvious to me at the time that I faced such a choice. I just wasn’t aware of the different ways that I could accomplish this task, let alone the pros and cons of each. I almost ended up prematurely committing to one approach without even knowing it.
We have a natural tendency to latch on to the first possible solution we find to a problem we have. We like the feeling of accomplishment we get when we solve a problem so we work hard towards a solution and the associated rush we feel. Sometimes this works well, but when there are multiple possible solutions, this approach can cut ourselves off from considering each solution.
Bill Buxton talks about this in his book ‘Sketching User Experiences‘. He talks about the differences between the design process and the engineering process. A design process considers many different designs and the tradeoffs between each, ending up with the ‘right’ design. The engineering process takes a design and figures out how best to implement it – how to get the design ‘right’. He discusses how software engineering projects often consider the design and engineering phase or process as one and the same. As a result, little time is spent considering alternative designs. Typically what happens is the first design is the one that gets built, without much consideration about whether or not that is the right design.
It’s a similar phenomenon but on a smaller scale with APIs that have multiple ways of accomplishing the same task. As developers perhaps we need to rethink how we work so that we do a better job of considering all of the alternatives. But changing our behaviour isn’t easy. It might be easier to work with APIs that just make it more obvious that there are choices to be made and that help you make the right choice. Brad Abrams blogged about ways to help developers to fall into the ‘pit of success‘. At a local level, we can use good attractive names for example to orient developers towards the ‘best’ approach.
On a larger scale though, when the choice is between different approaches, technologies or patterns I’m not sure that there is a simple way to make it clear to developers which approach is right or best. Maybe there isn’t even a best approach at this scale? I would be very reluctant to suggest that the APIs should offer fewer patterns for example. The whole point of APIs and frameworks is that they are flexible and can be used to solve many different programming tasks. Reducing the number of alternatives could significantly reduce the flexibility of the API. For example, now that MVVM is becoming more and more mainstream, does that mean we should remove the code-behind model? I don’t think so.
There is obviously a role for documentation. I think though that the way that we search for help and documentation could be significantly improved. In my own experience observing developers work, when developers latch onto a particular solution that uses a particular technology or pattern, they refine any subsequent documentation search that they do such that it is related to the chosen pattern or technology. This makes complete sense since it reduces the number of irrelevant results. But the outcome is that they now almost have no chance of being exposed to other solutions. Their searches have gone from being task based (how do I write a line of text to a text file) to technology based (how to I use the StreamWriter constuctor). If there was some documentation search engine that could build up a task context from the sequence of searches that a user has performed, , perhaps that could be used to automatically suggest other alternative techniques.
For example, imagine I do a search for ‘accessing a silverlight or wpf templated control’. From the search results I might find something that discusses how to use the method FindName to access a named templated control. My next search might be ‘equivalent of findname in silverlight’ since FindName doesn’t exist in Silverlight. If the search engine assumed that the context of this second search is still the task specific search I did to begin with, perhaps there might be more of an opportunity to offer up better alternative designs, rather than focus more and more on the first solution.
Anyway, these are just some random thoughts I had this morning. If anyone is so inclined, I’d love to hear your thoughts about this.