Aikido

Wie man Funktionen kurz und bündig hält: Schreiben von wartbarem Code

Lesbarkeit

Regel

Behalten Sie Funktionen prägnant.
Lange Funktionen sind schwierig zu verstehen, testen, und warten.

Unterstützte Sprachen: 45+

Einführung

Funktionen, die sich über Hunderte von Zeilen erstrecken, vermischen mehrere Zuständigkeiten und machen es schwer zu verstehen, was die Funktion tut, ohne jede Zeile zu lesen. Lange Funktionen behandeln in der Regel mehrere Aspekte wie Validierung, Geschäftslogik, Datenumwandlung und Fehlerbehandlung an einer Stelle. Dies verstößt gegen das Prinzip der einzigen Verantwortung und führt zu Code, der schwer zu testen, zu debuggen und zu ändern ist, ohne das bestehende Verhalten zu verändern.

Warum das wichtig ist

Wartbarkeit des Codes: Bei langen Funktionen müssen die Entwickler mehr Kontext im Kopf haben, um das Verhalten zu verstehen. Die Änderung eines Teils birgt das Risiko, einen anderen Teil zu zerstören, da die gesamte Logik miteinander verwoben ist. Fehlerbehebungen werden riskant, da unbeabsichtigte Nebenwirkungen schwer vorhersehbar sind.

Komplexität der Tests: Das Testen einer Funktion mit 200 Zeilen bedeutet, dass alle möglichen Codepfade in einem Test abgedeckt werden müssen, was eine komplexe Einrichtung und zahlreiche Testfälle erfordert. Kleinere Funktionen können unabhängig voneinander mit fokussierten Unit-Tests getestet werden, wodurch Test-Suites schneller und zuverlässiger werden.

Code-Beispiele

❌ Nicht konform:

async function processOrder(orderData) {
    if (!orderData.items?.length) throw new Error('Items required');
    if (!orderData.customer?.email) throw new Error('Email required');
    const subtotal = orderData.items.reduce((sum, item) => 
        sum + (item.price * item.quantity), 0);
    const tax = subtotal * 0.08;
    const total = subtotal + tax + (subtotal > 50 ? 0 : 9.99);
    const order = await db.orders.create({
        customerId: orderData.customer.id,
        total: total
    });
    await emailService.send(orderData.customer.email, `Order #${order.id}`);
    await inventory.reserve(orderData.items);
    return order;
}

Warum es falsch ist: Diese Funktion behandelt Validierung, Berechnung, Datenbankoperationen, E-Mail und Inventar. Testen erfordert das Mocking aller Abhängigkeiten. Jede Änderung der Steuerlogik oder der Validierung erfordert die Änderung dieser gesamten Funktion.

✅ Konform:

function validateOrder(orderData) {
    if (!orderData.items?.length) throw new Error('Items required');
    if (!orderData.customer?.email) throw new Error('Email required');
}

function calculateTotal(items) {
    const subtotal = items.reduce((sum, item) => 
        sum + (item.price * item.quantity), 0);
    return subtotal + (subtotal * 0.08) + (subtotal > 50 ? 0 : 9.99);
}

async function createOrder(customerId, total) {
    return await db.orders.create({ customerId, total });
}

async function processOrder(orderData) {
    validateOrder(orderData);
    const total = calculateTotal(orderData.items);
    const order = await createOrder(orderData.customer.id, total);
    
    // Non-critical operations in background
    emailService.send(orderData.customer.email, `Order #${order.id}`).catch(console.error);
    
    return order;
}

Warum das wichtig ist: Jede Funktion hat eine klare Verantwortung. validateOrder() und berechneGesamt() können unabhängig ohne Mocks getestet werden. erstellenAuftrag() isoliert die Datenbanklogik. E-Mail- und Inventarvorgänge blockieren die Auftragserstellung nicht, und Fehler werden separat behandelt.

Schlussfolgerung

Entwickeln Sie APIs durch additive Änderungen weiter: Fügen Sie neue Felder, neue Endpunkte und optionale Parameter hinzu. Wenn einschneidende Änderungen unvermeidlich sind, verwenden Sie die API-Versionierung, um alte und neue Versionen gleichzeitig auszuführen. Veralten Sie alte Felder mit klaren Zeitplänen und Migrationsleitfäden, bevor Sie sie entfernen.

FAQs

Haben Sie Fragen?

Wie kann ich lange Funktionen aufschlüsseln?

Identifizieren Sie unterschiedliche Verantwortlichkeiten innerhalb der Funktion. Extrahieren Sie die Validierung in separate Funktionen. Ziehen Sie Berechnungen in reine Funktionen aus. Verschieben Sie E/A-Operationen (Datenbank, API-Aufrufe) in eigene Funktionen. Jede extrahierte Funktion sollte einen klaren, einzigen Zweck mit einem beschreibenden Namen haben.

Verursachen kleine Funktionen nicht zusätzlichen Aufwand und beeinträchtigen die Leistung?

Moderne Compiler und Interpreter binden kleine Funktionen ein und eliminieren so den Aufruf-Overhead. Die Auswirkungen auf die Leistung sind im Vergleich zu den Vorteilen bei der Wartung vernachlässigbar. Profile vor der Optimierung. Lesbarer Code lässt sich später leichter optimieren, wenn Sie tatsächliche Engpässe identifizieren.

Was ist mit Funktionen mit vielen aufeinanderfolgenden Schritten?

Sequentielle Schritte legen einen Arbeitsablauf nahe, der in kleinere Funktionen unterteilt werden kann. Erstellen Sie Hilfsfunktionen für jeden Schritt und rufen Sie diese nacheinander von einer Koordinatorfunktion aus auf. Dadurch wird der Arbeitsablauf lesbar und jeder Schritt kann unabhängig getestet werden.

Wie gehe ich mit Funktionen um, die nach der Extraktion viele Parameter benötigen?

Übergeben Sie Objekte, die zusammengehörige Parameter enthalten, statt langer Parameterlisten. Oder überlegen Sie, ob extrahierte Funktionen Methoden für eine Klasse sein sollten, die einen gemeinsamen Zustand enthält. Wenn eine Funktion mehr als 6 Parameter benötigt, könnte dies auf eine schlechte Abstraktion oder fehlende Datenstrukturen hinweisen.

Sollte ich Funktionen extrahieren, auch wenn sie nur einmal aufgerufen werden?

Ja, wenn die Extraktion die Lesbarkeit verbessert. Eine gut benannte extrahierte Funktion dokumentiert besser als Kommentare, was ein Codeblock tut. Eine einmalige Extraktion ist wertvoll, wenn sie komplexe Logik verdeutlicht oder Verschachtelungsebenen in der übergeordneten Funktion reduziert.

Starten Sie kostenlos

Sichern Sie Ihren Code, Cloud und die Laufzeit in einem zentralen System.
Finden und beheben Sie Schwachstellen schnell  automatisch.

Keine Kreditkarte erforderlich | Scanergebnisse in 32 Sekunden.