The Usability of Code, Part 1 of 2
October 12th, 2007 | by Bill Kayser |Not long ago Ken Arnold wrote an article for Queue magazine called Programmers are People Too. In it he talks about applying the principles of User Interface Design to the design of APIs. It turns out the practices of Human Factors and Usability Engineering have a lot to offer the implementors of public APIs and frameworks. Think of an API as the “user interface” of a larger programming model. Users are application programmers and the usability of the API is judged not just by it’s richness, but on the ease of use and learnability of the API. It’s not sufficient to address usability with thorough documentation any more than it’s sufficient to compensate for a bewilderingly difficult user interface to a mobile phone with a five pound user manual.
The idea of applying Human Factors to API design is not far off the idea of designing programs as works of literature. In both cases your main focus is your audience, not the computer. The common principle in both is readability, but the idea of API usability takes it a little further because your audience isn’t just trying to understand what it’s looking at but actually use and extend the work.
I believe these principles of usability apply not just to API design, but to programs in general. Ken Arnold gives a couple of examples of UI principles applied to API design, such as the use of Progressive Disclosure. That’s the principle that says you shouldn’t overwhelm a user with more detail than they need for a common task, but rather disclose the additional detail when the need arises as they move further along in some interaction. Give the user what they need to know when they need it and only when they need it. That way they won’t be distracted or confused by superfluous information.
For an API, this might mean segregating the methods of a complicated class into the methods most commonly used by client applications from the less frequently used methods needed in special situations or by advanced users. For an application designer it might mean using interfaces and abstract classes to hide the distracting implementation details of a class.
Think about other common principles for user interface design, such those described in the Apple Human Interface Guidelines. How can these be applied to program design? I’ll list some more examples in the next installment of this column.
Tags: api design, usability
By Manas Fuloria on Oct 14, 2007
Bill, I’m really enjoying this.
Just FYI, since we worked together I’ve become a convert to the importance of usability. Everything we do as engineers is to enhance human experience - our own or that of others. (Even if you are designing a bridge - you don’t want your users to get wet, right?!) It takes a lot of introspection and self-criticism to make human factors truly influence your design, but the results can be delightful.
By Vaibhav on Oct 15, 2007
At a smaller level, this thinking would apply to class design as well. How to design an interface to a class? What are the best practices?
In terms of an API, the most common question that I face is whether there should be fewer API methods which do a lot of things depending on the control information provided in the parameters? Or there should be many methods, with each one doing exactly one thing.
Conventional wisdom suggests the latter, however, I somehow have had trouble digesting that. I keep thinking there needs to be a middle path somehow, but where to strike that balance is something that eludes me.
Any help?
By Bill Kayser on Oct 15, 2007
I guess I fall into the camp of conventional wisdom. If I identify a method with control parameters to distinguish different ‘modes’ I try to split them into distinct methods, but only if I can create distinct meaningful names for them. If I can’t come up with a new name that isn’t just the original name plus some qualifier like “…WithoutValidation” then I’ll go for the new method. I also allow for common idioms for control flags like “createIfAbsent”, but for the most part I don’t think the benefit of collapsing distinct methods into parameterized forms justify the loss of clarity. After all, you could implement many API’s with a single method by inserting an enum parameter for “operation”. I think most times methods are combined with an operation parameter as a convenience to the author, not the user.
Still, you could make a case that it complicates an API to have so many different methods. You could even view it as a tradeoff of API usability versus code readability. I just think combining methods just masks the complexity without really eliminating it.
If you end up with a lot of methods, think about progressive disclosure. Is there a way to surface the most commonly used methods and classes while making the less common methods accessible, but less apparent? I haven’t had a chance to put that idea into practice but I’m keeping an eye out.
By Vaibhav on Oct 15, 2007
Okay… now that I actually followed that link and read a little bit more about Progressive Disclosure, it sounds like exactly that middle path that I am seeking.
Oh, I didn’t use the term ‘conventional wisdom’ in any bad sense. I was trying to point out that most advice from experts points that path to follow. That is the ‘right’ answer. Hardly anyone explains the true thought behind it. (Much like the real reasons for using Hungarian Notations).
I normally hate to just follow rules unless I understand the value they bring. And although I dislike the very widespread practice of people coding too many things inside a function (mostly stuff which is not reflected by the name of the function); I am also uncomfortable designing APIs which are loaded with various method calls.
Yes! Progressive Disclosure sounds interesting, although the right pattern for implementing such a system still probably needs to be discovered.
By Deepak Nohwal on Oct 17, 2007
I would also be interested in seeing if there is a pattern available for implementing a system using Progressive Disclosure technique. Has anyone defined such a pattern so far?
By Amit Jain on Dec 16, 2007
Deepak,
I can think of defining different interfaces and the class implementing those interfaces. A ‘user’ would see just those APIs which are defined in the interface, the one he is using to access the class.
This is one way to make API’s simple and easy to use. But this is definitely not ‘Progressive’ disclosure.
For that, we can design a class with very basic methods plus a method like ‘GetAdvanceControl()’ which would return an object with advance stuff.