Liberal and conservative

I was introduced to the principle “Be explicit in what you return, be liberal in what you accept” when I started as a C#-developer about two decades ago. Since, I tried to act accordingly. When developing. When I architect systems. When I design business processes. When I interact with people. In short almost always. In this post I’ll revisit this principle, both in the context programming and business process design.

By the way: a few later I discovered the original quote, which is less explicit in what it expects:

"Be conservative in what you do, be liberal in what you accept from others."
Jon Postel (1981). RFC 793

Not into programming? Skip to the business context.

Programming context

When I joined a team as software developer a regular public method definition would look like:

public List<Album> GetAlbumsOf(IArtist artist)
{
    return repository.FindArtist(artist.Name).Albums;
}

Some years later new colleagues joined and, citing the Aviva coding guidelines they’d write:

public IEnumerable<Album> GetAlbumsOf(Artist artist)
{
    return repository.FindArtist(artist.Name).Albums;
}

Jon Postel’s principle and the Aviva coding guidelines contradict each other at first sight. Do they? Jon Postel’s original “Robustness Principle” doesn’t stipulate the specificity of any returned (or send) information. So whether you should return List<Album> or IEnumerable<Album> is not discussed at all.

The rationale given in coding guideline principle “Return an IEnumerable or ICollection instead of a concrete collection class (AV1130)" is to ensure callers are not able to change an internal collection. While reasonable there are several problems with this approach:

  • You can downcast to the original class again (unless you use AsIEnumerable);
  • Potentially fast operations like Count() are reduced to slower operations as we need to enumerate the complete returned list;
  • The guideline proposes to use ICollection<T>, which gives you the possibility to Add and Remove making this while guidelines mood;
  • Using .NET 4.5 or higher they propose to use IReadOnlyCollection<T>, IReadOnlyList<T> or IReadOnlyDictionary<TKey, TValue>. These implement the IList-interface, but throw an exception when you try to modify the list. This is just bad interface-design by Microsoft in my opinion. A compile-time error has just been reduced to a (possibly) difficult to debug runtime-error.

A second reason (not given in the guidelines) to return a generic type is to be able to change the representation of the returned value, without requiring all callers to update their types. In C# this is easy solvable by using the var-keyword or by defining the variable as a specific interface—remember to be liberal in what you receive?

Moving on to the invocation of a method. Should we “Define parameters as specific as possible (AV1137) or be liberal? Repeating myself, the “Robustness Principle” doesn’t tell you to be explicit, but to be conservative. Therefore, I actually think I was wrong in my approach of trying to be liberal with a generic interface. Be liberal in the “Robustness Principle” refers to not rejecting the parameter because it doesn’t conform to the way you would create it. E.g. don’t reject the IArtist artist- or Artist artist-object because the name-property has white space surrounding the name, or because the gender-property is not set. Interpret and use it liberally by e.g. removing the white space and not using the gender. By the way, don’t forget to read “The Harmful Consequences of the Robustness Principle”.

On the other hand, I think my new colleagues were wrong on their interpretation of the guideline too. Being as specific as possible should, in my opinion, be interpreted as “don’t pass more than required”. Passing an Artist-object passes definitely more information (and maybe even requires more information to be constructed)—only the name is required. Passing in a String or taking “Consider using domain-specific value types rather than primitives (AV1140)" into account and passing a ArtistName-object is more inline with the coding guidelines. As this may require a lot of conversions (moving more work to the callers), one could also opt to use an IArtistName-interface.

So I’d write the following code in .NET 4.5:

// I return the interface here, because a ReadOnlyCollection still exports the
// Add and Remove methods, so it is usable in any place an IList is expected
// potentially throwing exceptions when modifications are tried to be made.
public IReadOnlyList<Album> GetAlbumsOf(ArtistName artist)
{
    return new ImmutableList<Album>.Empty.AddRange(repository.FindArtist(artist).Albums);
}

// In case performance is an issue, and most callees will not convert to a list
public IEnumerable<Album> EnumerableAlbumsOf(ArtistName artist)
{
    return repostory.FindArtist(artist).Albums.AsEnumerable();
}

Business context

As shown in the technical context there are several ways to interpret Jon Postel’s principle and to practice it. With a wide variety of organizations all possibilities are covered.

Suppose we, as a business, provide low-cost, on-site flower decoration services. Depending on our market segment we might respond different to the request to “decorate offices in several states with flowers to improve employee wellness”. Attached are several multi-page documents outlining the company philosophy and culture. In our low-cost business we should reject this request immediately. It misses information, is not specific enough and refers to a lot of unnecessary information. Which states should we deliver in? Which cities? What flowers do the employees like (wellness is perceptive and thus the flowers need to be customized for the employees)? To get an answer to all this questions and read the attached documents, takes too much time to fulfill this request profitable. On the other hand, in the high-end market we might request even more information. Have long conversations with the customer, provide samples, etc. Maybe you even refer the customer to a competitor of yours. Of course in either case the request should be as specific as possible. But in the low-cost segment you’d be conservative in what you accept and reject all request not conforming to your specification. In the high-end segment you’d be liberal in what you accept and have your customer success manager (the interface between the customer and the people decorating) work on the details.

Now, move on to a mortgage provider. A customer requests an overview of his mortgage payments during a specific period. You could just send him an overview of all his mortgage payments—after all the request period is included. This moves the burden of the work from you to the customer. This may make perfect sense for a low-cost mortgage provider. On the other hand, in a high-margin mortgage business you could provide more service. Redirect the request of the customer to the correct department if it was addressed wrong. Have the requested information collected and add some explanation to it. Preferably the response is customized to the customer. Depending on the customer a liberal response with a lot of information is welcomed, or a more conservative approach with only the requested information is enough.

Luckily in this last case we’re often “saved” by the internet. Many customers don’t care to log into “my.company-portal.com” to search for the information they need (normally due to the fact they get the exact information they need at the time they want it—which is now). These portals can be seen as a very liberal response to the customer request.

Conclusion

Jon Postel’s principle can be applied to both a technical and a business context. In a technical context the reason to apply the principle is to provide data hiding and reduce dependencies. The principle is to protect the caller from needing to change in the future when the provider changes. The interface is to the advantage of the caller.

In a business context is to protect the business (the service provider). It is in place to make sure the resources required by the service provider are minimized. That said, the exact interface is influenced by the value discipline of the organization. There is no good or wrong here, but when designing business processes one should take the value discipline into account.