Last time, we presented partial and total methods, and their respective pros and cons. Today we discuss their benefits in practical situations.
Public and Private APIs
Public APIs, which are — by definition — exposed to anybody, cannot make any assumptions on its user and context of use. They should thus sanitize the input values, for the user could ignore (purposely or not) any precondition.
For example, think about the Java API. If you read its documentation you’ll notice that most of its methods are total. Even
null values will usually be handled or lead to a
NullPointException, although their use is commonly discouraged.
On the contrary, private APIs are typically built for an intended use and for specific clients (e.g. other developers from your company, or even yourself). Given the more controlled context, one may rely on partial methods whenever it is more convenient (often to avoid implementing and testing irrelevant cases).
Abstract data types are typical providers of partial methods. These are meant to discard all situations that could lead the ADT to an inconsistent state. In this case, surrounding services (e.g. application services) must act as a façade and prevent illicit calls to the methods of the ADT.
Partial methods can support more efficient implementations by making additional assumptions on the inputs. Consider, for example, the following specification:
/** * @requires values != null && values is sorted in ascending order * @return the number of occurrences of x in values, i.e., the number * of times x appears in values. */ int occurrencesOf(int x, int values)
In the above, a precondition states that the list of integers must be sorted in ascending order. Thanks to this assumption, we can stop counting the number of occurrences of x as soon as we find a value greater than x. Without that, the implementation would have to iterate over the complete array, which is less efficient on average.
We’re pretty sure that you can think of cases in your projects where well-thought preconditions can simplify the implementations and/or make them more efficient. Of course, the burden of meeting the preconditions is moved onto the caller of the method, which should have practical means of ensuring their satisfaction. In our example, one would expect that the methods modifying the array guarantee it to be sorted in ascending order.
How do you specify public APIs in your team? What kind of policy do you have to handle input sanitization and exceptional conditions?