Eclipse-Plattform
Verwendungsregeln für API
Version 0.15 - Last revised 12:00 May 30, 2001
Hier finden Sie alle Verwendungsregeln zu den Clients der API der
Eclipse-Plattform (und anderen Komponenten).
Bedeutung einer API
Die Eclipse-Plattform definiert API-Elemente, die durch ihre Clients
verwendet werden, vor allem durch unabhängige Softwarehersteller,
die Plug-ins schreiben. Diese Plug-ins können wiederum API-Elemente für ihre eigenen Clients
definieren usw. API-Elemente kommunizieren auf gewisse Weise mit dem Benutzer: sie
geben an, welche Aufgaben sie übernehmen und wie sie eingesetzt
werden sollen. API-Elemente werden unterstützt: Das Eclipse-Plattformteam korrigiert
Programmfehler einer Implementierung, wenn eine Abweichung vom
angegebenen erhalten festgestellt wird. Da umfangreiche API-Änderungen häufig erhebliche Kosten nach sich
ziehen, versucht das Eclipse-Plattformteam außerdem, API-Elemente
über erfolgreiche Haupt-Releases problemlos weiterzuentwickeln.
Kommunikation zwischen API-Elementen und anderen Elementen
API-Elemente sind ihrem Charakter nach so angelegt, dass sie
dokumentiert werden und über eine Spezifikation verfügen. Sie bilden
hierdurch einen Gegensatz zu anderen, nicht für eine API gedachten
Elementen, bei denen es sich um interne Implementierungsdetails
handelt, für die in der Regel weder Dokumentation noch
Spezifikationen publiziert werden. Wenn Sie also nicht in der Lage sind, die Dokumentation für ein
bestimmtes Element aufzufinden, ist dies normalerweise ein Hinweis
darauf, dass es sich nicht um eine API handelt.
Um die Trennung zwischen diesen beiden Elementtypen noch
deutlicher zu ziehen, ist die Codebasis für die Plattform in API- und
Nicht-API-Pakete unterteilt, und alle API-Elemente werden in
designierten API-Pakete deklariert.
-
API-Paket: Ein Java-Paket, das mindestens 1 API-Klasse oder
API-Schnittstelle enthält. Die Namen der API-Pakete sind in der Dokumentation der entsprechenden
Komponente angegeben, wenn möglich, ist im Namen anderer Pakete, die
nur Implementierungsdetails enthalten, "internal" angegeben. Die Namen von API-Paketen werden ganz normal im Client-Code angezeigt. Bei der Eclipse-Plattform selbst sind dies die folgenden Pakete:
-
org.eclipse.foo.* (z. B. org.eclipse.swt.widgets,
org.eclipse.ui oder
org.eclipse.core.runtime
-
org.eclipse.foo.internal.*: Keine API-Pakete, sondern
interne Implementierungspakete
-
org.eclipse.foo.examples.*: Keine API-Pakete, sondern
Beispiele
-
org.eclipse.foo.tests.*: Keine API-Pakete, sondern
Programmpakete für Testzwecke
-
API-Klasse oder -Schnittstelle: Eine
öffentliche Klasse oder Schnittstelle (public)
in einem API-Paket bzw. ein Member einer öffentlichen oder
geschützten Klasse oder Schnittstelle
(public oder protected), das in einer anderen
API-Klasse oder -Schnittstelle deklariert oder durch diese übernommen
wird.
Die Namen von API-Klassen und -Schnittstellen können ganz normal im
Client-Code angezeigt werden.
-
API-Methode oder -Konstruktor: Eine öffentliche oder
geschützte Methode (public oder protected) bzw.
ein solcher Konstruktur, die/der entweder in einer API-Klasse oder
Schnittstelle deklariert oder durch diese übernommen wird. Die Namen von API-Methoden können ganz
normal im Client-Code angezeigt werden.
-
API-Feld: Ein öffentliches oder
geschütztes Feld (public oder protected),
das entweder in einer API-Klasse oder Schnittstelle deklariert
oder durch diese übernommen wird. Die Namen von API-Feldern können
ganz normal im Client-Code angezeigt werden.
Alle anderen Elemente werden als interne Implementierungsdetails
betrachtet und sind für keinen Client zugänglich. Ein ordnungsgemäßer Client-Code darf nie auf die Namen von Elementen
verweisen, die keine API-Elemente sind, nicht einmal unter Verwendung
einer Java-Spiegelung. In manchen Fällen werden unzulässige Verweise durch die Regeln für
die Zugriffsmöglichkeit auf Namen verboten, die in der Java-Sprache
definiert sind.
In vielen Fällen ist dies jedoch schlichtweg nicht möglich. Zur
völligen Umgehung dieses Problems ist es jedoch ausreichend,
lediglich eine einzige einfache Regel zu beachten:
-
Verwenden Sie ausschließlich offiziell dokumentierte APIs. Verweisen
Sie nur auf Pakete, die im publizierten API-Javadoc für
die Komponente dokumentiert sind.
Verweisen Sie unter keinen Umständen auf ein Paket, das zu einer
anderen Komponente gehört, deren Name die Angabe "internal" enthält,
denn dies sind keine API-Pakete. Verweisen Sie nie auf ein Paket, für die kein publiziertes
API-Javadoc vorhanden ist - auch hier handelt es sich nicht um
API-Pakete.
Allgemeine Regeln
Die Spezifikation von API-Elementen wird aus den Javadoc-Kommentaren
im Java-Quellcode des Elements generiert. Bei einigen Elementtypen wird die Spezifikation in Form einer
Vereinbarung bereitgestellt. Beispielsweise besteht bei Methoden die Vereinbarung zwischen
zwei
Partnern: dem Modul, das die Methode aufruft, und dem Modul, das die
Methode implementiert. Hierbei gilt die folgende Grundregel:
-
Respektieren Sie alle Vereinbarungen. Die Vereinbarungen
sind im
publizierten Javadoc des API-Elements beschrieben, das Sie verwenden.
Wenn in einer API-Vereinbarung der Begriff "muss" ("must") verwendet
wird,
bedeutet dies, dass der Vereinbarungspartner selbst für die
Einhaltung der
beschriebenen Bedingung sorgen muss. Alle Fälle, in denen dies nicht
sichergestellt wird, werden als Programmierfehler mit nicht genauer
definierten (und möglicherweise unvorhersehbaren) Folgen betrachtet.
-
Bedingungen, die den Begriff "muss" ("must") enthalten, müssen
respektiert werden. Bitte achten Sie deshalb insbesondere auf
solche Bedingungen.
Weitere allgemein gültige Regeln:
-
Stützen Sie sich nicht auf ein zufälliges Verhalten. Ein
zufälliges Verhalten, ist ein Verhalten, das bei Tests oder im
praktischen Einsatz beobachtet wurde, jedoch nicht durch eine
API-Spezifikation garantiert wird.
-
Setzen Sie "Null" nicht als Objekt ein. "Null" entspricht eher
dem Fehlen eines Objekts.
Gehen Sie davon aus, dass alles Vorhandene "Nicht-Null" entspricht,
es sei denn, dass in der API-Spezifikation etwas anderes angegeben
ist.
-
Versuchen Sie nicht, die Java-Spiegelung zu überlisten. Die
Verwendung der Java-Spiegelung zur Umgehung der
Java-Compiler-Prüfungen bringt Ihnen keine Vorteile. Es gibt keine zusätzlichen API-Vereinbarungen über die Verwendung der
Spiegelung. Die Spiegelung erhöht lediglich das
Risiko, dass Sie sich auf ein nicht definiertes Verhalten und interne
Implementierungsdetails stützen.
-
Verwenden Sie Ihre eigenen Pakete. Deklarieren Sie Code nicht
in einem Paket, das zu einer anderen Komponente gehört. Deklarieren Sie Ihren eigenen Code immer in eigenen Paketen.
Öffentliche API-Methoden aufrufen
Bei den meisten Clients besteht der Hauptteil der Eclipse-API aus
öffentlichen Methoden für API-Schnittstellen oder -Klassen, die der
Client aufrufen kann, wenn dies erforderlich ist.
-
Stellen Sie sicher, dass alle erforderlichen Voraussetzungen
gegeben sind. Gewährleisten Sie, dass die Voraussetzungen für
eine API-Methode vorliegen, bevor Sie die Methode aufrufen. Als Umkehrschluss kann das aufrufende Modul sicher davon ausgehen,
dass die Bedingungen, die für die Methode anschließend vorliegen
müssen, mit der Rückgabe aus dem Aufruf sofort zur Verfügung stehen.
-
Geben Sie Werte für Parameter an. Übergeben Sie einen Nullwert
nur dann als Parameter an eine API-Methode, wenn die Dokumentation
ausdrücklich angibt, dass ein Nullwert für den Parameter zulässig ist. Dies ist möglicherweise der am häufigsten begangene Programmierfehler.
-
Beachten Sie Einschränkungen für aufrufende Module. Rufen Sie
eine API-Methode, die laut Dokumentation nur bestimmten aufrufenden
Modulen zur Verfügung steht, nur dann auf, wenn eines dieser Module
verwendet wird. In bestimmten Situationen müssen Methoden Teil der öffentlichen API
sein, damit eine bestimmte Klasse von aufrufenden Modulen (häufig
interne Module) verwendet werden kann. Wenn Sie eine dieser Methoden
zum falschen Zeitpunkt aufrufen, hat dies nicht genauer definierte
(und möglicherweise unvorhersehbare) Folgen.
-
Verwenden Sie keine Debug-Methoden. Rufen Sie keine
API-Methode mit der Kennzeichnung "for debugging purposes only" ("nur
für Debug-Zwecke gedacht") auf. In diese Kategorie fallen beispielsweise die meisten
Methoden toString().
-
Gehen Sie bei der Angabe von Parametern sorgfältig vor. Sie
dürfen auf keinen Fall Bereiche
Objektgruppen oder andere veränderbare Objekte als
Parameter an eine API-Methode übergeben und anschließend das
übergebene Objekt ändern, da dies mit Sicherheit Fehler verursacht.
Plattform-API-Klassen als Exemplare erstellen
Nicht alle konkreten API-Klassen können durch jeden Benutzer als
Exemplar erstellt werden.
API-Klassen enthalten eine Vereinbarung über die Exemplarerstellung,
die die Bedingungen angibt, unter denen Exemplare erstellt werden
können. Die Vereinbarung kann außerdem andere Aspekte wie die
Verantwortlichkeiten für die lokale Initialisierung (z. B. das
Konfigurieren einer bestimmten Eigenschaft, bevor das Exemplar
gänzlich aktiv ist) sowie Zuständigkeiten für den zugeordneten
Lebenszyklus (z. B. das Aufrufen der Methode dispose() zum
Freigeben von Betriebssystemressourcen, die durch das Exemplar
belegt wurden) behandeln. Klassen, die von Clients als Exemplare erstellt werden können, sind
im Javadoc-Kommentar zur Klasse explizit gekennzeichnet
(mit Angaben wie "Clients
may instantiate" = "Clients können Exemplare erstellen" o. ä.).
-
Beachten Sie Einschränkungen für die Exemplarerstellung. Erstellen
Sie nur dann ein Exemplar einer API-Klasse, die laut Dokumentation
nur bestimmten Partnern zur Verfügung steht, wenn Sie einer dieser
Partner sind.
In bestimmten Situationen müssen Klassen Teil der öffentlichen API
sein, um einen bestimmten Partner (häufig intern) verwenden zu können.
Wenn Sie eine dieser Klassen unzulässigerweise als Exemplar erstellen,
hat dies nicht genauer definierte (und möglicherweise unvorhersehbare) Folgen.
Plattform-API-Klassen als Unterklassen aufnehmen
Nur ein Teil der API-Klassen kann als Unterklasse aufgenommen werden. API-Klassen
enthalten eine Vereinbarung über Unterklassen. Diese gibt die
Bedingungen an, unter denen Unterklassen deklariert werden können. Diese Vereinbarung behandelt auch die Verantwortlichkeiten für
Initialisierung und Lebenszyklus. Klassen, die von Clients als Unterklassen aufgenommen werden können,
sind
im Javadoc-Kommentar zur Klasse explizit gekennzeichnet (mit Angaben
wie "Clients may subclass" = "Clients können Unterklassen
aufnehmen" o. ä.).
-
Beachten Sie Einschränkungen für die Aufnahme von Unterklassen. Nehmen
Sie eine API-Klasse nicht als Unterklasse auf, die hierfür nicht
vorgesehen ist. Behandeln Sie solche Klassen so wie als "final" deklarierte Klassen. (In manchen Fällen werden solche Klassen mit "soft final"
bezeichnet.)
Geschützte API-Methoden aufrufen
Das Aufrufen von übernommenen geschützten und öffentlichen Methoden
aus einer Unterklasse heraus ist generell zulässig. Häufig ist es
jedoch komplizierter, auf einen korrekten Aufruf zu achten, als
öffentliche Methoden außerhalb der Hierarchie aufzurufen.
API-Methoden überschreiben
Nur ein Teil der öffentlichen und geschützten API-Methoden kann überschrieben werden.
API-Klassen enthalten eine Vereinbarung über Unterklassen. Diese gibt
die Bedingungen an, unter
denen sie durch eine Unterklasse überschrieben werden kann. Standardmäßig
ist es nicht zulässig, eine Klasse zu überschreiben.
Die Vereinbarung über Unterklassen in der tatsächlichen
Methodenimplementierung, die überschrieben werden soll, muss
genau überprüft werden. Die Bedingungen der Vereinbarungen über
Unterklassen werden nicht automatisch übergeben, wenn diese Methode
überschrieben wird.
-
Überschreiben Sie eine öffentliche oder geschützte API-Methode nur dann, wenn dies ausdrücklich zulässig ist. Sofern nichts anderes angegeben ist, sollten Sie alle Methoden so wie
als "final" deklarierte Methoden behandeln. (In manchen Fällen werden solche Methoden mit "soft
final" bezeichnet.)
Für die einzelnen Möglichkeiten, eine Methode zu überschreiben,
gilt Folgendes:
implement (implementieren): Die abstrakte Methode, die in
der Unterklasse deklariert ist, muss durch eine konkrete Unterklasse
implementiert werden.
extend (erweitern): Die Methode, die in der Unterklasse
deklariert ist, muss die Methode in der Superklasse aufrufen (exakt
1).
re-implement (erneut implementieren): Die Methode, die in
der Unterklasse deklariert ist, darf die Methode in der Superklasse
nicht aufrufen.
override (überschreiben): Die Methode, die in der
Unterklasse deklariert ist, kann die Methode in der Superklasse
erforderlichenfalls aufrufen.
-
Stellen Sie sicher,
dass alle nachträglichen Bedingungen erfüllt werden. Sie
müssen gewährleisten, dass alle nachträglichen Bedingungen, die für
die API-Methode angegeben sind, nach der Rückgabe durch die
Implementierung erfüllt werden.
-
Prüfen Sie selbst, ob Voraussetzungen erfüllt werden. Gehen
Sie nicht davon aus, dass Voraussetzungen, die für die API-Methode
angegeben sind, zwangsläufig von vornherein erfüllt werden. Auch wenn es bei der Methodenimplementierung zulässig ist, angegebene
Voraussetzungen nicht zu überprüfen, ist dies doch eine sinnvolle
Maßnahme (wenn dies mit einem vertretbaren Aufwand möglich ist), um
aufrufende Module mit einem nicht ordnungsgemäßen Verhalten zu
ermitteln.
-
Geben Sie Werte für Ergebnisse an. Geben Sie als Ergebnis
aus einer API-Methode nur dann einen Nullwert an, wenn
in der Dokumentation (für die angebende Schnittstelle oder
Superklasse) ausdrücklich angegeben ist, dass das Ergebnis einen
Nullwert enthalten kann.
-
Geben Sie Kopieren zurück. Geben Sie als Ergebnis aus einer
API-Methode in keinem Fall einen nicht ersetzbaren Bereich, eine
solche Objektgruppe oder ein anderes veränderbares Objekt mit dieser
Eigenschafte zurück. Geben Sie immer eine Kopie zurück, um Probleme mit aufrufenden
Modulen zu vermeiden, die das Objekt ändern könnten.
Plattform-API-Schnittstellen implementieren
Nur ein Teil der API-Schnittstellen kann durch Clients implementiert
werden. API-Schnittstellen enthalten eine Vereinbarung mit den Bedingungen,
unter denen sie implementiert werden können. Schnittstellen, die durch Clients implementiert werden können, sind
im Javadoc-Kommentar zur Klasse explizit gekennzeichnet (mit Angaben
wie etwa "Clients may implement" = "Implementierung durch Clients ist
zulässig" o. ä.). Ein Client kann eine Unterschnittstelle einer
API-Schnittstelle nur und ausschließlich dann deklarieren, wenn ihre
Implementierung zulässig ist.
-
Beachten Sie Einschränkungen
für implementierende Module. Implementieren Sie eine
API-Schnittstelle, die laut Dokumentation nur bestimmten Partnern zur
Verfügung steht, nur dann, wenn Sie einer dieser Partner sind. In vielen Fällen werden Schnittstellen dazu eingesetzt, interne
Implementierungsdetails für den Benutzer zu verdecken.
Öffentliche API-Methoden implementieren
Siehe "API-Methoden überschreiben".
Auf Felder in API-Klassen und -Schnittstellen zugreifen
Clients können API-Felder lesen, von denen die meisten final sind. Bestimmte
strukturähnliche Objekte können nicht als "final" definierte
öffentliche Felder enthalten, die Clients lesen und schreiben können,
sofern nichts anderes angegeben ist.
-
Geben Sie Werte für Felder an. Setzen Sie ein API-Feld nur
dann auf Null, wenn dies ausdrücklich zulässig ist.
Objekte eines bekannten API-Typs umsetzen
Ein Objekt mit einem bekannten API-Typ kann nur dann in einen anderen
API-Typ umgesetzt (oder mit "instanceof" bedingt umgesetzt) werden,
wenn dies in der API ausdrücklich zulässig ist.
-
Setzen Sie Umsetzungsausdrücke und Ausdrücke "instanceof"
vorsichtig ein. Verwenden Sie Ausdrücke "cast" und "instanceof"
nicht, um die bekannte Unterstützung der API für ein Objekt zu
vergrößern.
Bei einer unsachgemäßen Verwendung entstehen zufällige
Implementierungsdetails, die durch die API nicht garantiert werden.
Außerdem und logischerweise ist das Umsetzen eines Objekts in ein
eine Klasse oder Schnittstelle, die keine API-Klasse oder
-Schnittstelle ist, immer ungeeignet.
Folgen bei Nichteinhaltung der Regeln
Regelübertretungen - seien sie nun vorsätzlich oder unbeabsichtigt
- sind nie folgenlos. Es wäre wahrscheinlich einfacher für alle Beteiligten, wenn es eine
Art "API-Polizei" gäbe, die solche Regelübertretungen entsprechend
sanktioniert. Dies ist jedoch nicht der Fall.
Die Berücksichtigung der API-Regeln erfolgt größtenteils auf
Vertrauensbasis. Bei diesem System ist jeder Client dafür
verantwortlich, die Regeln zu kennen und zu befolgen.
Die Vereinbarungen in den API-Elementen beschränken das unterstützte
und ordnungsgemäße Verhalten. Da sich die Eclipse-Plattform weiterentwickelt und ausreift, können
Sie anhand der API-Vereinbarungen verfolgen, wie sich diese
Entwicklung vollzieht. Alles, was nicht in diesen Vereinbarungen angegeben ist, wird nicht
unterstützt und kann jederzeit und ohne vorherige Ankündigung
geändert werden (sogar mitten in einem Release oder zwischen
unterschiedlichen Betriebssystemplattformen. Client-Code, der gegen die vorstehenden Regeln verstößt, kann auf
unterschiedlichen Versionen und Programmkorrekturstufen der
Plattform fehlschlagen, außerdem bei der Ausführung auf verschiedenen
Betriebssystemen,
bei einer Ausführung mit einem unterschiedlichen Mix aus ebenfalls
residenten Plug-ins oder bei der Verwendung mit einer anderen
Workbench-Perspektive usw. Natürlich ist es für niemanden besonders interessant, genau
vorherzusagen, in welcher Form sich eine bestimmte Regelübertretung
negativ auswirken kann. Diejenigen, die die Regeln ignorieren wollen, sollten später nur
nicht behaupten, dass sie nicht gewarnt worden wären, oder mehr als
ein mitfühlendes "Wir haben es ja vorhergesagt" erwarten.
Ein Client-Plug-in-Code, der die oben beschriebenen Regeln hingegen
befolgt, sollte auch über unterschiedliche Versionen oder
Programmkorrekturstufen der Plattform hinweg und auf verschiedenen zu
Grunde liegenden Betriebssystemen weiterhin funktionieren und
problemlos mit anderen Plug-ins koexistieren können. Wenn alle Beteiligten sich an die Regeln halten, bietet die
Eclipse-Plattform eine stabile und unterstützte Basis, auf der
interessante neue Produkte erstellt werden können.