APISeam
From APIDesign
Do you maintain an API and have you ever received a patch from an external contributor which you considered inappropriate? I did, many times. Also I was many times in a position when I wanted to twist some API in ways that were not really comfortable for the original API maintainer.
What can be result of such clash? Rejection of the patch? Possible, but that probably upsets the submitter and good API maintainer does not want to upset those who are willing to contribute patches. Accepting silly patch? Well, that creates a maintenance nightmare. No API maintainer is wishing to spend time bugfixing, expanding and baby sitting an unwanted code. Looks like loose/loose situation! Is there a better solution?
Code Injection
The solution is to create a code slot. Instead of accepting a an unwanted patch, the API can be extended to execute arbitrary code at given patch set point. Imagine simple API for counting down to zero:
does not exists: codeinjection.CountDown
and its simple implementation:
does not exists: codeinjection.v1
It is obvious to author of the API and almost everyone else that down() means decrement by one. But imagine that there is someone who would like to decrement by two. Such person may provide a patch, but maybe it is complicated, maybe it contains code that the API maintainer does not want to accept. Still, if the maintainer wants to let that submitter shot himself into his own foot, he can open his API by providing code slot interface:
does not exists: codeinjection.slot
and looking up its implementation at the right place:
does not exists: codeinjection.v2
This keeps the API clean of any hacks of subtleties of the foreign code. The API just defines a code slot by use of ServiceLoader.load, which is standard JDK 1.6 interface for doing Component Injection. Either it is present (someone included additional JAR on classpath with registration of implementation of the interface), and in such way the decrement is completely handled by new code, or it is missing and then the behaviour remains the same as in version 1.0.
Code slots provide a nice balance between the need to extend an API with additional functionality and the fear of maintaining such code. Every API can be extended to provide code slots and I see them as a perfect way of providing patches for unwanted behaviour. For example I want to change Felix to cooperating with NetBeans runtime container. Of course I do not want to polute the original Felix code with anything NetBeans specific, but maybe all I need is just a single code slot to hook in. Of course, the API maintainer needs to be ready to support such slot and accept any, even surprising behaviour inside it, so the solution is not completely for free. Still, it is the one that provides the best balance by turning an unacceptable patch into acceptable slot.
<comments/>