API-Design. Kai Spichale

Чтение книги онлайн.

Читать онлайн книгу API-Design - Kai Spichale страница 14

Автор:
Серия:
Издательство:
API-Design - Kai Spichale

Скачать книгу

weitere Informationen zu diesem Thema.

      Bessere Lesbarkeit und Wartbarkeit von Unit Tests waren die Entwurfsziele des FEST-Assert-Frameworks. In diesem Zusammenhang könnte man noch viele andere Bibliotheken mit gleichem Zweck nennen: Das Spock Famework beispielsweise bietet eine kleine DSL zur übersichtlichen Strukturierung von Tests.

      Ein Beispiel aus einem ganz anderen Aufgabengebiet ist die JPA Criteria API. Diese API dient zur Konstruktion von typsicheren Datenbankabfragen. Mit dem folgenden Java-Code wird eine Query gebaut und ausgeführt, um alle Order-Objekte mit mehr als einer Position zu selektieren:

      EntityManager em = ...;

      CriteriaBuilder builder = em.getCriteriaBuilder();

      CriteriaQuery<Order> cq = builder

      .createQuery(Order.class);

      Root<Order> order = cq.from(Order.class);

      order.join(Order_.positions);

      cq.groupBy(order.get(Order_.id)).having(

      builder.gt(builder.count(order), 1));

      TypedQuery<Order> query = em.createQuery(cq);

      List<Order> result = query.getResultList();

      Übersichtlicher wird die Abfrage mit QueryDSL. Diese Bibliothek bietet ein Fluent Interface, mit dem verständliche Pfadausdrücke formuliert werden können.

      EntityManager em = ...;

      QOrder order = QOrder.order;

      JPQLQuery query = new JPAQuery(em);

      List<Order> list = query.from(order)

      .where(order.positions.size().gt(1))

      .list(order).getResults();

      Entwickler verbringen mehr Zeit mit dem Lesen als mit dem Schreiben von Quellcode. Daher kann deren Produktivität durch gut lesbaren Quellcode bzw. einer leicht verständlichen API verbessert werden. Wie können APIs zu lesbarem Code führen?

       Gute Namenskonventionen sind wichtig, denn sie unterstützen das Lesen und Erfassen des Quellcodes. Gut lesbarer Code enthält auch weniger Fehler, denn Fehler fallen dann schneller auf.

       Die zuvor beschriebenen Eigenschaften Konsistenz und intuitive Verständlichkeit haben ebenfalls einen großen Einfluss auf die Lesbarkeit des Clientcodes.

       Auch ein einheitliches Abstraktionsniveau verbessert die Lesbarkeit von Code. Das bedeutet, dass eine API beispielsweise nicht Persistenzfunktionen mit Geschäftslogik mischen sollte. Das sind Aufgaben unterschiedlicher Abstraktionsniveaus. Wenn diese vermischt werden, entsteht unnötig komplexer Clientcode. Die gewählten Abstraktionen der API sollten passend für die zukünftigen Benutzer ausgewählt werden.

       APIs sollten Hilfsmethoden bieten, sodass der Clientcode kurz und verständlich bleibt. Ein Client sollte nichts tun müssen, was ihm die API abnehmen kann.

       2.2.6Schwer falsch zu benutzen

      Eine API sollte nicht nur einfach zu benutzen, sie sollte sogar schwer falsch zu benutzen sein. Daher sollte man nicht offensichtliche Seiteneffekte vermeiden und Fehler zeitnah mit hilfreichen Fehlermeldungen anzeigen. Benutzer sollten nicht gezwungen sein, die Methoden einer API in einer fest definierten Reihenfolge aufzurufen.

       Unerwartetes Verhalten

      Die ursprüngliche Datums- und Zeit-API von Java sieht auf den ersten Blick einfach und intuitiv aus. Doch schon bei einfachen Beispielen stolpert man über ein Verhalten, das man vermutlich nicht erwartet. Was das bedeutet, wollen wir uns an einem Beispiel anschauen:

      Die ursprüngliche Datums- und Zeit-API von Java lädt geradezu dazu ein, Fehler zu machen. Den 20. Januar 1983 würde man vermutlich so definieren wollen:

      Date date = new Date(1983, 1, 20);

      Leider enthält diese Codezeile gleich zwei Fehler. Denn die Zeitrechnung dieser API beginnt unerwarteterweise im Jahre 1900. Außerdem sind die Monate beginnend mit 0 durchnummeriert. Die Tage werden beginnend mit 1 angegeben. Deswegen muss der 20. Januar 1983 folgendermaßen erzeugt werden:

      int year = 1983 – 1900;

      int month = 1 - 1;

      Date date = new Date(year, month, 20);

      Im nächsten Schritt geben wir zusätzlich noch die Uhrzeit 10:17 mit der Zeitzone von Bukarest an. Die Uhrzeit soll schließlich in einen formatierten String umgewandelt werden. Weil die Klasse Date keine Zeitzonen unterstützt, müssen wir ein Calendar-Objekt erzeugen. Die erwartete Ausgabe ist »20.01.1983 10:17 +0200«.

      Date date = new Date(year, month, 20, 10, 17);

      TimeZone zone = TimeZone.getInstance("Europe/Bucharest");

      Calendar cal = new GregorianCalendar(date, zone);

      DateFormat fm = new SimpleDateFormat("dd.MM.yyyy HH:mm Z");

      String str = fm.format(cal);

      Auch hier verstecken sich mehrere Fehler: Der Konstruktor der Klasse GregorianCalendar akzeptiert eine Zeitzone, aber kein Date-Objekt. Der Calendar kann nicht von SimpleDateFormat formatiert werden. Auch SimpleDateFormat muss die Zeitzone übergeben werden. Durch Angabe der Zeitzone wird die Uhrzeit verändert. Der korrigierte Clientcode sieht so aus:

      int year = 1983 - 1900;

      int month = 1 - 1;

      // weil 1 Stunde Zeitunterschied zwischen Berlin und Bukarest

      int hour = 10 - 1;

      Date date = new Date(year, month, 20, hour, 17);

      TimeZone zone = TimeZone.getInstance("Europe/Bucharest");

      Calendar cal = new GregorianCalendar(zone);

      cal.setTime(date);

      DateFormat fm = new SimpleDateFormat("dd.MM.yyyy HH:mm Z");

      fm.setTimeZone(zone);

      Date calDate = cal.getTime();

      String str = fm.format(calDate);

      Aufgrund dieser Fallstricke entstand in der Java-Community die Bibliothek Joda-Time. Der Clientcode könnte folgendermaßen aussehen:

      DateTime dt = new DateTime(1983, 1, 20, 10, 17,

      DateTimeZone.forID("Europe/Bucharest"));

      DateTimeFormatter formatter

      = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm Z");

      String str = dt.toString(formatter);

Скачать книгу