For each user goal that your API supports, describe how easy it is to tell from reading the code what the code does. List those parts of the API that do not express their role clearly. Additionally, gather feedback from users regarding the code that they would expect to write for a given goal. Compare users expectations with the actual code required.
Note that there are two sides to role expressiveness:
Mean what you say.
Say what you mean.
Code that is easy to read (mean what you say) might not be easy to write (say what you mean). When evaluating role expressiveness don’t focus just on how easily users can read code that uses your API. Make sure you evaluate how well they can write code using your API also.
In the System.IO namespace, one user goal might be to append text to an existing text file. The code to accomplish this goal is as follows:
StreamWriter sw = new StreamWriter(“C:\\test.txt”, true);
This code does not fully express its role. It is not clear what the effect of setting the second parameter to true in the StreamWriter constructor is. Does the parameter mean create the file if it doesn’t exist, append text to the file or delete the contents of the hard drive that the code runs on? A user reading this code would have to look at the documentation to figure out that this code will create a StreamWriter that will append text to the file specified in the first constructor parameter. It’s also not clear whether or not this code will work. Does the file need to be opened before it can be written to, or does the act of creating a new instance of the StreamWriter class also open the associated file so that it can be written to?
Users might also have different ideas about how they would expect to accomplish the same task. They might expect something like the following pseudo-code:
FileObject theFile = new FileObject();
theFile.Path = “C:\\test.txt”;
In this pseudo-code, users indicate that they do not think the act of creating an instance of the type that represents the file should automatically open the file. Instead, they expect an explicit open operation to be required. Note also that users expect to be able to set the path of the file they wish to open, after creating the instance of the file object. This indicates that they would expect to be able to reuse the same instance of a file object to point to different files.
Role expressiveness can be defined in the following terms:
- If the code required to accomplish a user goal can be interpreted correctly and if it matches the user’s expectations, the API is said to be transparent.
- If the code required to accomplish a user goal can be interpreted correctly but does not fully match users expectations, the API is said to be plausible.
- If the code required to accomplish a user goal cannot be interpreted correctly and does not fully match users expectations, the API is said to be opaque.