Refactoring von Legacy-Code in Swift: Von A bis Z

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Refactoring von Legacy-Code in Swift: Von A bis Z

\n

Die Arbeit mit Legacy-Code ist ein unvermeidlicher Teil des Lebens eines iOS/macOS-Entwicklers. Oft handelt es sich um Code, der in frühen Versionen von Swift oder sogar Objective-C geschrieben wurde, ohne Tests, mit "magischen Zahlen" und riesigen UIViewController. In diesem Artikel werden wir eine Schritt-für-Schritt-Strategie zum Refactoring solchen Codes durchgehen und ihn in ein modernes, wartbares und testbares Projekt verwandeln.

\n\n

1. Vorbereitung und Sicherheit: Bevor Sie den Code berühren

\n

Die wichtigste Regel des Refactorings: Zerstöre nicht, was funktioniert. Ohne Tests ist jede Änderung ein Sprung ins Ungewisse.

\n
    \n
  • Charakterisierungstests (Characterization Tests): Schreiben Sie Tests, die das aktuelle Verhalten festhalten. Auch wenn der Code falsch erscheint, dokumentieren Sie zuerst seine Funktionsweise.
  • \n
  • Versionskontrollsystem: Erstellen Sie einen Commit mit dem aktuellen Stand. Verwenden Sie einen Feature-Branch.
  • \n
  • Werkzeuge: Xcode mit Bearbeiten > Refactoren (Umbenennen, Methode extrahieren) sowie Linter (SwiftLint) zur Einhaltung eines einheitlichen Stils.
  • \n
\n\n
// Beispiel für das "Einfrieren" des Verhaltens einer alten Methode\nclass LegacyCalculator {\n    func calculateTotal(items: [Int]) -> Int {\n        // Alte, unleserliche Logik\n        var result = 0\n        for i in items {\n            result += i * 2\n        }\n        return result + 10\n    }\n}\n\n// Test, der das Verhalten festhält\nfunc testCalculateTotal() {\n    let sut = LegacyCalculator()\n    let result = sut.calculateTotal(items: [1, 2, 3])\n    XCTAssertEqual(result, 22) // (1+2+3)*2 + 10 = 22\n}\n
\n\n

2. Die "Prügelknabe"-Strategie: Globale Variablen und Singletons

\n

Legacy-Code ist berüchtigt für seine globalen Zustände und Singletons. Dies macht den Code stark gekoppelt und unvorhersehbar.

\n

Problem:

\n
class NetworkManager {\n    static let shared = NetworkManager()\n    var baseURL: String = "http://old.api.com"\n    func fetchData() { ... }\n}\n
\n

Lösung: Dependency Injection. Erstellen Sie ein Protokoll und übergeben Sie Abhängigkeiten über den Initialisierer.

\n
protocol NetworkService {\n    func fetchData()\n}\n\nclass ModernViewModel {\n    private let network: NetworkService\n    \n    init(network: NetworkService) {\n        self.network = network\n    }\n    \n    func load() {\n        network.fetchData()\n    }\n}\n
\n

Dieser Ansatz ermöglicht es, Dienste in Tests einfach auszutauschen und macht den Code modular.

\n\n

3. Kampf gegen den "Massiven View Controller"

\n

Klassiker des iOS-Legacy: Ein UIViewController, der für alles zuständig ist – von Netzwerkanfragen bis zur UI-Formatierung. Das Refactoring erfolgt durch Aufteilung der Verantwortlichkeiten (SRP).

\n\n

Schritt 1: Lagern Sie die Geschäftslogik in ein separates Modell (ViewModel) aus.

\n
// War im Controller\nfunc buttonTapped() {\n    let data = fetchData()\n    let total = data.reduce(0, +)\n    label.text = "Summe: \\(total)"\n}\n\n// Wurde zu: ViewModel\nclass MyViewModel {\n    func calculateTotal(data: [Int]) -> String {\n        let total = data.reduce(0, +)\n        return "Summe: \\(total)"\n    }\n}\n
\n\n

Schritt 2: Lagern Sie die UI-Konfiguration in separate Methoden oder Fabriken aus.

\n
    \n
  • Erstellen Sie eine Klasse ViewBuilder für komplexe Hierarchien.
  • \n
  • Verwenden Sie UICollectionViewDiffableDataSource anstelle des alten dataSource.
  • \n
\n\n

4. Modernisierung: Von Objective-C zu Swift und neuen APIs

\n

Oft enthält Legacy-Code eine Mischung aus Objective-C und Swift. Beim Refactoring ist es wichtig, veraltete Konstrukte zu aktualisieren:

\n\n
    \n
  • Ersetzen von NSError durch throws: Modernes Swift verwendet Exceptions zur Fehlerbehandlung.
  • \n
  • Verzicht auf ! (
  • \n

Blogs

Buchempfehlungen