Final interface
From APIDesign
(→When it works?) |
(→When it works?) |
||
Line 13: | Line 13: | ||
The above problems can be slightly mitigated if one has good runtime support for [[modularity]] and this may be the reason why the [[vendor library]] seems to be very popular in [[OSGi]] world. If the [[RangeDependencies|version range]] used by clients is wider than [[RangeDependencies|version range]] used by implementations proper versioning is possible and the [[OSGi]] container can select the right modules to compose a working system. More about this in the [[proximity]] essay. However it needs to be stated that this works only in [[vendor library|One to Many]] and in [[Semantic versioning|Few to Many]] mode - e.g. when there is a single provider (or few of them) of the [[DOM]] parser and many users of the [[DOM]] parsing API. Then one can use [[OSGi]] [[RangeDependencies]] to make sure the implementation has closer [[proximity]] than users of the [[DOM]] [[API]]. | The above problems can be slightly mitigated if one has good runtime support for [[modularity]] and this may be the reason why the [[vendor library]] seems to be very popular in [[OSGi]] world. If the [[RangeDependencies|version range]] used by clients is wider than [[RangeDependencies|version range]] used by implementations proper versioning is possible and the [[OSGi]] container can select the right modules to compose a working system. More about this in the [[proximity]] essay. However it needs to be stated that this works only in [[vendor library|One to Many]] and in [[Semantic versioning|Few to Many]] mode - e.g. when there is a single provider (or few of them) of the [[DOM]] parser and many users of the [[DOM]] parsing API. Then one can use [[OSGi]] [[RangeDependencies]] to make sure the implementation has closer [[proximity]] than users of the [[DOM]] [[API]]. | ||
- | Once you end up with multiple [[DOM]] parser implementations in your application (like a large and [[modular]] app like [[NetBeans]] did) - e.g. you enter [modular library|Many to Many]] relationship, no close [[proximity]] is going to save you. The only saving point is to adhere to best [[API Design]] practice and separate [[ClientAPI]] from [[ProviderAPI]]s. As such [[I]] am going to include [[final interface]] in [[API Design]] anti patterns although [[I] am sure [[OSGi]] friends will never try to understand the [[ClarityOfTypes|better alternative]]. | + | Once you end up with multiple [[DOM]] parser implementations in your application (like a large and [[modular]] app like [[NetBeans]] did) - e.g. you enter [modular library|Many to Many]] relationship, no close [[proximity]] is going to save you. The only saving point is to adhere to best [[API Design]] practice and separate [[ClientAPI]] from [[ProviderAPI]]s. As such [[I]] am going to include [[final interface]] in [[API Design]] anti patterns although [[I]] am sure [[OSGi]] friends will never try to understand the [[ClarityOfTypes|better alternative]]. |
== Enforcing [[final interface]] During Compilation == | == Enforcing [[final interface]] During Compilation == |
Revision as of 07:53, 4 February 2015
Final interface is a pattern often used in vendor library style API design. It marks a Java interface in an API as final (either in Javadoc or elsewhere TBD) with the evolution plan to expand it incompatibly (from the point of implementers). The hope is that nobody except the implementers will ever implement such interface.
Why it does not work?
DOM2 vs. DOM3 problems are famous. The interfaces in DOM Java API were made Final interface, but as the XML specification was still evolving it soon turned out the original interfaces are not satisfactory. The XML introduced namespaces and the Java DOM API needed to adopt to it. How can one do it with Final interfaces? Well, you break backward compatibility for those who implement the interface - and there were many DOM2 parsers, as at certain point in time it was very popular to write own's XML parser.
If one worked only with the standard XML parser provided by the JDK itself together with the DOM API - everything worked fine. Of course, because of closest possible proximity! When you package your [[API] with (the only) implementation you don't have evolution and versioning problems - the proximity is so intimate, you don't have to think about versioning.
However most of the more complex Java applications were not satisfied with the default Java parser and needed to include different implementation. And hence the problems began - when one had implementation of DOM3 provided as a library, but the DOM2 API provided by the JDK, the linkage problems were endless. JDK's distribution of DOM2 and parsers and applications relying on DOM3 (which contains incompatible interfaces from provider point of view) just created a unsolvable mess.
When it works?
The above problems can be slightly mitigated if one has good runtime support for modularity and this may be the reason why the vendor library seems to be very popular in OSGi world. If the version range used by clients is wider than version range used by implementations proper versioning is possible and the OSGi container can select the right modules to compose a working system. More about this in the proximity essay. However it needs to be stated that this works only in One to Many and in Few to Many mode - e.g. when there is a single provider (or few of them) of the DOM parser and many users of the DOM parsing API. Then one can use OSGi RangeDependencies to make sure the implementation has closer proximity than users of the DOM API.
Once you end up with multiple DOM parser implementations in your application (like a large and modular app like NetBeans did) - e.g. you enter [modular library|Many to Many]] relationship, no close proximity is going to save you. The only saving point is to adhere to best API Design practice and separate ClientAPI from ProviderAPIs. As such I am going to include final interface in API Design anti patterns although I am sure OSGi friends will never try to understand the better alternative.