Clean Code in Python: Code für Menschen
Code wird viel öfter gelesen als geschrieben. Dieser eine Satz ist der ganze Grund, warum mir Clean Code wichtig ist. Wenn ein Stück Code nicht auf den ersten Blick verständlich ist, ist es noch nicht fertig. Im besten Fall liest sich Code fast wie natürliche Sprache.
Ich habe das in ein Skill verwandelt, das ich in meinen eigenen Projekten nutze. Hier sind die Regeln, die wirklich zählen, in der Reihenfolge, in der ich sie anwende.
Selbst-erklärender Code
Der Code sollte keine Kommentare brauchen, um zu erklären, was passiert. Kommentare erklären nur warum etwas getan wird. Wenn du einen Kommentar schreibst, der den Code beschreibt, ist der Code das Problem, nicht der Kommentar.
# ❌ Beschreibt was (offensichtlich aus dem Code) for item in items: item += 1 # ✅ Erklärt warum # Verarbeite die ältesten User zuerst, um langjährige Kunden zu priorisieren users.sort(key=lambda u: u.created_at).forEach(process)
Kein auskommentierter Code
Auskommentierter Code wird entfernt. Die Versionshistorie ist der richtige Ort für alte Versionen. Toten Code in einem Kommentar zu lassen, erzeugt nur Rauschen und Verwirrung für die nächste Person.
Naming ist das schwerste Problem
Ein Name muss diese Fragen beantworten: warum existiert das Objekt, was tut es, wie wird es genutzt, wo findet man es und was hält es? Wenn ein Name einen Kommentar braucht, um ihn zu erklären, ist er schlecht gewählt.
| Regel | Schlecht | Gut |
|---|---|---|
| Zweck zeigen | response | response_time_seconds |
| Aussprechbar | hw_chn_5_lab | hardware_channel_5_label |
| Keine Abkürzungen | s/d | source / destination |
| Einheiten nutzen | Time | delay_time_ms |
| Magische Zahlen | 42 | MAX_INDEX |
Eine Funktion, eine Aufgabe
Jede Funktion macht genau eine Sache. Wenn du "und" brauchst, um zu beschreiben, was eine Funktion tut, macht sie zu viel. Teile sie auf.
# ❌ Macht zu viel def process_user_and_send_email(user): # validate user # save to database # send welcome email # ✅ Single Responsibility def validate_user(user): ... def save_user(user): ... def send_welcome_email(user): ...
Gleiche Abstraktionsebene
Eine Funktion arbeitet auf genau einer Abstraktionsebene. Der Code sollte wie ein Algorithmus von oben nach unten lesbar sein. Wenn du hohe Absicht mit niedrigen Details mischst, teile die Funktion.
Keine Seiteneffekte
Eine Funktion, die prüft, ob eine Datei existiert, erstellt nicht auch die Datei. Eine Funktion hat einen Job. Versteckte Aufgaben sind, wie Bugs entstehen.
Die Boy-Scout-Regel
Hinterlasse den Code sauberer, als du ihn vorgefunden hast. Lösche veraltete Kommentare, entferne auskommentierten Code, vereinfache duplizierten Code, ergänze fehlende Funktionsbeschreibungen. Kleine Verbesserungen summieren sich.
Don't repeat yourself
Identischer Code wird einmal geschrieben und wiederverwendet. Copy-Paste ist die häufigste und folgenreichste Verletzung. Aber achte auch auf die andere Seite: zu viele Parameter sind auch gefährlich. Maximal drei bis vier pro Funktion, sonst kapsle in einem Dataclass.
Nicht alles braucht eine Klasse
Kleine Klassen sind kontraproduktiv. Nutze eine Funktion, wenn Code mehrfach aufgerufen wird, eine Klasse, wenn mehrere Variablen und Funktionen logisch zusammengehören, ein Modul, wenn Klassen entkoppelt werden können. Logisches Urteilsvermögen schlägt Dogma.
Der Nutzen
Diese Regeln sind nicht dafür da, hübsch zu sein. Es geht um kognitive Last. Eine Codebase, die sich wie natürliche Sprache liest, ist schneller zu debuggen, schneller zu erweitern und schneller zu übergeben. Dein zukünftiges Ich wird dir danken, und auch die Person, die deinen Code erbt.
Willst du sehen, wie ich meinen docs/-Ordner tatsächlich organisiere? Das ist der nächste Post.