←Older revision |
Revision as of 20:12, 19 March 2011 |
Line 1: |
Line 1: |
- | Rules for extending [[ProviderAPI|API designed for implementors]] are very different to those for [[ClientAPI|API that can only be called]]. In case you have a provider implementing your interface, the obvious expectation of that person seems to be that the once the implementation is written, (potentially) compiled once, it will continue to work forever. | + | Rules for extending [[ProviderAPI|API designed for implementors]] are very different to those for [[ClientAPI|API that can only be called]]. |
| | | |
- | One can visualize such [[ProviderAPI|provider interface]] as a ''fixed point''. As a point which stays the same, does not grow (adding a new method to implement would put additional, unsatisfiable requirements on existing implementors). If the ''fixed point'' changes, then only minimaly. It can shrink - e.g. in future version the [[API]] infrastructure may decide to not call some of the methods ''so often''. Or it can start receiving different arguments (instead of array of size 1024 bytes, one may obtain calls with 4096 bytes array). Of course only if the specification was not strict about the order of calls, or size of the parameters...
| + | As soon as an implementation of your interface is written, the natural expectation of its author is, that it will work forever. |
| | | |
- | The easiest way to break this promise is to add new non-implemented methods into the type. As such do not add new methods to ''interface''s or ''abstract classes'' implemented by some [[ProviderAPI|providers]]. This immediately breaks the promise of source [[BackwardCompatibility]].
| + | One can visualize such [[ProviderAPI|provider interface]] as a '''fixed point''' - a piece of the [[API] that does not change at all. Well, it can change a bit. You may decide to call its methods more often in new version, or call them less frequently. You may pass in arrays of size 4096 instead of previously used 1024, etc. Slight modifications of the contract are allowed, but compared to [[ClientAPI]] (where adding methods is [[good]]), the interface for providers is really ''fixed''. No new methods additions (adding a new method would put additional, unsatisfiable requirement on already existing implementors), no refactorings. Stability is [[good]]. |
| | | |
- | [[TBD]]: Fragile methods additions | + | The easiest way to break this promise is to add new non-implemented methods into the type. As such do not add new methods to ''interface''s or ''abstract classes'' implemented by some [[ProviderAPI|providers]]. This immediately breaks the promise of [[BackwardCompatibility]]. |
| | | |
- | [[TBD]]: Interfaces and clear definition of a version | + | The best construct in [[Java]] to implement [[ProviderAPI]]s is to define these types as [[Java]] '''interface'''s. All their methods are abstract (thus they have to be implemented) and it is clear that changing the interface method signatures renders existing implementation uncompilable. |
| + | |
| + | As soon as a modification of the contract with providers is needed, one should add new interface to be implemented. The the interfaces clearly define version which the provider implemented. One can use '''instanceof''' to check whether the provider implemented old or new version and behave appropriatelly: |
| + | |
| + | <source lang="java"> |
| + | /** @since 1.0 */ |
| + | public interface Playback { |
| + | public void play(byte[] arr); |
| + | |
| + | /** @since 2.0 we can also control volume */ |
| + | public interface Volume extends Playback { |
| + | public void setVolume(int volume); |
| + | } |
| + | } |
| + | |
| + | The list of ''additional'' interface that can be implemented is sometimes hard to find. As the previous code snippet shows, it helps if they are nested interface inside the most general (original) one. When the providers write their implementations, they directly see all available ''extensions'' added in newer revisions of the [[API]]. |
| | | |
| [[Category:APIDesignPatterns]] | | [[Category:APIDesignPatterns]] |
| [[Category:APIDesignPatterns:Evolution]] | | [[Category:APIDesignPatterns:Evolution]] |