Aikido

FreeCodeCamp Einblicke in die Code-Qualität: Regeln, die jede Code-Basis verbessern können

Einführung

FreeCodeCamp ist mehr als eine Lernplattform; es ist eine große Open-Source-Codebasis mit Tausenden von Mitwirkenden und Millionen von Zeilen JavaScript und TypeScript. Die Verwaltung eines so komplexen Projekts erfordert konsistente Architekturmuster, strenge Namenskonventionen und gründliche Tests, um Regressionen zu vermeiden und die Zuverlässigkeit zu erhalten.

In diesem Artikel stellen wir die wirkungsvollsten Code-Review-Regeln aus dem FreeCodeCamp vor. Jede Regel zeigt, wie ein sorgfältiges Design, ein konsistenter Datenfluss und eine robuste Fehlerbehandlung dazu beitragen können, dass große Projekte organisiert bleiben und das Risiko von subtilen Fehlern im Laufe der Zeit reduziert wird.

Die Herausforderungen

Die Aufrechterhaltung der Codequalität in FreeCodeCamp ist aufgrund der großen JavaScript- und TypeScript-Codebasis und Tausenden von Mitwirkenden eine Herausforderung. Die Sicherstellung konsistenter Muster, vorhersehbarer Datenflüsse und zuverlässiger Funktionen erfordert strukturierte Überprüfungsregeln und automatisierte Kontrollen.

Zu den größten Herausforderungen gehören inkonsistente Codierungsmuster, eng gekoppelte Legacy-Module, ungleichmäßige Testabdeckung, abweichende Dokumentation und ein hohes Aufkommen an Pull-Requests.

Klare Standards, automatisierte Validierung und sorgfältige Codeüberprüfung tragen dazu bei, dass die Codebasis wartbar, stabil und skalierbar bleibt, wenn das Projekt wächst.

Warum diese Regeln wichtig sind

Konsistente Regeln für die Codeüberprüfung verbessern die Wartbarkeit, indem sie eine einheitliche Modulstruktur, Namenskonventionen und vorhersehbare Datenflüsse erzwingen, wodurch Tests zuverlässiger und Abhängigkeiten leichter zu verfolgen sind.

Außerdem erhöhen sie die Sicherheit durch Eingabevalidierung, Fehlerbehandlung und kontrollierte Seiteneffekte und beschleunigen die Einarbeitung neuer Mitarbeiter, indem sie ihnen helfen, die Zuständigkeiten und Integrationspunkte der Module schnell zu verstehen.

Überbrückungskontext zu diesen Regeln

Diese Regeln werden aus dem Repository und den Pull-Requests von FreeCodeCamp extrahiert und spiegeln wiederkehrende Probleme wie unklaren Datenfluss, fehlende Fehlerbehandlung und inkonsistente Tests wider, die sich auf Stabilität und Wartbarkeit auswirken.

Jede Regel hebt einen konkreten Fallstrick hervor, erklärt dessen Auswirkungen auf Leistung, Klarheit oder Zuverlässigkeit und enthält ❌ nicht konforme vs. ✅ konforme JavaScript- oder TypeScript-Beispiele.

1. Vermeiden Sie die übermäßige Verwendung eines Typs in TypeScript

Vermeiden Sie die Verwendung beliebiger Typen in TypeScript. Definieren Sie immer genaue und explizite Typen für Variablen, Funktionsparameter und Rückgabewerte, um Typsicherheit zu gewährleisten und Laufzeitfehler zu vermeiden.

❌ Nicht konform:

let userData: any = fetchUserData();

✅ Konform:

interface UserData {
  id: string;
  name: string;
  email: string;
}

let userData: UserData = fetchUserData();

Warum dies wichtig ist: Durch die Verwendung von any wird die Typüberprüfung von TypeScript deaktiviert, wodurch Laufzeitfehler auftreten können und die Wartbarkeit und Zuverlässigkeit des Codes verringert wird. Explizite Typen machen den Code sicherer und für andere Entwickler leichter zu verstehen.

2. Bevorzugen Sie beschreibende Variablennamen gegenüber Abkürzungen

Verwenden Sie stets eindeutige und beschreibende Variablennamen. Vermeiden Sie Abkürzungen oder kryptische Namen, die die Bedeutung des Codes verschleiern.

❌ Nicht konform:

const usr = getUser();

✅ Konform:

const Benutzer = getUser();

Warum das wichtig ist: Beschreibende Variablennamen machen den Code leichter lesbar, verständlich und wartbar. Schlechte Benennungen können Entwickler verwirren und das Risiko von Fehlern erhöhen.

3. Vermeiden Sie tief verschachtelte Schleifen oder Konditionale

Refaktorieren Sie den Code, um tiefe Verschachtelungen in Schleifen oder Bedingungen zu vermeiden. Verwenden Sie frühe Rückgaben oder Hilfsfunktionen, um die Logik zu vereinfachen.

❌ Nicht konform:

if (Benutzer) {
  if (user.isActive) {
    if (user.hasPermission) {
      // Aktion ausführen
 }
  }
}

✅ Konform:

if (!user) return;
if (!user.isActive) return;
if (!user.hasPermission) return;

// Aktion ausführen
processUserAction(user);

Warum das wichtig ist: Tief verschachtelte Logik ist schwer zu verfolgen, zu pflegen und zu testen. Sie erschwert das Schreiben von Unit-Tests, insbesondere bei negativen Fällen und frühen Fehlern. Die Verflachung des Kontrollflusses mit frühen Rückgaben macht den Code leichter nachvollziehbar, verbessert die Testabdeckung und verringert die Wahrscheinlichkeit von versteckten Edge-Case-Fehlern.

4. Sicherstellung einer einheitlichen Fehlerbehandlung in der gesamten Codebasis

Implementieren Sie stets eine konsistente Fehlerbehandlung. Verwenden Sie zentralisierte Fehlerfunktionen oder standardisierte Muster, um Ausnahmen einheitlich zu behandeln.

❌ Nicht konform:

try {
  // Some code
} catch (e) {
  console.error(e);
}

✅ Konform:

try {
  // Some code
} catch (error) {
  logError(error);
  throw new CustomError('An error occurred', { cause: error });
}

Warum dies wichtig ist: Eine konsistente Fehlerbehandlung erleichtert das Debugging, verhindert unerwartetes Verhalten und gewährleistet die Zuverlässigkeit der gesamten Anwendung.

5. Vermeiden Sie das Hardcoding von Konfigurationswerten

Geben Sie keine umgebungsspezifischen Werte wie URLs, Ports oder secrets fest ein. Verwenden Sie immer Konfigurationsdateien oder Umgebungsvariablen.

❌ Nicht konform:

const apiUrl = 'https://api.example.com';

✅ Konform:

const apiUrl = process.env.API_URL;

Warum das wichtig ist: Fest kodierte Werte verringern die Flexibilität, machen den Code weniger sicher und erschweren die Bereitstellung in verschiedenen Umgebungen. Die Verwendung von Konfigurationen gewährleistet Wartungsfreundlichkeit und Sicherheit.

6. Konzentration der Funktionen auf eine einzige Aufgabe

Stellen Sie sicher, dass jede Funktion eine einzige, klar definierte Aufgabe ausführt. Vermeiden Sie Funktionen, die mehrere Aufgaben übernehmen, da dies zu Verwirrung und Schwierigkeiten bei der Wartung führen kann.

❌ Nicht konform:

function processUserData(user) {
  const validatedUser = validateUser(user);
  saveUserToDatabase(validatedUser);
  sendWelcomeEmail(validatedUser);
}

✅ Konform:

Funktion validateUser(user) {
  // Validierungslogik
}

function saveUserToDatabase(user) {
  // Speicherlogik
}

function sendWelcomeEmail(user) {
  // Logik für den E-Mail-Versand
}

Warum das wichtig ist: Funktionen mit einer einzigen Zuständigkeit sind einfacher zu testen, zu debuggen und zu warten. Sie fördern die Wiederverwendung von Code und verbessern die Lesbarkeit.

7. Vermeiden Sie die Verwendung magischer Zahlen

Ersetzen Sie magische Zahlen durch benannte Konstanten, um die Übersichtlichkeit und Wartbarkeit des Codes zu verbessern.

❌ Nicht konform:

const Fläche = Länge * 3.14159 * Radius * Radius;

✅ Konform:

const PI = 3.14159;
const Fläche = Länge * PI * Radius * Radius;

Warum das wichtig ist: Magische Zahlen können die Bedeutung des Codes verschleiern und zukünftige Änderungen fehleranfällig machen. Benannte Konstanten bieten einen Kontext und verringern das Risiko der Einführung von Fehlern.

8. Minimierung der Verwendung von globalen Variablen

Beschränken Sie die Verwendung globaler Variablen, um Abhängigkeiten und potenzielle Konflikte in der Codebasis zu reduzieren.

❌ Nicht konform:

let user = { name: 'Alice' };

function greetUser() {
  console.log(`Hello, ${user.name}`);
}

✅ Konform:

function greetUser(user) {
  console.log(`Hello, ${user.name}`);
}

const user = { name: 'Alice' };
greetUser(user);

Warum das wichtig ist: Globale Variablen können zu versteckten Abhängigkeiten und unvorhersehbaren Nebeneffekten führen. Sie erschweren es, nachzuvollziehen, woher die Daten kommen oder wie sie sich in der Codebasis ändern. Durch die explizite Übergabe von Daten über Funktionsparameter bleibt der Datenfluss klar und kontrolliert, was die Modularität, das Debugging und die langfristige Wartbarkeit verbessert.

9. Verwendung von Schablonenliteralen für die Stringverkettung

Bevorzugen Sie Schablonenliterale gegenüber der Stringverkettung, um die Lesbarkeit und Leistung zu verbessern.

❌ Nicht konform:

const message = 'Hallo, ' + user.name + '! Du hast ' + user.notifications + ' neue Benachrichtigungen.';

✅ Konform:

const message = `Hello, ${user.name}! You have ${user.notifications} new notifications.`;

Warum dies wichtig ist: Schablonenliterale bieten eine sauberere Syntax und verbessern die Lesbarkeit, insbesondere bei komplexen Zeichenketten oder mehrzeiligen Inhalten.

10. Implementierung einer angemessenen Eingabevalidierung

Überprüfen Sie immer die Benutzereingaben, um zu verhindern, dass ungültige Daten in das System gelangen, und um die Sicherheit zu erhöhen.

❌ Nicht konform:

Funktion processUserInput(input) {
  // Verarbeitungslogik
}

✅ Konform:

function validateInput(input) {
  if (typeof input !== 'string' || input.trim() === '') {
    throw new Error('Invalid input');
  }
}

function processUserInput(input) {
  validateInput(input);
  // processing logic
}

Warum dies wichtig ist: Die Validierung von Eingaben ist entscheidend für die Vermeidung von Fehlern, die Gewährleistung der Datenintegrität und den Schutz vor Sicherheitslücken wie Injektionsangriffen.

11. Eine logische Änderung pro Pull-Request beibehalten

Stellen Sie sicher, dass jeder Pull Request (PR) eine einzelne logische Änderung oder Funktion implementiert; vermeiden Sie die Kombination von nicht zusammenhängenden Korrekturen, Refactors und Funktionserweiterungen in einem PR.

❌ Nicht konform:

# "Fix login + update homepage"
--- auth.js
+ if (!user) throw new Error('User not found');

--- HomePage.js
- <button>Start</button>
+ <button>Begin Journey</button>

✅ Konform: (diff)

# PR 1: Fix login validation
+ if (!user) throw new Error('User not found');

# PR 2: Update homepage button
+ <button>Begin Journey</button>

Warum das wichtig ist: Kleine, fokussierte PRs vereinfachen die Codeüberprüfung, verringern das Risiko unbeabsichtigter Nebeneffekte und beschleunigen die Merge-Zyklen. KI-Tools können erkennen, wenn sich nicht verwandte Dateien, Module oder Domänen im selben PR ändern - etwas, das Linters nicht feststellen können.

12. Benennung von APIs und Diensten nach Domänen

Benennen Sie APIs, Dienste und Module entsprechend der Geschäftsdomäne (z. B. challengeService.createSubmission und nicht handler1.doIt); die Namen sollten Entität und Aktion klar widerspiegeln.

❌ Nicht konform:

// backend/services/handler.js
export async function doIt(data) {
  return await process(data);
}

// routes/index.js
router.post('/submit', handler.doIt);

✅ Konform:

// backend/services/challengeService.js
export async function createSubmission({ userId, challengeId, answer }) {
  return await challengeModel.create({ userId, challengeId, answer });
}

// routes/challenges.js
router.post('/submissions', challengeService.createSubmission);

Warum dies wichtig ist: Eine bereichsbezogene Benennung sorgt für eine Selbstdokumentation des Codes, fördert die Klarheit für neue Mitarbeiter und stimmt mit der Geschäftslogik überein. Nur eine KI, die den semantischen Kontext (Entitätsnamen, Dienstebenen) kennt, kann falsch ausgerichtete oder generische Benennungen über Module hinweg erkennen.

13. Sicherstellen, dass die Tests Fehlfunktionen und Randfälle abdecken

Schreiben Sie Tests nicht nur für den "glücklichen Weg", sondern auch für Fehlerbedingungen, Randfälle und Grenzwerte; stellen Sie sicher, dass jedes kritische Modul sowohl positive als auch negative Tests hat.

❌ Nicht konform:

describe('login', () => {
  it('should succeed with correct credentials', async () => { … });
});

✅ Konform:

describe('login', () => {
  it('should succeed with correct credentials', async () => { … });
  it('should fail with incorrect password', async () => { … });
  it('should lock account after 5 failed attempts', async () => { … });
});

Warum das wichtig ist: Geschäftskritische Logik bricht oft ab, wenn Randfälle wie ungültige Eingaben, Zeitüberschreitungen oder fehlgeschlagene Anmeldungen übersehen werden. Das Testen von Erfolgs- und Fehlerpfaden stellt sicher, dass sich die Anwendung unter realen Bedingungen zuverlässig verhält, und verhindert Regressionen, die später nur schwer zu erkennen sind.

14. Vermeiden Sie die Vermischung von Schichten: UI-Komponenten sollten keine Geschäftslogik ausführen

Halten Sie UI-Komponenten (React, Frontend) frei von Geschäftslogik und Datenbank-/Dienstaufrufen; delegieren Sie diese Aufgaben an dedizierte Dienste oder Hooks.

❌ Nicht konform:

// FreeCodeCamp-style
function CurriculumCard({ user, challenge }) {
  if (!user.completed.includes(challenge.id)) {
    saveCompletion(user.id, challenge.id);
  }
  return <Card>{challenge.title}</Card>;
}

✅ Konform:

function CurriculumCard({ user, challenge }) {
  return <Card>{challenge.title}</Card>;
}

// In service:
async function markChallengeComplete(userId, challengeId) {
  await completionService.create({ userId, challengeId });
}

Warum das wichtig ist: Die Vermischung von Geschäftslogik mit UI-Komponenten verwischt die Grenzen zwischen den Schichten und macht zukünftige Änderungen riskant. Außerdem zwingt es die Front-End-Entwickler, die Back-End-Logik zu verstehen und verlangsamt die Zusammenarbeit. Durch die Trennung der Zuständigkeiten wird sichergestellt, dass sich jede Schicht unabhängig weiterentwickeln kann, und das Risiko, beim Refactoring subtile Fehler einzuführen, wird verringert.

Schlussfolgerung

Durch die Analyse des FreeCodeCamp-Repositorys haben wir praktische Code-Review-Regeln herausgearbeitet, die helfen, die große Codebasis organisiert, lesbar und wartbar zu halten. Diese 20 Regeln spiegeln reale Praktiken aus jahrelangen Beiträgen wider, auch wenn sie nicht durch ein automatisiertes Tool durchgesetzt werden.

Die Anwendung dieser Lektionen in Ihren eigenen Projekten kann die Klarheit verbessern, Fehler reduzieren und die Zusammenarbeit reibungsloser gestalten. Sie bieten eine solide Grundlage für die sichere Skalierung Ihres Codes und stellen sicher, dass der Code bei wachsendem Projekt zuverlässig und einfach zu handhaben bleibt.

Bei der Codeüberprüfung geht es um mehr als die Überprüfung der Syntax. Es geht darum, die Qualität und Integrität Ihres Codes im Laufe der Zeit zu erhalten. Von einem ausgereiften Open-Source-Projekt wie FreeCodeCamp zu lernen, gibt Entwicklern konkrete Anleitungen zur Verbesserung jeder Codebasis.

FAQs

Haben Sie Fragen?

Wie wirken sich diese Regeln auf den Datenfluss und die Modulgrenzen in FreeCodeCamp aus?

Sie erzwingen eine konsistente Ein-/Ausgabebehandlung, ein vorhersehbares Funktionsverhalten und eine klare Trennung von Belangen, wodurch die Kopplung reduziert wird und die Module einfacher zu refaktorisieren und zu testen sind.

Wie verbessern diese Regeln die Testabdeckung und Zuverlässigkeit?

Indem sie Unit- und Integrationstests für Randfälle, Fehlerbehandlung und kritische Geschäftslogik vorschreiben, stellen sie sicher, dass Regressionen frühzeitig erkannt werden und automatisierte Tests das Systemverhalten genau wiedergeben.

Wie helfen diese Regeln bei der Verwaltung von Legacy-Code?

Sie bieten Muster für das Refactoring von eng gekoppelten oder veralteten Modulen unter Wahrung der Abwärtskompatibilität und Minimierung des Risikos von Regressionen.

Können diese Regeln Sicherheitsprobleme in FreeCodeCamp verhindern?

Ja. Sie erzwingen eine Eingabevalidierung, eine sichere Datenverarbeitung und eine konsistente Fehlerbehandlung, wodurch Risiken wie Injektionsangriffe, unbehandelte Ausnahmen und Datenlecks verringert werden.

Wie können neue Beitragszahler von diesen Regeln profitieren?

Klare Modulzuständigkeiten, einheitliche Namensgebung und standardisierte Fehlerbehandlung helfen neuen Entwicklern, die Architektur schnell zu verstehen und sicher zu integrieren, ohne Regressionen einzuführen.

Wie wurden diese Regeln von FreeCodeCamp abgeleitet?

Sie wurden aus der Analyse von Pull-Requests, Code-Änderungen, Diskussionssträngen und wiederkehrenden Mustern extrahiert, die sich auf die Wartbarkeit, Lesbarkeit und Stabilität der Codebasis auswirken.

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.