Heute widmen wir uns einem Thema, das tagtäglich jeden iOS-und MacOS-Entwickler betrifft: Das Erstellen und Lesen von Code. Genauer gesagt die Erstellung von Objective-C Klassen und deren „Aufteilung“ in Header bzw. Implementations-Dateien (.h/.m). Hierbei befindet sich jeder Entwickler sowohl in der Rolle eines „API-Nutzers“, also durch Nutzung/Einsatz von Klassen anderer Entwickler im Team oder anderen externen Libraries (OpenSource oder ClosedSource-Binary). Zugleich ist man als Entwickler durch Generierung von eigenen Klassen auch immer in der Rolle eines „API-Erstellers“ (also für die anderen Entwickler oder gezielt zur Publizierung einer Library/Framework).

Naturgemäß fällt der erste Blick eines Entwicklers, wenn er zum ersten mal mit fremdem (aber auch eigenem) „C-basierten“ Code umgehen muss, auf die Header-Dateien der einzelnen Klassen. Diese .h-Dateien dienen hierbei als „Schnittstelle zur Aussenwelt“ und geben dem Entwickler einen ersten Eindruck über Funktionsweise der Klasse und eine erste Idee, wie diese am besten in den bisherigen eigenen Code zu integrieren ist. Der folgende Code-Schnipsel zeigt eine exemplarische (keine reale, vollständige) Header-Datei, in der viele typische Eigenschaften aus dem Entwicklungs-Alltag zu sehen sind. Das entspricht im Allgemeinen den Klassen die man von anderen Entwicklern vorfindet bzw. die man selber erstellt.

 

Auf den ersten Blick nichts besonderes oder auffälliges. Auf den zweiten Blick jedoch sind zahlreiche Unschönheiten oder gar gefährliche Stellen zu sehen, die ganz sicher „nicht im Sinne des Erfinders“ sind. Versetzen wir uns mal gezielt in beide Rollen, also des API-Erstellers und des  API-Nutzers; wir stellen folgendes fest:

  • Die Klasse scheint „intern“ ein Protokoll zu implementieren (in dem Fall: NSURLConnectionDelegate). Eine Tatsache, die zwar technisch für die Funktionalität der Klasse notwendig ist, jedoch nicht zwingend dem API-Nutzer in der Header-Datei „gezeigt“ werden will (aus der Perspektive des API-Erstellers).
  • Es werden zahlreiche Instanzvariablen (ivar) aufgelistet, die ebenfalls technisch benötigt aber aus API-Nutzer-Perspektive eher störend wenn nicht gar irritierend empfunden werden, da hier zahlreiche Klassen-Internas unnötig preisgegeben werden. (Bei Klassen mit sehr vielen ivars wird zusätzlich die Größe und somit die Lesbarkeit und das Verständnis der .h Datei verschlechtert)
  • Das Property „urlrequest“ ist mit großer Warscheinlichkeit nicht dafür gedacht dass es von „außen“ also von einem API-Nutzer manipuliert also gesetzt (setter) werden kann, dennoch wird es so von einem API-Nutzer gelesen und womöglich wird von dieser setter-Möglichkeit auch Gebrauch gemacht. (nicht selten endet das in einem fatalen Fehlverhalten der benutzten Klasse, da diese Funktionalität nicht bewusst vom API-Ersteller vorgesehen war)
  • Das IBOutlet-Property „deleteButton“ hat mit hoher Wahrscheinlichkeit nichts mit der vom API-Ersteller beabsichtigten public-API der Klasse zu tun, sondern hat lediglich den Zweck um mit einer UI-Komponente (aus einer .xib oder .storyboard Datei) verbunden zu werden. Also prinzipiell eine rein interne Angelegenheit der betroffenen Klasse. Kein Freischein für externe Manipulationen, wie es hier auch verstanden (und in der Praxis auch missbraucht) werden kann.

Was der geneigte API-Ersteller der Klasse einem potenziellen API-Nutzer eigentlich „zeigen“ will, ist folgendes:

 

Eine „saubere“ Klassen-API, in der nur diejenigen Sachen deklariert sind, die für den API-Nutzer zielführend von Interesse sind bzw. die für diesen zugänglich und beeinflussbar sein sollen. Ein Wunschtraum? Nein, Realität! Wenn man hierzu einige Dinge in die Implementierungsdatei der Klasse (.m) verlagert , die als „private API“ der Klasse einzustufen sind. Und so sieht der Trick in der Praxis aus:

Die spannendsten Tatsachen dürften folgende sein:

  • Die 2 zusätzlichen Stellen, in denen Instanzvariablen deklariert werden können, alternativ zur Header-Datei, siehe „_iVarABC“ oder „_iVarXYZ“
  • Die Möglichkeit IBOutlet (auch IBOutletCollection und IBAction) keywords in der m-Datei einzusetzen. Das aktuelle XCode (4.3.x) erlaubt dies mittlerweile und bietet mit der „Assistent“-Ansicht zudem eine elegante Möglichkeit InterfaceBuilder-Elemente mit Code zu verbinden per Drag-and-Drop.

Wenn man Klassen nach dieser Strategie entwickelt, sorgt das automatisch für eine gute Datenkapselung, korrekte Sichtbarkeit und mehr Akzeptanz bei den API-Nutzern. Getreu dem Motto: Komplexität verbergen, Simplizität hervorheben.

Bewerte diesen Beitrag
0 Kommentare

Dein Kommentar

An Diskussion beteiligen?
Hinterlasse uns Deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.