This page collects topics for the API Design Workshop at EclipseCon 2008.
Status: the workshop submission has been accepted for EclipseCon 2008! It will be held on Monday, March 17, from 8:00 a.m. to 12:30 a.m. in Room 203/204 of the convention center.
In this workshop, targeted at Eclipse committers, we will work together on best practices for API design. This workshop will be run in an Open Space format to ensure maximum benefit for the participants. In advance of the workshop, participants will use a wiki page to sign up for the workshop and to coordinate topics they want to discuss or learn about. During the workshop, we will have several breakout discussion sessions about the topics that matter the most to the participants. Discussion notes or results will be posted on the wiki. The workshop organizer will bring a 4-hour slide deck about Java API design just in case. However, I hope that together as a group, we can do better than just listening to one individual.
- Boris Bokowski, IBM Rational, Canada
- Jim des Rivières, IBM Rational, Canada
- Christopher Daniel, Poznan University of Technology, Poland
- Brian Carroll, Serena Software (email@example.com)
- Paul Fullbright, Oracle (firstname.lastname@example.org)
- Pawel Piech, Wind River (email@example.com)
- Benjamin Cabé, Anyware Technologies (firstname.lastname@example.org)
- ... add your name...
- Binary compatibility vs. source compatibility vs. contract compatibility
- API design process best practices
- Exposing the API of an OSGi bundle:
- Import-Package vs. Require-Bundle
- How to use Export-Package with x-internal, x-friends, etc
- Bundle version numbers and package version numbers
- Expressing dependency on execution environments
- API testing
- Guidance on how to approach restructuring a Java library that was not desgined with bundles/plugins in mind to properly expose the APIs for eventual use as a bundle
- Granularity in API design - Guidance on how to organize APIs. At first glance, I would expect to apply traditional OO design criteria and techniques to organize an API, but are there additional considerations for bundles?
- Guidance on designing an API with both flexibility and maintenance (backwards compatibility) in mind
- ... add your own topic ...
Notes from 8:00-10:00 Session (courtesy of Anders Skarby)
- On "How to structure existing code, into an API" and a "API design process".
- Don't want to guide the user in best practices, rather support users to do things and be flexible, than guide for best practices. Allow for good practices, and stupid implementations.
- A good API cannot be constructed from existing code, without making modifications to the existing code base.
- API is an interface between components and also teams, defines interfaces / boundaries for the API working within those limitations everything goes (is allowed).
- APIs will be best if designed as an API from scratch, have a specification in mind. It's easier to design for something when having a cover story available (all questions should be answered.
- Every API designed should at least have one client (user). The more distance between the API and the client, the better.
- Interaction between client and API teams should be incremental. Implement inital draft, document, ship to client - be prepared of any inconvinience reports, get that feedback and go onto another iteration.
- It's okay to change an API until it's published. Once published the API should be freezed (locked down for changes). Since unknown party of clients there's no way of changing the implementaiton and mediate the information about that. If inhouse API this might be an acceptable situation since informaiton CAN be mediated.
- It pays to design upfront, and understand what you will be serving. You want to expand the API over time but not retract any parts of the API.
- If clients starts relying upon implementaiton details instead of API you have a problem since you don't have a way to change the API specification.
- The client can not (may not) assume anothing that's not in the API contract.
- The API dictates a contract of decoupling code.
- Unit tests don't dictate behaviour since the implementation of the test (if written by the specific part of the API) since it's only testing for the behaviour the developer is consious about.
- Unit tests should probably be looked over, or written by, another party so that it is written against the API specificaiton.
- Documenting your API (Javadoc specification) is important, it can rely on a platform convention (not talking about null values, assumes that they are accepted) or being specific (being verbose about whether an argument or return type accepts null).
- Annotations could also be used for using tooling (like findbugs, eg.) to verify that a null-check is implemented in the code using the API.
- Internal packages are used to mediate that the behaviour in these packages are not for users, it's possible to access or do in java code - but PDE suports that it is not desirable. Dictating non-public code in private classes limits the usability of that code in a too strict sense.
- x-internal (statements in MANIFEST.MF) can be used for marking internal classes so that they can be used of other plugins, although they get a warning, marking API without enforcing it in a strict / dictating way.
- The signature of a method sometimes exposes an internal packages class to the API - this is not best practice and should generally be avoided.
- Overloading is sometimes an issue (or becomes an issue) when serving convenience, but over tiem null arguments can lead to new methods bein invoked and unintended behaviour occuring at the client side.
- It's very difficult to protect against overloading and various other functionalities in Java - still it's desirable to guide the user / client as far as possible and guard against the API speicification.
- Eclipse uses binary compatibility between releases, so that any plugin mediating that it relies on version XX or later can run on the API of that version or later. Source compatibility between releases is not always sufficient. Step carefully to ensure binary compatibilty between releases (guidelines on Eclipse WIKI on evolving APIs).
- In terms of process for maintaining version compatability (within the Eclipse platform) an API freeze is enforced from Milestone 6 so that you can enforce stability in the end of a release cycle. Furthermore public classes / exposed API is checked for binary compatibility (internal classes are assumed safe). It's an investment against stability and to provide upwards compatbility. If any API breaks occur, they to into the migration guide.
- When going between major versions of API release, a compatability layer should be present to provide a bridge between older versions and the new version (and keep clients utilitizng older versions of APIs functioning on the new API).
- You can't always clean up APIs by deprecating parts of an API, since a flood of warning / errors would occur at the client side. Keep the users existing code in mind, and for that rather keep the old APIs present and provide new APIs. An example of this is the command extension point vs. action contributions.
- There API and non-API, but sometimes you want to release a partial implementation (or not available in a final implementation) - this is the provisional available code, this is however non-API and the only promise made is that compatability WILL be broken. It's also available to service API work that spans multiple release cycles, to get users (external clients) feedback. Provisinal "APIs" should be placed in internal packages to indicate that changes will occur.
- Versioning indicates API changes in the following way: Changes to major version segment indicates changes that breaks API compability, Changes to minor version segment mediates non-breaking API changes. Changes to micro version segment mediates bug fixes, code changes that don't affect the API from a client point of view etc.