A Class (or Caste) System for APIs
Application Programming Interfaces (APIs) should be designed with their specific audience in mind. Some APIs are meant to be used by low-level developers for creation of infrastructure code; other APIs are to be used by high-level developers in the creation of user interface or workflow code. Most APIs rely on the ambient language to provide strong typing and 'link' themselves to the function signatures.
MyFooFunc(string, int, int, DateTime, bool)
I divide interfaces into three classes and I've started using these terms when I present on architecture and design: 1st Class, 2nd Class and 3rd Class Interfaces. In naming these interfaces 1st through 3rd I do not aim to make a qualitative value judgment, only to correctly describe the level of fidelity the interface provides. Sometimes when a API is created as a front-end to some large mysterious 'blackbox' and that box is to be used in a language or platform agnostic way, the blackbox defines a syntax of its own. For example, SQL Server is a large black box whose vast power can be exploited via a single method: Execute(string). The real power lies in what "string" contains, in this case, T-SQL. Regardless of what language you choose to call Execute(), a lot of work (read: magic) will happen as a result of the SQL.
For Example: In COM, when someone writes Dim x as new Foo, someone calls CoCreateInstance(foo), a 3rd class API, someone has to call LoadLibrary(foofilename.dll), also a 3rd class API. This is an example of layering lower classes of APIs to present a 1st class API to the higher level developer.
Command.Execute("INSERT INTO employee (emp_no, fname, lname, officeno) VALUES (3022, 'John', 'Smith', 2101)")
Employees.Insert(3002, "John", "Smith", 2101);
3rd Class Interfaces are usually limited to a core infrastructure functions or ".Executes" that are like procedure calls within a string. Notable examples include Database APIs that expose an Execute method that takes a string of T-SQL as a parameter. It is within that T-SQL command that the programmers intention is expressed.
Overwhelmingly, 1st and 2nd Class APIs are built on top of 3rd Class Interfaces. 2nd Class Interfaces often hang off of a larger controller object or domain object. There is also some use of Domain Objects, primarily as complex-type or "rich" parameters to the Controller.
1st Class Interfaces are typically found in object oriented or command/message oriented designs. These are meant to describe the programmers intent using business objects that fall into a specific business domain. Objects representing high level logical constructs act upon other objects.
Question of the day:
When creating APIs, particularly for use by developers in business verticals who wire up complex processes, what is the right balance between type-rich function signatures (n parameters) and type-rich internal messages (n simple types within a complex type)?
This whole rant will get me into another rant coming in a few days on "The Myth of .NET Purity"...