Refactoring von Legacy-Code in JavaScript: Das vollständige Handbuch

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

Einleitung: Warum Legacy-Code kein Todesurteil, sondern eine Aufgabe ist

\n\n

Jeder Entwickler stößt früher oder später auf Legacy-Code – veralteten, schlecht dokumentierten und oft ungetesteten Code in JavaScript (Node.js). Die Arbeit mit solchem Code kann Angst und Frustration auslösen, ist aber ein unvermeidlicher Teil der beruflichen Entwicklung. Refactoring von Legacy-Code ist nicht einfach nur Umschreiben, sondern ein systematischer Prozess zur Verbesserung der internen Struktur ohne Änderung des externen Verhaltens.

\n\n

In diesem Artikel werden wir einen schrittweisen Ansatz zum Refactoring von veraltetem JavaScript-Code behandeln, einschließlich Strategien, Werkzeugen und konkreten Beispielen für Node.js. Sie erfahren, wie Sie "albtraumhaften" Code in eine wartbare, skalierbare und moderne Codebasis verwandeln.

\n\n

1. Analyse und Vorbereitung: Wo beginnt man mit dem Refactoring?

\n\n

1.1. Audit des vorhandenen Codes

\n\n

Bevor Sie etwas ändern, müssen Sie das aktuelle System vollständig verstehen. Verwenden Sie die folgenden Methoden:

\n\n
    \n
  • Statische Analyse: ESLint mit Plugins (eslint-plugin-import, eslint-plugin-security) deckt problematische Muster auf.
  • \n
  • Suche nach "roten Flaggen": Funktionen länger als 50 Zeilen, globale Variablen, Callback-Hell, fehlende Modularität.
  • \n
  • Dokumentation des aktuellen Verhaltens: Notieren Sie alle Ein- und Ausgabedaten der Schlüsselfunktionen.
  • \n
\n\n
// Beispiel: Suche nach "schlechten" Mustern mit ESLint\n// npm install eslint @eslint/js eslint-plugin-security --save-dev\n\n// eslint.config.js\nimport js from "@eslint/js";\nimport security from "eslint-plugin-security";\n\nexport default [\n  js.configs.recommended,\n  security.configs.recommended,\n  {\n    rules: {\n      "no-var": "error",\n      "prefer-const": "error",\n      "max-lines-per-function": ["warn", 40],\n    },\n  },\n];\n
\n\n

1.2. Erstellen eines Sicherheitsnetzes: Tests

\n\n

Regel Nr. 1 des Refactorings: Refactoren Sie niemals Code ohne Tests. Verwenden Sie für Node.js Jest oder Mocha. Beginnen Sie mit Integrationstests, die die wichtigsten Anwendungsszenarien überprüfen.

\n\n
// Beispiel: Test für eine Legacy-Funktion\n// legacy.js\nfunction processOrder(orderData) {\n  // ... 150 Zeilen verworrener Code\n  return result;\n}\n\n// processOrder.test.js\nconst processOrder = require('./legacy');\n\ndescribe('processOrder', () => {\n  it('sollte eine Standardbestellung verarbeiten', () => {\n    const input = { id: 1, items: ['book', 'pen'], total: 25 };\n    const result = processOrder(input);\n    expect(result.status).toBe('completed');\n    expect(result.total).toBe(25);\n  });\n\n  it('sollte bei leerer Bestellung einen Fehler werfen', () => {\n    expect(() => processOrder({})).toThrow('Invalid order');\n  });\n});\n
\n\n

2. Refactoring-Strategien: Vom Chaos zur Ordnung

\n\n

2.1. Die "Strangler Fig"-Strategie (Würgefeige)

\n\n

Dieser Ansatz ist besonders effektiv für große Node.js-Projekte. Sie ersetzen schrittweise Teile des Legacy-Systems durch neue Module, ohne den Betrieb der gesamten Anwendung zu unterbrechen.

\n\n
// Beispiel: Ersetzen eines alten HTTP-Clients durch einen neuen\n// Alter Code (Legacy)\nconst http = require('http');\n\nfunction fetchUserData(userId) {\n  return new Promise((resolve, reject) => {\n    http.get(`http://api.example.com/users/${userId}`, (res) => {\n      let data = '';\n      res.on('data', chunk => data += chunk);\n      res.on('end', () => resolve(JSON.parse(data)));\n    }).on('error', reject);\n  });\n}\n\n// Neues Modul (modern)\nconst axios = require('axios');\n\nasync function fetchUserDataModern(userId) {\n  const response = await axios.get(`https://api.example.com/users/${userId}`);\n  return response.data;\n}\n\n// Zwischenschicht (Fassade)\nasync function getUserData(userId) {\n  // Zuerst die neue API versuchen, bei Fehler auf die alte zurückfallen\n  try {\n    return await fetchUserDataModern(userId);\n  } catch (error) {\n    console.warn('Fallback auf Legacy-API                

Blogs

Buchempfehlungen