API design: concrete vs. abstract approach – best practices

apiapi-designweb services

When discussing APIs between systems (on the business level) there are often two different point of views in our team: some people prefer a more – lets say – generic abstract approach, other a straight forward "concrete" approach.

Example: the design of a simple "person search" API. the concrete version would be

 searchPerson(String name, boolean soundEx,
              String firstName, boolean soundEx,
              String dateOfBirth)

People in favour of the concrete version say:

  • the API is self-documenting
  • it is easy to understand
  • it is easy to validate (compiler or as a webservice: schema validation)
  • KISS

The other group of people in our team would say "That is just a list of search criteria"

searchPerson(List<SearchCriteria> criteria)

with

SearchCritera {
  String parameter,
  String value,
  Map<String, String> options
}

with possibly making "parameter" of some enumeration type.

Proponents say:

  • without changing the (declaration of) the API the implementation can change, e.g. adding more criteria or more options. Even without synchronizing such a change at deployment time.
  • documentation is necessary even with the concrete variant
  • schema validation is overrated, often you have to validate further, schema cannot handle all cases
  • we already have a similiar API with another system – reuse

The counter-argument is

  • lots of documentation about valid parameters and valid parameter combinations
  • more communication effort because it's more difficult to understand for other teams

Are there any best practices? Literature?

Best Answer

It depends on how many fields you're talking about, and how they are used. Concrete is preferable for highly structured queries with only a few fields, but if the querying tends to be very free form, then the concrete approach quickly becomes unwieldy with more than three or four fields.

On the other hand, it's very difficult to keep a generic API pure. If you do a simple name search in a lot of places, eventually someone is going to tire of repeating the same five lines of code, and they're going to wrap it in a function. Such an API invariably evolves into a hybrid of a generic query together with concrete wrappers for the most commonly used queries. And I don't see anything wrong with that. It gives you the best of both worlds.