Einheitlichkeit und Übersichtlichkeit in Swift Code-Dateien

16. April 2018

Orientierung in komplexen Projekten

Jeder, der im Team programmiert, hat diese Situation vermutlich schon einmal erlebt: Ihr wollt in einem großen Projekt eine Änderung vornehmen und sucht den richtigen Code-Abschnitt; und ihr sucht und sucht und sucht ... selbst, wenn man schon die richtige Datei vor sich hat, kann es eine gefühlte Ewigkeit dauern, bis man endlich fündig wird. Aber das muss nicht so sein. Wenn man ein paar Regeln beachtet, ist es ganz einfach, Dateien einheitlich übersichtlicher zu gestalten und es anderen in eurem Team zu erleichtern, sich in eurem Quellcode zurechtzufinden.

Ein sehr wichtiges Tool für die Orientierung ist die in Xcode eingebaute Jump-Leiste: Mit ihr erhält man eine Voransicht von allen Typen, Eigenschaften, Initialisern, Methoden, usw. einer Datei in einer einfachen, aufgeräumten Oberfläche:

Auf die Jump-Leiste kann man in der letzten Spalte der Datei-Navigation, ganz oben im Source-Editor zugreifen. Aber wie nutzt man sie am besten?

Es hat sich bewährt, alles nach zuvor festgelegten Regeln zu sortieren und das MARK-Feature in Xcode zu verwenden. Aber der Reihe nach: Was nützt einem das MARK-Feature, um bestehende Dateien schneller zu durchsuchen und wie vereinheitliche ich damit den Code?

Sortierung

Um mit der von Xcode durch die Jump-Leiste vorgegebenen Struktur zu harmonieren, haben sich folgende Regeln bewährt:

  • Jeder Typ kann verschiedene Untertypen beinhalten:

    • Ihre Länge sollte idealerweise auf maximal 20 Zeilen begrenzt sein.
    • Untertypen mit mehr als 20 Zeilen Länge, sollten in eine gesonderte Datei ausgegliedert und als unabhängiger Typ entworfen werden.
      • Lässt sich ein längerer Untertyp nicht ausgliedern, kann man ihn in einer Erweiterung zu seinem Obertyp - ganz am Ende der Datei - platzieren.
  • Innerhalb eines Typs sollten die einzelnen Elemente in folgender Reihenfolge sortiert werden:

    • Cases (für Enums)
    • Untertypen
      • Typaliase
      • verwandte Typen
      • andere Typen (Enums, Strukturen, Klassen)
    • Klasseneigenschaften
    • Instanzeigenschaften
    • Initialisierer
    • Klassenmethoden
    • Instanzmethoden
  • Wenn es mehrere Elemente einer Kategorie gibt, z.B. verschiedene Methoden, sollten sie zuallererst nach Funktion sortiert werden. Beispielweise gruppiert man alle Lebenszyklus-Methoden, alle Hilfsfunktionen, etc. zusammen.

  • Methoden, die Teil des Protokolls sind, fasst man in einer Erweiterung unter dem Haupttypen zusammen.

    • Hilfsmethoden, mit denen man ein Protokoll implementiert, kommen in die gleiche Erweiterung wie die eben genannten Methoden. Hilfsmethoden sollten immer unter Protokollmethoden stehen. Aber ACHTUNG: Sobald die Hilfsmethoden irgendwo anders auch verwendet werden (könnten), gehören sie zurück in den Haupttypen.
  • Eigenschaften und Methoden sollten zunächst nach Domäne, dann nach Sichtbarkeit sortiert sein – von oben nach unten:

    • open
    • public
    • internal
    • fileprivate
    • private

IBOutlets sollten beieinander stehen. Für Methoden ist die optimale Reihenfolge: 1. Life-Cycle-Methoden 2. IBActions 3. Selector-Aktionen 4. Hilfsmethoden

MARK-Richtlinien

MARKs richtig einzusetzen ist der nächste Schritt auf dem Weg zu einer übersichtlichen Datei-Struktur. Es gibt zwei grundlegende MARK-Typen:

  1. Trennstrich-MARK: // MARK: - Ein wichtiger Titel: In der Jump-Leiste erscheint dieses MARK sowohl in Fettschrift als auch mit Trennlinie oberhalb.
  2. Einfaches MARK: // MARK: Irgendein Titel: Dieses MARK erscheint als fettgedruckte Titelzeile innerhalb der Jump-Leiste, aber ohne eine Trennlinie darüber. Man kann es nutzen, um Elemente zu gruppieren - wenn man möchte.

Besondere Bedeutung kommt den Trennstrich-MARKs zu:

  1. Um die Übersichtlichkeit der Jump-Leiste zu optimieren, verwendet man ein Trennstrich-MARK für das jeweils erste Element der folgenden Gruppen:

- Cases (für Enums) - Untertypen - Eigenschaften - Initalisierer - Methoden

  1. Ein Trennstrich-MARK nutzt man zudem für jegliche Erweiterungen des Haupttyps innerhalb dieser Datei. Es nennt entweder das Protokoll, an das diese Erweiterung den Haupttyp anpasst, oder einen Titel, der den jeweiligen Inhalt der Erweiterung beschreibt.

Empfehlung

Für die letzte Empfehlung, wie man aufgeräumte und übersichtliche Dateien schreibt, gibt es so viele Ausnahmen, dass man sie nicht als feste Regel definieren sollte. Sie ist aber als Orientierungshilfe nützlich: Im Idealfall enthält jede Datei nur einen Top-Level Typen.

Beispiel

Das war jetzt ziemlich viel Theorie. In der Praxis kommt es darauf an, diese Struktur zur Gewohnheit werden zu lassen. Das erfordert schon einiges an Disziplin. Ich hoffe, dass ich euch mit einem Beispiel, wie strukturiert Dateien und die Jump-Leiste mithilfe dieser Regeln aussehen können, überzeugen kann, dass es sich lohnt. Schaut es euch an: Den zugehörigen Code findet ihr auf Github.