Warum Clean Code wichtig ist
Wir schreiben Code nicht nur für Computer, sondern auch für Menschen. Code wird viel häufiger gelesen als geschrieben, deshalb ist Lesbarkeit entscheidend. In diesem Post teile ich 5 Prinzipien, die ich täglich anwende, um meinen Code sauberer zu machen.
1. Aussagekräftige Namen verwenden
Schlecht:
function calc(x, y, z) {
return x * y * z;
}
const d = new Date();
const t = 86400;
Besser:
function calculateShippingCost(weight, distance, rate) {
return weight * distance * rate;
}
const currentDate = new Date();
const SECONDS_PER_DAY = 86400;
Warum das wichtig ist:
- Der Code dokumentiert sich selbst
- Keine Kommentare nötig, um zu verstehen, was passiert
- Neue Teammitglieder verstehen den Code sofort
2. Funktionen sollten eine Sache tun
Schlecht:
function processUser(user) {
// Validierung
if (!user.email || !user.name) {
throw new Error('Invalid user');
}
// Transformation
user.email = user.email.toLowerCase();
user.name = user.name.trim();
// Speichern in DB
database.save(user);
// Email senden
emailService.sendWelcomeEmail(user.email);
// Logging
logger.info(`User ${user.id} processed`);
return user;
}
Besser:
function processUser(user) {
const validatedUser = validateUser(user);
const normalizedUser = normalizeUser(validatedUser);
const savedUser = saveUser(normalizedUser);
sendWelcomeEmail(savedUser);
logUserCreation(savedUser);
return savedUser;
}
function validateUser(user) {
if (!user.email || !user.name) {
throw new Error('Invalid user');
}
return user;
}
function normalizeUser(user) {
return {
...user,
email: user.email.toLowerCase(),
name: user.name.trim()
};
}
function saveUser(user) {
return database.save(user);
}
function sendWelcomeEmail(user) {
emailService.sendWelcomeEmail(user.email);
}
function logUserCreation(user) {
logger.info(`User ${user.id} processed`);
}
Vorteile:
- Jede Funktion ist testbar
- Wiederverwendbar
- Einfacher zu debuggen
- Leichter zu verstehen
3. Vermeide Magic Numbers und Magic Strings
Schlecht:
if (user.status === 1) {
// Was bedeutet 1?
}
setTimeout(() => {
retry();
}, 5000); // Warum 5000?
if (user.age > 18) {
// Hardcoded business logic
}
Besser:
const UserStatus = {
ACTIVE: 1,
INACTIVE: 2,
SUSPENDED: 3
};
const RETRY_DELAY_MS = 5000;
const LEGAL_AGE = 18;
if (user.status === UserStatus.ACTIVE) {
// Klar, was hier passiert
}
setTimeout(() => {
retry();
}, RETRY_DELAY_MS);
if (user.age > LEGAL_AGE) {
//Businesslogik ist dokumentiert
}
Warum:
- Werte können zentral geändert werden
- Code ist selbsterklärend
- Weniger Fehler bei Änderungen
4. Early Returns statt verschachtelte If-Statements
Schlecht:
function processPayment(payment) {
if (payment) {
if (payment.amount > 0) {
if (payment.method === 'credit_card') {
if (payment.cardNumber) {
// Eigentliche Logik erst hier
return chargeCard(payment);
} else {
throw new Error('No card number');
}
} else {
throw new Error('Invalid payment method');
}
} else {
throw new Error('Invalid amount');
}
} else {
throw new Error('No payment provided');
}
}
Besser:
function processPayment(payment) {
if (!payment) {
throw new Error('No payment provided');
}
if (payment.amount <= 0) {
throw new Error('Invalid amount');
}
if (payment.method !== 'credit_card') {
throw new Error('Invalid payment method');
}
if (!payment.cardNumber) {
throw new Error('No card number');
}
return chargeCard(payment);
}
Vorteile:
- Weniger Verschachtelung = leichter zu lesen
- Fehlerbehandlung am Anfang
- Happy Path ist klar erkennbar
5. DRY - Don’t Repeat Yourself
Schlecht:
// User erstellen
const newUser = {
id: generateId(),
createdAt: new Date(),
updatedAt: new Date(),
version: 1,
...userData
};
// Product erstellen
const newProduct = {
id: generateId(),
createdAt: new Date(),
updatedAt: new Date(),
version: 1,
...productData
};
// Order erstellen
const newOrder = {
id: generateId(),
createdAt: new Date(),
updatedAt: new Date(),
version: 1,
...orderData
};
Besser:
function createEntity(data) {
return {
id: generateId(),
createdAt: new Date(),
updatedAt: new Date(),
version: 1,
...data
};
}
const newUser = createEntity(userData);
const newProduct = createEntity(productData);
const newOrder = createEntity(orderData);
Oder noch besser mit TypeScript:
function createEntity<T>(data: T): T & BaseEntity {
return {
id: generateId(),
createdAt: new Date(),
updatedAt: new Date(),
version: 1,
...data
};
}
Bonus: Kommentare richtig einsetzen
// ❌ Schlechte Kommentare
// Inkrementiere i
i++;
// Loop über alle Users
users.forEach(user => {
// ...
});
// ✅ Gute Kommentare
// HACK: Temporärer Workaround für Bug #1234
// TODO: Refactor this when API v2 is available
/**
* Berechnet den Rabatt basierend auf komplexer Businesslogik:
* - VIP Kunden: 20%
* - Bestellwert > 100€: 10%
* - Beide Bedingungen: 25%
*/
function calculateDiscount(customer, orderValue) {
// Implementation
}
Fazit
Clean Code ist keine Raketenwissenschaft, sondern gesunder Menschenverstand:
- Schreibe für Menschen, nicht für Maschinen
- Halte Funktionen klein und fokussiert
- Benenne Dinge so, dass Kommentare unnötig werden
- Reduziere Komplexität wo möglich
- Eliminiere Duplikation
Dein zukünftiges Ich (und deine Kollegen) werden es dir danken! 🚀
Weiterführende Ressourcen
Was sind deine liebsten Clean Code Praktiken? Lass es mich wissen!