API-Design. Kai SpichaleЧитать онлайн книгу.
zu verändern. Die Spezifikationen definieren die Konzepte der API und die Anforderungen an Implementierungen. Eine textuelle Spezifikation kann durch ein detailliertes JavaDoc vervollständigt werden. Darin werden konkrete Packages, Interfaces, Klassen etc. genannt und beschrieben. Weitere Details zu JavaDoc finden Sie in Kapitel 12.
Prinzipiell können Sie eine API-Spezifikation in folgende Abschnitte gliedern:
Allgemeine Spezifikation
Auf dieser Ebene können Eigenschaften spezifiziert werden, die für die gesamte API gültig sind. Beispielsweise kann festlegt werden, dass alle Objekte Thread-sicher sind. Abweichungen werden explizit angegeben. Ein anderes Beispiel ist der Umgang mit Unchecked Exceptions.
Package-Spezifikation
Diese Angaben sind gültig für alle Elemente innerhalb eines Packages. Der Zweck des Packages sollte kurz und präzise beschrieben sein. Verweise auf andere Dokumente können hier ebenfalls eingefügt werden.
Klassen- und Interface-Spezifikation
Dieser Abschnitt beginnt stets mit einer kurzen und präzisen Beschreibung des Objektes. Es folgen Angaben zu Thread-Sicherheit, Zustand (Immutability), Serialisierung, erlaubte Implementierungsvarianten, eventuelle Hardwareabhängigkeiten, Sicherheitseinschränkungen und Verweise auf andere Dokumente.
Feldspezifikation
Zur Spezifikation eines Feldes gehört dessen Bedeutung, Wertebereich und eine Aussage, ob das Feld null sein könnte.
Methoden- und Konstruktorspezifikation
Das erwartete Verhalten der Methode ist in jedem Fall anzugeben. Falls der Aufruf der Methode den Zustand des Objektes ändert, sollte ebenfalls die Zustandsänderung beschrieben werden. Weitere Angaben umfassen Bedeutung und Wertebereiche der Parameter, null-Parameter, mögliche Rückgabewerte, null-Rückgaben, erlaubte Implementierungsvarianten, Sicherheitseinschränkungen und Exceptions. Um das Verhalten der Methode korrekt beschreiben zu können, müssen häufig auch Algorithmen beschrieben werden.
Der Teufel steckt häufig im Detail, deswegen kann sich eine aufwendige Dokumentation gerade für veröffentlichte APIs lohnen. Vergessen Sie jedoch nicht zu beschreiben, wie die einzelnen Objekte im Kontext verwendet werden sollen. Typischerweise enthalten JSR-Spezifikationen (Java Specification Request) auch Beispiele, um die Funktionsweise zu verdeutlichen.
3.7Reviews und Feedback
Was würden Sie über eine Bibliothek oder einen Dienst denken, wenn Sie beim erstmaligen Ausprobieren schon nach wenigen Minuten falsch geschriebene Bezeichner oder Inkonsistenzen finden? Sie würden sich vermutlich fragen, ob Sie an dieser Stelle abbrechen und Ihre Arbeit mit einer Alternative fortsetzen sollten.
Berühmte API-Typos
Als Ken Thompson, der Erfinder von Unix, einmal gefragt wurde, was er anders machen würde, wenn er Unix noch einmal neu schreiben würde, antwortete er: »Ich würde create mit einem 'e' schreiben.« Gemeint war die Funktion creat zur Öffnung eines Dateideskriptors für I/O-Operationen. Auch der HTTP-Header refer(r)er wurde falsch geschrieben. Das Gleiche gilt für mnemonic in der Funktion SHStripMneumonic. Der Schreibfehler fiel zunächst nicht auf oder wurde als unwichtig eingestuft, weil diese Funktion nur intern verwendet wurde. Als jedoch später die betreffende Bibliothek ohne weitere Qualitätssicherung veröffentlicht wurde, war es zu spät. Der Name konnte nicht mehr korrigiert werden. Denn eine Änderung hätte Auswirkungen auf alle Programme, die diese Funktion verwenden.
Diese Art von einfachen Fehlern kann man leicht aufspüren und beheben. Sie können beispielsweise eine Kollegin oder einen Kollegen bitten, ein Review zu machen, denn bekanntlich ist man blind für seine eigenen Fehler. Feedback ist insgesamt sehr wichtig für den Entwurf einer API. Zeigen Sie die entworfene API Ihrem Team und führen Sie Gespräche mit Benutzern der API, um Feedback zu sammeln. Auch negatives Feedback hilft. Je mehr Informationen Ihnen zur Verfügung stehen, desto besser sind Ihre Chancen, eine gute API zu entwerfen.
3.8Wiederverwendung
Versuchen Sie nicht alles neu zu erfinden, sondern versuchen Sie etablierte Konzepte und Bezeichner wiederzuverwenden, die die Benutzer Ihrer API vermutlich schon kennen. Beispielsweise hat jeder Java-Entwickler eine intuitive Erwartung, wie sich die Methode add einer Klasse namens OrderSet verhält. Nutzen Sie dieses Wissen für sich aus. Berücksichtigen Sie beispielsweise auch die bekannten Namenskonventionen von JavaBeans.
Wiederverwendung heißt auch, von anderen guten APIs zu lernen. Nutzen Sie die Namen und Muster von APIs von Bibliotheken oder Diensten, die Sie bereits kennen oder die von vielen anderen Entwicklern verwendet werden.
Falls die Anwendung, an der Sie arbeiten, bereits andere Schnittstellen hat, dann sollten Sie diese beim Entwurf der neuen berücksichtigen. Denn die Benutzer der neuen API kennen bereits die Namen und Konzepte der existierenden APIs. Versuchen Sie eine dazu passende API zu entwerfen, sodass die Lernkurve der Benutzer möglichst flach bleibt.
3.9Zusammenfassung
In diesem Kapitel wurde das allgemeine Vorgehen beim Entwurf einer API beschrieben. Die wichtigsten Informationen sind hier noch einmal kurz zusammengefasst:
Softwareentwurf basiert nicht auf deterministischen Algorithmen, sondern auf Heuristiken.
Wenn die Anforderungen nicht stimmen, ist es fast egal, wie gut der Rest des Projektes läuft.
Entwerfen Sie APIs mit Beispielen für wichtige Benutzungsszenarien.
Zeigen Sie die API anderen Entwicklern und zukünftigen Benutzern. Nutzen Sie Feedback für Verbesserungen.
Nutzen Sie das Vorwissen der API-Benutzer aus.
Lassen Sie sich von guten APIs inspirieren.
Im nächsten Kapitel werden objektorientierte Java-APIs vorgestellt, die in vielen unterschiedlichen Formen genutzt werden.
4Ausprägungen
Java-APIs sind sehr vielfältig, sodass man sie auf verschiedenen Ebenen diskutieren kann. Das Spektrum reicht von den APIs einzelner Klassen und Komponenten bis zu den APIs ganzer Frameworks. Zwischen den folgenden Ausprägungen kann man unterscheiden:
Implizite Objekt-API
Utility-Bibliothek
Service
Framework
4.1Implizite Objekt-API
Jedes Objekt hat eine extern sichtbare Schnittstelle, die im Wesentlichen nicht private Methoden und Konstruktoren umfasst. Diese Schnittstelle bildet per Definition die API des Objektes. Objekte sind untereinander verbunden, sodass APIs typischerweise nicht nur auf Basis einzelner Klassen, sondern auf Basis mehrerer miteinander verbundener Klassen zu betrachten sind. Nichtsdestotrotz ist API-Design auf dieser Ebene eng verbunden mit allgemeineren Konzepten wie dem Geheimnisprinzip, Datenkapselung und der Trennung von Zuständigkeiten: