Home

02 Code-Qualität in der Praxis: Von funktionierendem Code zu professioneller Software

lecture code-quality pep8 ruff linting formatting best-practices python

1. Einleitung: Wenn funktionierender Code nicht ausreicht

Sie haben Ihre Road Profile Viewer Anwendung gebaut. Die Visualisierung ist schön, der Kamerastrahl schneidet perfekt mit dem Straßenprofil, und wenn Sie auf “Run” klicken, funktioniert alles. Herzlichen Glückwunsch! 🎉

Aber dann… pushen Sie Ihren Code auf GitHub, öffnen einen Pull Request, und automatisierte Checks schlagen fehl. ❌

$ git push origin feature/road-profile-viewer

Running automated checks...
❌ Ruff check: 14 errors found
❌ Format check: 8 files need formatting
❌ Type check: 6 type errors detected

Pull request blocked - fix issues before merging

Was ist passiert? Ihr Code funktioniert, aber er erfüllt nicht die professionellen Qualitätsstandards. Das ist die Lücke zwischen Hobby-Code und produktionsreifer Software.

Diese Vorlesung handelt davon, diese Lücke zu verstehen und zu schließen—nicht mit mühsamen manuellen Reviews, sondern mit automatisierten Tools, die Qualitätskontrolle mühelos und konsistent machen.


2. Lernziele

Am Ende dieser Vorlesung werden Sie:

  1. Den Unterschied verstehen zwischen Code, der funktioniert, und Code, der professionellen Standards entspricht
  2. Häufige Code-Qualitätsprobleme erkennen anhand realer Beispiele aus dem Road Profile Viewer Projekt
  3. Sich überschneidende Qualitätskonzepte unterscheiden: Style Guides, Linting, Formatting, Type Hints und Type Checking—verstehen, was jedes davon tut und wie sie sich ergänzen
  4. Über Pythons Style Guide (PEP 8) lernen und warum er für professionelle Entwicklung wichtig ist
  5. Moderne Qualitäts-Tools beherrschen:
    • Ruff: Der All-in-One-Linter und Formatter, der PEP 8 durchsetzt und Bugs findet
    • Pyright: Der Type Checker, der Type Annotations validiert und typbezogene Fehler verhindert
  6. Verstehen, warum wir sowohl Ruff ALS AUCH Pyright brauchen: Sie arbeiten auf verschiedenen Ebenen (Style/Bugs vs. Type Safety)
  7. Automatisierte Checks anwenden, um Probleme vor menschlicher Review zu finden
  8. Qualität von Anfang an in Ihren Workflow einbauen, nicht als nachträglichen Gedanken
  9. Den Business Case für Code-Qualität schätzen: reduzierte Kosten, schnelleres Debugging und bessere Team-Zusammenarbeit

3. Teil 1: Die Realitätsprüfung - Unser Code unter Beobachtung

Schauen wir uns echten Code aus dem Road Profile Viewer Projekt an und sehen, was automatisierte Tools finden.

3.1 Der Code, den wir geschrieben haben

Hier ist ein Ausschnitt aus main.py:

"""
Road Profile Viewer - Interactive 2D Visualization
"""

import numpy as np
from dash import Dash, html, dcc, Input, Output
import plotly.graph_objects as go
import sys,os  # Multiple imports on one line


def generate_road_profile(num_points=100,x_max=80):
    """Generate a road profile using a clothoid-like approximation."""
    x = np.linspace(0, x_max, num_points)
    x_norm = x / x_max
    
    # Clothoid approximation
    y=0.015 * x_norm**3 * x_max + 0.3 * np.sin(2 * np.pi * x_norm)
    y = y - y[0]
    
    return x,y


def HelperFunction(val):
    """Unused helper function that violates naming convention"""
    result=val*2
    return result


# Later in the code...
camera_x,camera_y = 0,2.0

marker=dict(size=12,color='red',symbol='circle')

# Add camera ray - This is a very long comment that exceeds the recommended 79 character line length limit specified in PEP8 style guide

Erster Eindruck? Sieht vernünftig aus. Es funktioniert. Aber schauen wir, was die Tools sagen…

3.2 Ausführen automatisierter Checks

$ uv run ruff check .

src/road_profile_viewer/main.py:16:1: E401 Multiple imports on one line
src/road_profile_viewer/main.py:16:8: F401 `sys` imported but unused
src/road_profile_viewer/main.py:16:12: F401 `os` imported but unused
src/road_profile_viewer/main.py:24:5: E701 Multiple statements on one line (colon)
src/road_profile_viewer/main.py:29:5: E225 Missing whitespace around operator
src/road_profile_viewer/main.py:32:12: E231 Missing whitespace after ','
src/road_profile_viewer/main.py:36:1: N802 Function name should be lowercase
src/road_profile_viewer/main.py:36:1: F841 Local variable `HelperFunction` is assigned but never used
src/road_profile_viewer/main.py:38:11: E225 Missing whitespace around operator
src/road_profile_viewer/main.py:43:14: E231 Missing whitespace after ','
src/road_profile_viewer/main.py:43:24: E231 Missing whitespace after ','
src/road_profile_viewer/main.py:45:8: E225 Missing whitespace around operator
src/road_profile_viewer/main.py:45:13: E231 Missing whitespace after ','
src/road_profile_viewer/main.py:47:1: E501 Line too long (149 > 88 characters)

Found 14 errors.

14 Fehler in Code, der perfekt funktioniert! Das ist der Unterschied zwischen “läuft auf meiner Maschine” und “erfüllt professionelle Standards.”

Diese automatisierten Tools prüfen gegen Pythons etablierte Style-Richtlinien und Best Practices. Wir werden die Grundlage dieser Standards—Pythons offiziellen Style Guide—später in dieser Vorlesung erkunden. Für jetzt, lassen Sie uns verstehen, was jedes Problem bedeutet und warum es wichtig ist.

Lassen Sie uns jedes Problem aufschlüsseln und verstehen warum es wichtig ist.


4. Teil 2: Code-Qualitätsprobleme verstehen

4.1 Problem-Kategorie 1: Import-Verstöße

4.1.1 Das Problem

import sys,os  # SCHLECHT: Mehrere Imports in einer Zeile

Was ist falsch?

Ruff meldet:

4.1.2 Warum das wichtig ist

Für Computer: Das Importieren ungenutzter Module verschwendet Speicher und Startzeit. In diesem kleinen Beispiel ist es vernachlässigbar, aber in großen Anwendungen mit Dutzenden ungenutzter Imports sammelt es sich an.

Für Menschen: Wenn Sie import sys sehen, erwarten Sie, dass der Code sys irgendwo verwendet. Ungenutzte Imports erzeugen Verwirrung:

Für Wartbarkeit: Ungenutzte Imports sammeln sich über Zeit an. Jemand fügt einen Import für einen schnellen Test hinzu, vergisst ihn zu entfernen, und er bleibt für immer. Nach ein paar Jahren hat Ihre Datei 20 Imports, aber verwendet nur 10. Viel Glück dabei herauszufinden, welche sicher entfernt werden können!

4.1.3 Die Lösung

# GUT: Getrennte Imports, nur importieren, was Sie verwenden
import numpy as np
from dash import Dash, html, dcc, Input, Output
import plotly.graph_objects as go

Python Best Practice: Imports sollten normalerweise in separaten Zeilen stehen für bessere Lesbarkeit und Wartbarkeit.

# Gut
import os
import sys

# Schlecht
import sys, os

4.2 Problem-Kategorie 2: Fehlende Leerzeichen

4.2.1 Das Problem

# SCHLECHT: Fehlende Leerzeichen überall
def generate_road_profile(num_points=100,x_max=80):
    y=0.015 * x_norm**3 * x_max
    return x,y

camera_x,camera_y = 0,2.0
result=val*2
marker=dict(size=12,color='red',symbol='circle')

Ruff meldet:

4.2.2 Warum das wichtig ist

Lesbarkeit ist König

Vergleichen Sie diese beiden Versionen:

# Schwer zu lesen - alles läuft zusammen
marker=dict(size=12,color='red',symbol='circle')

# Leicht zu lesen - klare Trennung
marker = dict(size=12, color='red', symbol='circle')

Welche können Sie schneller erfassen? Die zweite, offensichtlich.

Die Wissenschaft dahinter

Forschung in kognitiver Psychologie zeigt, dass Menschen visuelle Information in “Chunks” verarbeiten. Leerzeichen schaffen natürliche Grenzen zwischen Chunks, wodurch Code leichter zu scannen und zu verstehen ist.

Ihr Gehirn verarbeitet die zweite Version ~30% schneller, weil es nicht so hart arbeiten muss, um die Information zu segmentieren.

Reale Auswirkung

Versionskontroll-Vorteile

Konsistente Leerzeichen-Platzierung hilft, unerwünschte Diffs in zukünftigen Commits zu vermeiden. Betrachten Sie dieses Szenario:

# Inkonsistente Abstände - Änderungen erzeugen verrauschte Diffs
marker=dict(size=12,color='red')  # Erster Commit
marker = dict(size=12, color='red', symbol='circle')  # Später: Parameter hinzugefügt

Der Diff zeigt, dass sich die gesamte Zeile geändert hat, wodurch es schwer zu erkennen ist, dass nur symbol='circle' hinzugefügt wurde. Vergleichen Sie:

# Konsistente Abstände von Anfang an - saubere Diffs
marker = dict(size=12, color='red')  # Erster Commit
marker = dict(size=12, color='red', symbol='circle')  # Später: nur neuer Parameter sichtbar

Grundprinzip: Wenn alle im Team dieselben Leerzeichen-Regeln befolgen, zeigen Git-Diffs tatsächliche Logikänderungen anstelle von Stiländerungen. Dies macht Code-Reviews schneller und effektiver.

4.2.3 Die Lösung

# GUT: Richtige Abstände
def generate_road_profile(num_points=100, x_max=80):
    y = 0.015 * x_norm**3 * x_max
    return x, y

camera_x, camera_y = 0, 2.0
result = val * 2
marker = dict(size=12, color='red', symbol='circle')

Professioneller Python-Style:


4.3 Problem-Kategorie 3: Namenskonventionen

4.3.1 Das Problem

def HelperFunction(val):  # SCHLECHT: PascalCase für Funktion
    """Unused helper function"""
    result = val * 2
    return result

Ruff meldet:

4.3.2 Warum das wichtig ist

Namenskonventionen sind eine gemeinsame Sprache

In Python gibt es etablierte Namensmuster, die verschiedene Arten von Code-Elementen signalisieren:

Diese Konventionen sind in Pythons offiziellem Style Guide formalisiert, den wir später in dieser Vorlesung im Detail erkunden werden.

Wenn Sie HelperFunction() sehen, denkt Ihr Gehirn “Klasse.” Wenn Sie versuchen, es zu verwenden und entdecken, dass es eine Funktion ist, erleben Sie kognitive Dissonanz. Dieser winzige Moment der Verwirrung passiert Hunderte Male beim Lesen von Code.

Das Prinzip: Geringste Überraschung

Code sollte sich so verhalten, wie Leser es erwarten. Konventionen zu brechen erzeugt Überraschung (und Frustration).

Echtes Beispiel aus der Produktion

# Jemand hat dies in einer echten Codebasis geschrieben
DatabaseConnection = connect_to_db()  # Sieht aus wie eine Klasse!

# Später versuchte ein anderer Entwickler:
conn = DatabaseConnection()  # TypeError: 'Connection' object is not callable

Das kostete 2 Stunden Debugging, weil die Benennung Erwartungen verletzte.

4.3.3 Die Lösung

# GUT: Klare Namenskonvention
def helper_function(val):
    """Calculate double of input value."""
    result = val * 2
    return result

Aber warten Sie! Diese Funktion wird auch nie verwendet…


4.4 Problem-Kategorie 4: Toter Code

4.4.1 Das Problem

def HelperFunction(val):
    """Unused helper function"""
    result = val * 2
    return result

# Diese Funktion wird nirgendwo im Code aufgerufen

Ruff meldet:

4.4.2 Warum das wichtig ist

Toter Code ist technische Schuld

Jede Zeile Code hat Kosten:

1. Wartungskosten Jemand muss ihn warten, auch wenn er nicht verwendet wird:

2. Kognitive Kosten Zukünftige Entwickler müssen ihn lesen und verstehen:

3. Test-Kosten Toter Code wird oft trotzdem getestet:

Reales Szenario

# Sie müssen ändern, wie Koordinaten funktionieren
# Sie aktualisieren alle Koordinatenfunktionen...

def calculate_position(x, y, z):  # ✅ Aktualisiert!
    return Vector3D(x, y, z)

def transform_point(point):  # ✅ Aktualisiert!
    return point.to_3d()

def HelperFunction(val):  # ❌ Vergessen, dies zu aktualisieren!
    # Verwendet immer noch alte 2D-Logik
    return val * 2

Der tote Code bricht nichts (er wird nicht aufgerufen), aber er sitzt da wie eine tickende Zeitbombe. Wenn jemand ihn später entdeckt und versucht zu verwenden, wird er veraltete Logik verwenden.

4.4.3 Die Lösung

# GUT: Toten Code löschen
# Wenn Sie ihn später brauchen, dafür gibt es Versionskontrolle (Git)!

Schlüsselprinzip: Wenn Code nicht verwendet wird, entfernen Sie ihn. Git erinnert sich an alles.


4.5 Problem-Kategorie 5: Zeilenlänge

4.5.1 Das Problem

# Add camera ray - This is a very long comment that exceeds the recommended 79 character line length limit specified in PEP8 style guide

Ruff meldet:

4.5.2 Warum das wichtig ist

Bildschirmplatz ist begrenzt

Betrachten Sie diese Szenarien:

Szenario 1: Side-by-side Code Review

[Ihre Code-Datei     ] | [Kommentare des Reviewers]
[                    ] | [                         ]

Mit 150-Zeichen-Zeilen muss der Reviewer ständig horizontal scrollen. Das ist anstrengend und fehleranfällig.

Szenario 2: Split-Screen-Entwicklung

[Implementierungsdatei] | [Testdatei              ]
[Alte Code-Version    ] | [Neue Code-Version      ]

Lange Zeilen zwingen Sie zum Vollbild-Arbeiten, wodurch Sie Produktivitätsvorteile geteilter Ansichten verlieren.

Szenario 3: Code-Diffs

- marker=dict(size=12,color='red',symbol='circle',shape='diamond',opacity=0.8,line=dict(width=2,color='black'))
+ marker=dict(size=12,color='blue',symbol='circle',shape='diamond',opacity=0.8,line=dict(width=2,color='black'))

Können Sie die Änderung erkennen? Es ist color='red'color='blue', aber es ist in einer 120-Zeichen-Zeile vergraben.

Vergleichen Sie mit:

  marker = dict(
      size=12,
-     color='red',
+     color='blue',
      symbol='circle',
      shape='diamond',
  )

Die Änderung ist sofort offensichtlich.

Die Forschung

Studien zeigen, dass das Verständnis signifikant abnimmt, wenn Zeilen länger als 60-80 Zeichen gelesen werden. Ihre Augen müssen längere Sakkaden (Sprünge) machen, und Sie verlieren leichter Ihre Position.

4.5.3 Die Lösung

# GUT: Lange Zeilen logisch umbrechen
marker = dict(
    size=12,
    color='red',
    symbol='circle'
)

# GUT: Lange Kommentare umbrechen
# Add camera ray - Dieser Kommentar ist in mehrere Zeilen aufgeteilt,
# um empfohlene Zeilenlängenbeschränkungen für bessere Lesbarkeit zu respektieren

Professionelle Style-Richtlinie:


5. Teil 3: Das große Bild - Warum Code-Qualität wichtig ist

Jetzt, da wir spezifische Probleme gesehen haben, lassen Sie uns herauszoomen und die Prinzipien verstehen.

5.1 Prinzip 1: Code wird mehr gelesen als geschrieben

Die 10:1-Regel

Für jede Stunde, die mit dem Schreiben von Code verbracht wird, werden ungefähr 10 Stunden mit dem Lesen verbracht.

Denken Sie an Ihren Entwicklungsprozess:

  1. Sie schreiben ein Feature (1 Stunde)
  2. Sie debuggen es (lesen Ihren Code) (30 Min.)
  3. Ihr Kollege reviewt es (liest Ihren Code) (20 Min.)
  4. Zukünftiges Ich fügt ein Feature hinzu (liest alten Code) (1 Stunde)
  5. Neues Teammitglied lernt die Codebasis (liest Ihren Code) (2 Stunden)
  6. Jemand behebt einen Bug (liest Ihren Code) (1 Stunde)

Total: 5,5 Stunden Lesen, 1 Stunde Schreiben.

Code-Qualität optimiert für Lesen, nicht Schreiben.

5.2 Prinzip 2: Konsistenz reduziert kognitive Last

Ihr Gehirn ist eine Mustererkennungsmaschine. Wenn Code konsistent ist:

Beispiel:

# Inkonsistente Abstände - Ihr Gehirn muss jede Zeile einzeln parsen
x_road,y_road = generate_road_profile(num_points=100, x_max=80)
camera_x, camera_y = 0, 2.0
result= calculate_value(a,b)

# Konsistente Abstände - Ihr Gehirn erkennt das Muster
x_road, y_road = generate_road_profile(num_points=100, x_max=80)
camera_x, camera_y = 0, 2.0
result = calculate_value(a, b)

Die zweite Version fühlt sich “glatter” an, weil Ihr Gehirn nicht für jede Zeile den Kontext wechseln muss.

5.3 Prinzip 3: Früherkennung verhindert teure Bugs

Die Kosten von Bugs wachsen exponentiell

Wann gefunden Relative Kosten Beispiel
Beim Schreiben 1x "Hoppla, Tippfehler!" (5 Sekunden zu beheben)
Während Code Review 10x "Lass mich einen Fix pushen..." (5 Minuten)
Während QA-Tests 100x "Muss debuggen, fixen, retesten" (1 Stunde)
In Produktion 1000x+ "Notfall-Hotfix, Kundenentschädigung, Reputationsschaden" (Tage/Wochen)

Echtes Beispiel aus unserem Code

def find_intersection(x_road, y_road, angle_degrees, camera_x=0, camera_y=1.5):
    # ... code ...
    return x_intersect, y_intersect, distance

# Später:
x_intersect, y_intersect, distance = find_intersection(...)

Das funktioniert gut. Aber stellen Sie sich vor, jemand ändert es ohne Type Hints:

def find_intersection(x_road, y_road, angle_degrees, camera_x=0, camera_y=1.5):
    # ... code ...
    return distance  # Hoppla! Vergessen, x und y zurückzugeben

# Später:
x_intersect, y_intersect, distance = find_intersection(...)  # BOOM! Runtime-Fehler

Ohne Type Checking: Dieser Bug erreicht die Produktion, stürzt ab, wenn ein Benutzer den Winkel anpasst.

Mit Type Checking:

def find_intersection(
    x_road: np.NDArray,
    y_road: np.NDArray,
    angle_degrees: float,
    camera_x: float = 0,
    camera_y: float = 1.5
) -> tuple[float, float, float] | tuple[None, None, None]:
    # ... code ...
    return distance  # Type Checker: Fehler! Erwartete tuple[float, float, float]

Gefangen in 2 Sekunden, nicht 2 Wochen.

5.4 Prinzip 4: Automatisierung skaliert, Menschen nicht

Die Mathematik

Stellen Sie sich vor, Sie sind Teamleiter mit 10 Entwicklern. Ohne Automatisierung:

Manuelle Code-Review pro Pull Request: 30 Minuten
Pull Requests pro Woche: 50
Gesamte Review-Zeit: 25 Stunden/Woche

Sie müssen jemanden nur für Code-Reviews einstellen!

Mit Automatisierung:

Automatisierte Checks pro Pull Request: 2 Minuten
Pull Requests pro Woche: 50
Gesamte automatisierte Zeit: 100 Minuten/Woche
Menschliche Review-Zeit pro PR: 10 Minuten (Fokus auf Logik, nicht Style)
Gesamte menschliche Zeit: 8,3 Stunden/Woche

Gesparte Zeit: 16,7 Stunden/Woche = 867 Stunden/Jahr pro Team

Bei $100/Stunde (typische Entwicklerkosten) sind das $86.700 gespart pro Jahr.


6. Teil 4: PEP 8 - Die Grundlage der Python-Code-Qualität

In dieser Vorlesung haben wir gesehen, wie automatisierte Tools Probleme wie Import-Formatierung, Abstände, Namenskonventionen und Zeilenlänge finden. Sie fragen sich vielleicht: Woher kommen diese Regeln? Wer entscheidet, was “korrekt” ist?

Die Antwort ist PEP 8—Pythons offizieller Style Guide, der die Grundlage all dieser Qualitätsstandards bildet.

6.1 Was ist PEP 8?

PEP 8 ist Pythons offizieller Style Guide. PEP steht für “Python Enhancement Proposal”—so entwickelt sich Python als Sprache weiter.

PEP 8 sind keine Vorschläge—es ist der von der Community vereinbarte Standard.

6.2 Warum PEP 8 befolgen?

6.2.1 Grund 1: Es ist eine gemeinsame Sprache

Wenn Sie PEP 8 befolgen:

Es ist wie die Verwendung standardisierter deutscher Rechtschreibung. Sie könnten “Farbe” als “Varbe” schreiben, aber niemand würde Sie verstehen.

6.2.2 Grund 2: Tooling erwartet es

Alle wichtigen Python-Tools gehen von PEP 8 aus:

Gegen PEP 8 zu kämpfen bedeutet, gegen das gesamte Ökosystem zu kämpfen.

6.2.3 Grund 3: Einstellung und Karriere

Wenn Unternehmen Python-Entwickler einstellen, erwarten sie PEP 8-Kenntnisse. Code, der PEP 8 nicht befolgt, ist ein rotes Fähnchen bei:

6.3 Wichtige PEP 8-Regeln (Kurzreferenz)

Einrückung

# Verwenden Sie 4 Leerzeichen pro Einrückungsebene (keine Tabs)
def example_function():
    if True:
        print("Vier Leerzeichen")

Zeilenlänge

# Begrenzen Sie Zeilen auf 79 Zeichen (oder 88 mit modernen Tools)
# Brechen Sie lange Zeilen an logischen Punkten um
result = some_function(
    argument1,
    argument2,
    argument3
)

Imports

# Imports am Anfang der Datei, gruppiert in Reihenfolge:
# 1. Standardbibliothek
# 2. Drittanbieter
# 3. Lokale Anwendung

import os
import sys

import numpy as np
from dash import Dash

from myapp import utils

Namenskonventionen

# Funktionen und Variablen: snake_case
def calculate_average(numbers):
    total_sum = sum(numbers)
    return total_sum / len(numbers)

# Klassen: PascalCase
class RoadProfile:
    pass

# Konstanten: UPPER_CASE
MAX_SPEED = 100
PI = 3.14159

Leerzeichen

# Ja: Leerzeichen um Operatoren und nach Kommas
result = x + y
my_list = [1, 2, 3]
func(a, b, c)

# Nein: Fehlende Leerzeichen
result=x+y
my_list=[1,2,3]
func(a,b,c)

Kommentare

# Verwenden Sie Inline-Kommentare sparsam
x = x + 1  # Kompensiere für Rand

# Verwenden Sie Docstrings für Funktionen
def calculate_average(numbers):
    """
    Berechnet das arithmetische Mittel einer Liste von Zahlen.
    
    Args:
        numbers: Liste numerischer Werte
        
    Returns:
        float: Der Durchschnittswert
    """
    return sum(numbers) / len(numbers)

7. Teil 5: Moderne Tools - Die Ruff-Revolution

7.1 Die Evolution der Python-Code-Qualitäts-Tools

Traditioneller Ansatz (Vor 2023):

Jedes Tool hatte seine eigene Konfiguration, lief separat und brauchte erhebliche Zeit.

Moderner Ansatz (2024+):

Zwei Tools. Blitzschnell. Eine Konfigurationsdatei.

7.2 Was ist Ruff?

Ruff ist ein moderner Python-Linter und -Formatter, geschrieben in Rust. Er wird von Astral entwickelt, derselben Firma hinter uv.

Hauptmerkmale:

7.3 Ruff installieren - Dependency Management verstehen

Bevor wir Ruff verwenden können, müssen wir verstehen, wo und wie man es installiert. Das ist entscheidend, damit unsere Befehle funktionieren!

7.3.1 Das Problem: uv run ruff funktioniert (noch) nicht

Wenn Sie jetzt versuchen, Ruff auszuführen:

$ uv run ruff check .
error: program not found: ruff

Warum? Weil uv run nach ruff im .venv-Verzeichnis Ihres Projekts sucht, und wir es dort noch nicht installiert haben!

Das führt zu einer wichtigen Frage: Wo sollten wir Ruff installieren?

7.3.2 Drei Arten, Python-Pakete zu verwenden

Das Verständnis, wie man Abhängigkeiten richtig verwaltet, ist entscheidend für:

Lassen Sie uns die drei Kontexte erkunden, in denen Python-Pakete installiert werden können:

1. Projekt-Abhängigkeiten ([project.dependencies])

Was: Pakete, die Ihre Anwendung zum Laufen in der Produktion BRAUCHT.

Für unseren Road Profile Viewer sind das die Pakete, die installiert sein müssen, damit die Anwendung funktioniert:

[project]
dependencies = [
    "dash>=2.14.0",
    "plotly>=5.18.0",
    "numpy>=1.26.0",
]

Hinzufügen mit:

uv add dash plotly numpy

Wann verwenden: Wenn das Paket zum Ausführen der Anwendung erforderlich ist.


2. Entwicklungs-Abhängigkeiten ([dependency-groups.dev])

Was: Tools, die Sie für die ENTWICKLUNG benötigen, aber nicht zum Ausführen der App (Linter, Formatter, Test-Frameworks).

Hier gehört Ruff hin! Ruff ist ein Entwicklungstool – wir verwenden es, um unseren Code zu prüfen und zu formatieren, aber der Road Profile Viewer braucht Ruff nicht zum Laufen.

[dependency-groups]
dev = [
    "ruff>=0.8.0",
    "pytest>=7.0.0",
]

Hinzufügen mit:

uv add --dev ruff pytest

Wann verwenden: Wenn Sie das Tool für Entwicklung, Testing oder Code-Qualität benötigen, aber nicht zum Ausführen der Anwendung.


3. Globale Tools (uv tool install)

Was: CLI-Tools, die Sie systemweit in ALLEN Projekten verfügbar haben möchten.

uv tool install ruff

Wann verwenden: Wenn Sie ein Tool überall verfügbar haben möchten, ohne es zu den Abhängigkeiten jedes Projekts hinzuzufügen.

Abwägung:


7.3.3 Entscheidungsbaum: Wo sollte Ruff hin?

Wird Ruff benötigt, um die Road Profile Viewer Anwendung AUSZUFÜHREN?
└─ NEIN → Es ist ein Entwicklungstool

Ist Ruff spezifisch für DIESES Projekt?
└─ JA → Wir wollen konsistente Versionen im Team

Wollen wir es in der Versionskontrolle dokumentieren?
└─ JA → Teammitglieder sollten es in pyproject.toml sehen

✅ Entscheidung: Als Entwicklungs-Abhängigkeit installieren

7.3.4 Ruff für unser Projekt installieren

Schritt 1: Ruff als Entwicklungs-Abhängigkeit hinzufügen

uv add --dev ruff

Dies ändert Ihre pyproject.toml:

[project]
name = "road-profile-viewer"
version = "0.1.0"
dependencies = [
    "dash>=2.14.0",
    "plotly>=5.18.0",
    "numpy>=1.26.0",
]

[dependency-groups]
dev = [
    "ruff>=0.8.0",  # ← Hier hinzugefügt!
]

Schritt 2: Alle Abhängigkeiten installieren (inklusive dev)

uv sync --group dev

Dies installiert:

Schritt 3: Verifizieren, dass Ruff installiert ist

uv run ruff --version
# Ausgabe: ruff 0.8.0

Jetzt funktioniert uv run ruff! 🎉

7.3.5 uv run Verhalten verstehen

Wenn Sie uv run <command> ausführen, passiert Folgendes:

1. uv sucht nach pyproject.toml (durchsucht Verzeichnisbaum nach oben)
2. uv prüft, ob <command> im .venv des Projekts existiert
3. Wenn gefunden: führt es mit der Python-Umgebung des Projekts aus
4. Wenn nicht gefunden: Fehler "program not found"

Häufige Verwirrung:

Das funktioniert NICHT (Ruff noch nicht im .venv):

uv run ruff check .
# Fehler: program not found

Das FUNKTIONIERT (nach uv add --dev ruff):

uv run ruff check .
# Läuft erfolgreich!

Das FUNKTIONIERT (temporäre Installation, ändert Projekt nicht):

uv run --with ruff ruff check .
# Erstellt temporäre Umgebung mit ruff und führt es aus

Das FUNKTIONIERT (wenn global installiert):

uv tool install ruff
ruff check .  # Direkt ausführen, kein uv run nötig

7.3.6 Best Practice: Entwicklungs-Setup dokumentieren

Fügen Sie einen Abschnitt zu Ihrer README.md hinzu:

## 8. Entwicklungs-Setup {#entwicklungs-setup}

### 8.1 Abhängigkeiten installieren {#abhängigkeiten-installieren}

```bash
# Alle Abhängigkeiten installieren (inklusive Entwicklungstools)
uv sync --group dev

8.2 Verfügbare Entwicklungs-Befehle

# Linter ausführen
uv run ruff check .

# Linting-Probleme automatisch beheben
uv run ruff check --fix .

# Code formatieren
uv run ruff format .

# Anwendung ausführen
uv run road-profile-viewer

Dies stellt sicher, dass neue Teammitglieder genau wissen, wie sie ihre Umgebung einrichten!

8.2.1 Zusammenfassung: Dependency Management mit uv

Befehl Zweck Ändert pyproject.toml?
uv add <paket> Produktions-Abhängigkeit hinzufügen ✅ Ja → [project.dependencies]
uv add --dev <paket> Entwicklungs-Abhängigkeit hinzufügen ✅ Ja → [dependency-groups.dev]
uv sync Nur Produktions-Abhängigkeiten installieren ❌ Nein
uv sync --group dev Alle Abhängigkeiten installieren (Prod + Dev) ❌ Nein
uv run <befehl> Befehl in Projekt-Umgebung ausführen ❌ Nein
uv run --with <pkg> <cmd> Temporäre Paketverwendung ❌ Nein
uv tool install <paket> Globales CLI-Tool installieren ❌ Nein

Kernaussage: Entwicklungstools wie Ruff sollten mit uv add --dev installiert werden, um:


8.3 Ruff Check - Der Linter

Jetzt, da Ruff ordnungsgemäß als Entwicklungs-Abhängigkeit installiert ist, lassen Sie uns erkunden, was es kann!

Was es tut: Analysiert Code auf Fehler, Bugs, Style-Verstöße und Code-Smells.

Ruff Check ausführen:

# Alle Dateien im aktuellen Verzeichnis prüfen
uv run ruff check .

# Spezifische Datei prüfen
uv run ruff check src/main.py

# Probleme automatisch beheben, wo möglich
uv run ruff check --fix .

# Zeigen, was behoben würde, ohne Dateien zu ändern
uv run ruff check --fix --diff .

Beispiel-Ausgabe:

$ uv run ruff check .

src/main.py:16:1: E401 [*] Multiple imports on one line
src/main.py:16:8: F401 [*] `sys` imported but unused
src/main.py:29:5: E225 [*] Missing whitespace around operator
src/main.py:36:1: N802 Function name `HelperFunction` should be lowercase
src/main.py:47:1: E501 Line too long (149 > 88 characters)

Found 5 errors.
[*] 3 fixable with the `--fix` option.

Das [*] zeigt automatisch behebbare Probleme an.

8.4 Ruff Format - Der Code-Formatter

Was es tut: Formatiert Code automatisch, um konsistenten Style-Regeln zu folgen (kompatibel mit Black).

Ruff Format ausführen:

# Alle Dateien formatieren
uv run ruff format .

# Prüfen, ob Formatierung benötigt wird (ändert keine Dateien)
uv run ruff format --check .

# Zeigen, was sich ändern würde (Diff-Modus)
uv run ruff format --diff .

Vorher:

def generate_road_profile(num_points=100,x_max=80):
    y=0.015 * x_norm**3 * x_max
    return x,y

Nachher:

def generate_road_profile(num_points=100, x_max=80):
    y = 0.015 * x_norm**3 * x_max
    return x, y

8.5 Ruff konfigurieren

8.5.1 pyproject.toml Sections verstehen

Erinnern Sie sich, dass pyproject.toml zwei Hauptarten von Sektionen hat:

  1. Standardisierte Sektionen (definiert durch Python PEPs):
    • [project] - Projekt-Metadaten und Abhängigkeiten
    • [dependency-groups] - Optionale Abhängigkeitsgruppen wie dev
  2. Tool-spezifische Sektionen mit [tool.*] Namespace:
    • [tool.ruff] - Ruff-Konfiguration
    • [tool.pytest] - pytest-Konfiguration
    • [tool.mypy] - mypy-Konfiguration

Dies hält alle Tool-Konfigurationen in einer Datei, statt über .ruff.toml, .pytest.ini usw. verstreut zu sein.

8.5.2 Warum Ruff anpassen?

Ruff funktioniert mit seinen Standardwerten großartig, aber Sie möchten es anpassen, weil:

1. Projekt-spezifische Anforderungen

2. Mehr Regeln aktivieren

3. Team-Konsistenz

4. CI/CD-Integration

8.5.3 Ihre Ruff-Konfiguration

KI nutzen: Fokus auf Anforderungen, nicht auf Syntax

Anstatt TOML-Syntax und Ruff-Konfigurationsoptionen auswendig zu lernen, nutzen wir KI, um unsere Anforderungen in Konfiguration zu übersetzen. Das ist moderne Entwicklung: Fokus auf das, was Sie brauchen, KI übernimmt die Syntax-Details.

Schritt 1: Definieren Sie Ihre Anforderungen

Überlegen Sie, was Ihr Projekt braucht:

Schritt 2: KI bitten, Konfiguration zu generieren

Verwenden Sie einen Prompt wie diesen im GitHub Copilot Chat oder einem anderen KI-Assistenten:

Erstelle eine [tool.ruff] Konfiguration für pyproject.toml mit:
- Zeilenlänge: 88
- Ziel Python 3.12
- Ausschließen: .git, .venv, __pycache__, build, dist
- Diese Regelgruppen aktivieren: pycodestyle (E/W), Pyflakes (F), isort (I),
  pep8-naming (N), flake8-bugbear (B), flake8-comprehensions (C4), pyupgrade (UP)
- Auto-Fix für alle Regeln erlauben
- Formatierung mit doppelten Anführungszeichen, Unix-Zeilenenden, Leerzeichen-Einrückung

Schritt 3: Überprüfen und anwenden

Die KI generiert die Konfiguration. Überprüfen Sie sie immer - Sie sind der Experte für Ihre Projektanforderungen:

[project]
name = "road-profile-viewer"
version = "0.1.0"
description = "Interactive road profile visualization"
requires-python = ">=3.12"

[tool.ruff]
# Maximale Zeilenlänge festlegen
line-length = 88

# Ziel-Python-Version
target-version = "py312"

# Bestimmte Verzeichnisse ausschließen
exclude = [
    ".git",
    ".venv",
    "__pycache__",
    "build",
    "dist",
]

[tool.ruff.lint]
# Regeln zum Aktivieren auswählen
select = [
    "E",   # pycodestyle errors
    "W",   # pycodestyle warnings
    "F",   # Pyflakes
    "I",   # isort (import sorting)
    "N",   # pep8-naming
    "B",   # flake8-bugbear
    "C4",  # flake8-comprehensions
    "UP",  # pyupgrade
]

# Spezifische Regeln ignorieren, falls nötig
ignore = []

# Auto-Fix für diese Regeln erlauben
fixable = ["ALL"]
unfixable = []

[tool.ruff.format]
# Doppelte Anführungszeichen verwenden (wie Black)
quote-style = "double"

# Unix-Zeilenenden verwenden
line-ending = "lf"

# Mit Leerzeichen einrücken
indent-style = "space"

Warum dieser Ansatz funktioniert:

Fokus auf Absicht - Sie spezifizieren was Sie wollen, nicht wie man es schreibt
Schnellere Entwicklung - Kein Nachschlagen exakter Konfigurationsschlüssel
Lernen durch Überprüfung - Sie sehen korrekte Syntax und können sie anpassen
Syntaxfehler vermeiden - KI kennt die exakte TOML-Struktur

Merke: KI ist Ihr Syntax-Assistent, aber SIE entscheiden die Anforderungen basierend auf Ihren Projektbedürfnissen!

8.6 Ruff in VS Code - Echtzeit-Feedback

Während Ruff über die Kommandozeile mächtig ist, bringt die Ruff VS Code-Erweiterung Code-Qualität direkt in Ihren Editor mit sofortigem Feedback beim Tippen.

8.6.1 Installation der Ruff-Erweiterung

Methode 1: VS Code Extensions-Panel

  1. Öffnen Sie VS Code
  2. Klicken Sie auf das Extensions-Icon (oder drücken Sie Strg+Umschalt+X / Cmd+Shift+X)
  3. Suchen Sie nach “Ruff”
  4. Klicken Sie auf Installieren bei der offiziellen Erweiterung von Astral

Methode 2: Kommandozeile

code --install-extension charliermarsh.ruff

Methode 3: Quick Open

8.6.2 Echtzeit-Linting - Sofortiges Feedback

Nach der Installation analysiert Ruff Ihren Code automatisch während Sie tippen und zeigt Probleme mit farbigen Unterstreichungen:

Rote Wellenlinien = Fehler (müssen behoben werden)

import sys,os  # Rote Unterstreichung: E401 Mehrere Imports auf einer Zeile

Gelbe Wellenlinien = Warnungen (sollten behoben werden)

def HelperFunction(val):  # Gelbe Unterstreichung: N802 Funktionsname sollte Kleinbuchstaben sein

Hover für Details:

Problems-Panel:

Vorteile:

8.6.3 Auto-Fix mit Tastaturkürzeln

Die Ruff-Erweiterung kann viele Probleme automatisch beheben, ohne den Editor zu verlassen.

Quick Fix (Einzelnes Problem):

  1. Platzieren Sie Cursor auf unterstrichenem Code
  2. Drücken Sie Strg+. / Cmd+. (oder klicken Sie auf das Glühbirnen-Icon 💡)
  3. Wählen Sie “Ruff: Fix all auto-fixable problems”
  4. Problem ist sofort behoben!

Beispiel:

# Vorher (Cursor auf dieser Zeile)
import sys,os,json  # E401-Verletzung

# Drücken Sie Strg+. und wählen Sie Fix

# Nachher
import sys
import os
import json

Dokument formatieren (Alles auto-formatieren):

Auswahl formatieren:

Alle automatisch behebbaren Probleme beheben:

8.6.4 Format on Save - Null Aufwand

Konfigurieren Sie VS Code, um automatisch zu formatieren und Probleme zu beheben, wenn Sie eine Datei speichern.

Format on Save aktivieren:

  1. Öffnen Sie Einstellungen: Strg+, / Cmd+,
  2. Suchen Sie nach: format on save
  3. Aktivieren Sie ✅ Editor: Format On Save

Ruff als Standard-Formatter konfigurieren:

Fügen Sie zu Ihrer .vscode/settings.json hinzu (in Ihrem Projekt):

{
  "[python]": {
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.fixAll.ruff": "explicit",
      "source.organizeImports.ruff": "explicit"
    }
  }
}

Was das bewirkt:

Ergebnis: Drücken Sie Strg+S / Cmd+S → Code ist sofort formatiert und bereinigt! 🎉

8.6.5 Praktisches Workflow-Beispiel

Szenario: Sie schreiben neuen Code mit mehreren PEP 8-Verletzungen.

Ohne VS Code-Erweiterung:

# Sie schreiben diesen Code
def ProcessData(input,threshold=10):
    result=[]
    for item in input:
        if item>threshold:result.append(item*2)
    return result

# Später führen Sie Kommandozeile aus
$ uv run ruff check main.py
# Sehen 8 Verletzungen
# Manuell beheben oder --fix verwenden
# Erneut ausführen zur Überprüfung

Mit VS Code-Erweiterung:

# Während Sie tippen, sehen Sie:
def ProcessData(input,threshold=10):  # Gelbe Unterstreichung: N802
    #         ^ Gelbe Unterstreichung: E231
    result=[]  # Gelbe Unterstreichung: E225
    #     ^
    for item in input:
        if item>threshold:result.append(item*2)
        #      ^E225    ^E701 zusammengesetzte Anweisung

# Sie drücken Strg+. auf Funktionsnamen → Quick fix "Kleinbuchstaben verwenden"
# Sie drücken Umschalt+Alt+F → Gesamtes Dokument formatieren

# Ergebnis (sofort):
def process_data(input, threshold=10):
    result = []
    for item in input:
        if item > threshold:
            result.append(item * 2)
    return result

# Alle Verletzungen in 2 Sekunden behoben! 🚀

8.6.6 Konfigurations-Tipps

Workspace-Einstellungen (Projektspezifisch)

Erstellen Sie .vscode/settings.json in Ihrem Projekt:

{
  "ruff.lint.args": ["--config=pyproject.toml"],
  "ruff.format.args": ["--config=pyproject.toml"],
  "ruff.organizeImports": true,
  "ruff.fixAll": true,
  "editor.rulers": [88],
  "files.trimTrailingWhitespace": true
}

Benutzereinstellungen (Alle Projekte)

Einstellungen → Suche “ruff” → Konfigurieren:

Konflikt-Erweiterungen deaktivieren:

Falls Sie diese installiert haben, deaktivieren Sie sie für Python-Dateien:

Sie kollidieren mit Ruff und verlangsamen Ihren Editor.

8.6.7 Fehlersuche

Problem: Ruff-Erweiterung funktioniert nicht

Lösung:

  1. Prüfen Sie, ob Erweiterung installiert ist: Strg+Umschalt+X → Suche “Ruff”
  2. Prüfen Sie, ob Erweiterung für Workspace aktiviert ist
  3. VS Code neu laden: Strg+Umschalt+P → “Reload Window”
  4. Prüfen Sie Output-Panel: Ansicht → Output → “Ruff” auswählen

Problem: Format on save funktioniert nicht

Lösung:

  1. Überprüfen Sie settings.json-Konfiguration
  2. Prüfen Sie, ob Ruff Standard-Formatter ist: Strg+Umschalt+P → “Dokument formatieren mit…” → “Ruff” auswählen
  3. Datei speichern und Problems-Panel auf Fehler prüfen

Problem: Zu viele Warnungen

Lösung:

  1. Konfigurieren Sie pyproject.toml, um spezifische Regeln zu ignorieren
  2. Schweregrad anpassen: Einstellungen → Suche “ruff” → Schweregradebene festlegen
  3. Verwenden Sie # noqa-Kommentare für spezifische Zeilen (sparsam!)
import sys  # noqa: F401 - benötigt für Debugging

8. Teil 6: Type Checking mit Pyright

8.1 Warum Type Checking wichtig ist

Python ist dynamisch typisiert, was flexibel, aber gefährlich ist:

def calculate_discount(price, discount_percent):
    return price * (discount_percent / 100)

# Das wird zur Laufzeit abstürzen!
result = calculate_discount("50", "10")

Type Hints (Python 3.5+) erlauben es Ihnen, Typ-Informationen hinzuzufügen:

def calculate_discount(price: float, discount_percent: float) -> float:
    return price * (discount_percent / 100)

# Type Checker fängt dies VOR der Laufzeit
result = calculate_discount("50", "10")  # Fehler: Erwartete float, bekam str

8.2 Was ist Pyright?

Pyright ist ein schneller, funktionsreicher Type Checker für Python, entwickelt von Microsoft.

Warum Pyright statt mypy?

Merkmal Pyright mypy
Geschwindigkeit 5-10x schneller (TypeScript/Node.js) Langsamer (Python-basiert)
VS Code Integration In Pylance-Extension eingebaut Separate Extension benötigt
Modernes Python Exzellente 3.10+ Unterstützung Gute Unterstützung, langsamere Updates
Type Inference Intelligenter Gut, aber weniger ausgeklügelt
Aktive Entwicklung Microsoft-unterstützt, schnelle Updates Langsamerer Update-Zyklus

Für diesen Kurs: Wir verwenden Pyright, weil es zu Ihrer IDE (VS Code + Pylance) passt und eine konsistente Erfahrung bietet.

8.3 Pyright installieren

Genau wie Ruff sollte Pyright als Entwicklungs-Abhängigkeit installiert werden:

uv add --dev pyright

Dies fügt Pyright zu [dependency-groups.dev] in Ihrer pyproject.toml hinzu:

[dependency-groups]
dev = [
    "ruff",
    "pyright",
]

Synchronisieren und verifizieren:

# Entwicklungs-Abhängigkeiten installieren
uv sync --group dev

# Pyright testen
uv run pyright --version

8.3.1 Windows-Setup: Entwicklermodus erforderlich

⚠️ Windows-spezifisches Problem:

Pyright ist ein TypeScript-basiertes Tool, das Node.js benötigt. Wenn Sie uv run pyright zum ersten Mal ausführen, installiert uv automatisch Node.js (v25.0.0+) und erstellt Symlinks.

Unter Windows sehen Sie möglicherweise diesen Fehler:

Error: You do not have sufficient permissions to perform this operation.

Warum? Das Erstellen von Symlinks unter Windows erfordert entweder:

Lösung: Windows-Entwicklermodus aktivieren

Führen Sie PowerShell als Administrator aus und führen Sie dann aus:

# Entwicklermodus aktivieren (erfordert Admin-Rechte)
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"

Nach Ausführung dieses Befehls:

  1. Starten Sie Ihr Terminal neu
  2. Versuchen Sie erneut uv run pyright --version
  3. Node.js wird automatisch installiert und Pyright funktioniert

Alternative (nicht empfohlen): VS Code jedes Mal als Administrator ausführen. Entwicklermodus ist besser, da es eine einmalige Einrichtung ist.

8.4 Pyright konfigurieren - Von nachsichtig zu strikt

8.4.1 Das Standard-Problem

Standardmäßig läuft Pyright im Basic-Modus - es ist sehr nachsichtig und fängt viele Type-Probleme nicht:

uv run pyright
# Ausgabe: 0 errors found in 5 files

Das scheint gut, ist aber irreführend! Pyright ignoriert:

Warum so nachsichtig? Um mit bestehenden Python-Codebasen zu arbeiten, die keine Type Hints haben.

Für neue Projekte: Wir wollen strengere Prüfung, um Probleme früh zu fangen.

8.4.2 KI nutzen für strikte Type-Checking-Konfiguration

Definieren Sie Ihre Anforderungen:

Für unser Kursprojekt wollen wir:

Prompt für KI:

Erstelle eine [tool.pyright] Konfiguration für pyproject.toml mit:
- Type-Checking-Modus: strict
- Python-Version: 3.12
- Include: src Verzeichnis
- Report missing type stubs: true
- Report unknown member type: warning
- Report unknown parameter type: warning
- Report unknown variable type: warning

Generierte Konfiguration:

Fügen Sie dies zu Ihrer pyproject.toml hinzu:

[tool.pyright]
# Strikte Type-Prüfung
typeCheckingMode = "strict"

# Python-Version
pythonVersion = "3.12"

# Nur Source-Dateien einschließen
include = ["src"]

# Verzeichnisse ausschließen
exclude = [
    ".venv",
    "__pycache__",
    "build",
    "dist",
]

# Reporting-Optionen
reportMissingTypeStubs = true
reportUnknownMemberType = "warning"
reportUnknownParameterType = "warning"
reportUnknownVariableType = "warning"
reportUnknownArgumentType = "warning"

Jetzt Pyright erneut ausführen:

uv run pyright

Sie werden wahrscheinlich viele Fehler sehen! Das ist gut - dies waren versteckte Probleme, die Pyright jetzt fängt.

Häufige Fehler, die Sie sehen werden:

src/main.py:10:5 - error: Type of "x" is unknown (reportUnknownVariableType)
src/utils.py:25:15 - error: Return type is unknown (reportUnknownParameterType)

Type-Checking-Modi erklärt:

Modus Strenge Anwendungsfall
off Keine Prüfung Legacy-Code, Prototypen
basic Minimal (Standard) Schrittweise Typisierung
standard Moderat Die meisten Projekte
strict Maximum Neue Projekte, hohe Qualität

Für diesen Kurs: Verwenden Sie den strict-Modus, um von Anfang an ordnungsgemäße Type Safety zu lernen.

8.5 Type Hints verwenden

Grundtypen:

# Variablen
name: str = "Alice"
age: int = 25
height: float = 1.75
is_student: bool = True

# Funktionen
def greet(name: str) -> str:
    return f"Hello, {name}"

def calculate_total(items: list[float]) -> float:
    return sum(items)

Optionale Typen (None-Behandlung):

def find_user(user_id: int) -> User | None:
    """Gibt User zurück oder None, wenn nicht gefunden."""
    ...

user = find_user(123)
# Pyright-Fehler: 'user' könnte None sein
print(user.name)

# Richtige Art
if user is not None:
    print(user.name)

Komplexe Typen:

from typing import Callable

# Funktion, die einen Callback nimmt
def process(callback: Callable[[int], str]) -> None:
    result = callback(42)
    print(result)

# Richtiger Callback
def my_callback(x: int) -> str:
    return f"Value: {x}"

process(my_callback)  # OK

# Falscher Callback
def wrong_callback(x: str) -> str:
    return f"Value: {x}"

process(wrong_callback)  # Pyright-Fehler: Signatur passt nicht

Typen auf Road Profile Viewer anwenden:

import numpy as np
from numpy.typing import NDArray

def generate_road_profile(
    num_points: int = 100,
    x_max: float = 80
) -> tuple[NDArray[np.float64], NDArray[np.float64]]:
    """
    Generiert ein Straßenprofil mit einer Klothoiden-ähnlichen Approximation.
    
    Args:
        num_points: Anzahl der zu generierenden Punkte
        x_max: Maximaler x-Koordinatenwert
        
    Returns:
        Tupel von (x_koordinaten, y_koordinaten)
    """
    x = np.linspace(0, x_max, num_points)
    x_norm = x / x_max
    
    y = 0.015 * x_norm**3 * x_max + 0.3 * np.sin(2 * np.pi * x_norm)
    y = y - y[0]
    
    return x, y


def find_intersection(
    x_road: NDArray[np.float64],
    y_road: NDArray[np.float64],
    angle_degrees: float,
    camera_x: float = 0,
    camera_y: float = 1.5
) -> tuple[float, float, float] | tuple[None, None, None]:
    """
    Findet Schnittpunkt zwischen Kamerastrahl und Straßenprofil.
    
    Args:
        x_road: X-Koordinaten des Straßenprofils
        y_road: Y-Koordinaten des Straßenprofils
        angle_degrees: Kamerastrahlwinkel in Grad
        camera_x: Kamera-X-Position
        camera_y: Kamera-Y-Position
        
    Returns:
        Tupel von (x_intersect, y_intersect, distance) oder (None, None, None)
    """
    # Implementierung...
    pass

8.6 Pyright ausführen

Nach Installation und Konfiguration prüfen Sie Ihren Code auf Type-Fehler:

# Alle Dateien prüfen (berücksichtigt pyproject.toml-Konfiguration)
uv run pyright

# Spezifische Datei prüfen
uv run pyright src/main.py

# Detaillierte Fehlerinformationen anzeigen
uv run pyright --verbose

Was Sie im strict-Modus erwarten sollten:

Beispiel-Workflow:

# 1. Pyright ausführen
uv run pyright

# 2. Gemeldete Type-Probleme in Ihrem Code beheben
# 3. Erneut ausführen zur Verifizierung
uv run pyright

# Alles klar!
# ✓ 0 errors found in 5 files

9. Zusammenfassung: Von Tools zur Praxis

9.1 Funktionierender Code ≠ Qualitätscode

Code, der läuft, ist erst der Anfang. Professionelle Software muss sein:

9.2 Die Tools, die Sie brauchen

Für Qualitätsdurchsetzung:

Checks lokal ausführen:

uv run ruff check --fix .
uv run ruff format .
uv run pyright

9.3 Folgen Sie PEP 8

Pythons Style Guide ist nicht optional:

9.4 Type Hints sparen Zeit

Type Hints fangen Bugs, bevor sie die Produktion erreichen:

9.5 Was kommt als Nächstes?

Sie wissen jetzt was zu prüfen ist und wie man es lokal prüft. Aber wie stellen Sie sicher, dass diese Checks automatisch bei jedem Commit laufen und verhindern, dass schlechter Code in Ihr Repository gelangt?

In Kapitel 02 (Feature-Entwicklung) (Donnerstag, 16. Oktober) werden wir erkunden:

Wir werden Ihre lokalen Qualitätschecks in eine automatisierte Pipeline verwandeln, die Qualität 24/7 durchsetzt und sicherstellt, dass jeder Commit Ihre Standards erfüllt, egal ob Sie sich daran erinnern, die Checks auszuführen oder nicht.


10. Die Qualitätslandschaft verstehen: Konzepte und Tools

Bevor wir uns in die praktische Aufgabe vertiefen, lassen Sie uns die verschiedenen Qualitätskonzepte klären, die wir besprochen haben, und wie sie sich zueinander verhalten. Diese Landschaft kann verwirrend sein, weil sich einige Konzepte überschneiden und die Tools, die wir verwenden (Ruff und Pyright), mehrere Aspekte der Qualität behandeln.

10.1 Die Qualitätskonzepte

10.1.1 Style Guide (PEP 8)

Was es ist: Ein Dokument, das Codierungskonventionen definiert—die “Grammatikregeln” des Python-Codes.

Was es abdeckt:

Pythons Realisierung: PEP 8 ist Pythons offizieller Style Guide, geschrieben von Guido van Rossum und der Python-Community.

Analogie: Wie ein Sprachstil-Leitfaden (APA, MLA, Chicago) für das Schreiben von Aufsätzen—er sagt Ihnen die “richtige” Art, Ihren Code zu formatieren.

Beispielregel: “Funktionsnamen sollten Kleinbuchstaben mit durch Unterstriche getrennten Wörtern sein” → calculate_total() nicht CalculateTotal()


10.1.2 Linting

Was es ist: Automatisierte Analyse von Code, um Fehler, Bugs, stilistische Probleme und verdächtige Konstrukte zu finden.

Was es abdeckt:

Pythons Realisierung mit Ruff: ruff check analysiert Ihren Code gegen 800+ Regeln, einschließlich PEP 8-Style-Regeln, gängiger Bug-Muster und Best Practices.

Analogie: Wie ein Grammatikchecker in Microsoft Word—er hebt Probleme hervor und schlägt Fixes vor.

Beispiel-Checks:

Wichtige Erkenntnis: Linting ist der Prozess der Code-Prüfung. PEP 8 ist einer der Standards, die geprüft werden. Linters prüfen auf PEP 8-Konformität UND viel mehr.


10.1.3 Formatierung

Was es ist: Automatische Umstrukturierung von Code, um konsistenten Style-Regeln zu folgen—eine Teilmenge dessen, was ein Linter prüft.

Was es abdeckt:

Pythons Realisierung mit Ruff: ruff format formatiert Ihren Code automatisch, um PEP 8-konform zu sein (Black-kompatibler Style).

Analogie: Wie “Auto-Format” in Word—es behebt Abstände und Layout automatisch.

Wichtiger Unterschied:

Beispiel:

# Vorher
x=1+2

# Linter sagt: "E225: Fehlendes Leerzeichen um Operator"
# Formatter behebt es automatisch:
x = 1 + 2

10.1.4 Type Hints

Was es ist: Optionale Annotationen, die spezifizieren, welche Arten von Werten Variablen, Parameter und Rückgabewerte haben sollten.

Was es abdeckt:

Pythons Realisierung: In Python 3.5+ eingebaut, unter Verwendung des typing-Moduls. Von Entwicklern zum Code hinzugefügt.

Syntax:

def calculate_total(prices: list[float]) -> float:
    return sum(prices)

Analogie: Wie das Deklarieren von Variablentypen in statisch typisierten Sprachen (Java, C++), aber optional in Python.

Wichtige Erkenntnis: Type Hints sind Annotationen, die Sie schreiben. Sie tun von sich aus nichts—Sie benötigen einen Type Checker, um sie zu validieren.


10.1.5 Type Checking

Was es ist: Automatisierte Analyse, die überprüft, ob Type Hints konsistent und korrekt in Ihrem Code verwendet werden.

Was es abdeckt:

Pythons Realisierung mit Pyright: pyright analysiert Ihre Type Hints und leitet Typen ab, auch wo nicht explizit annotiert.

Analogie: Wie ein Compiler-Type-Checker in Java oder TypeScript—fängt Typfehler vor der Laufzeit.

Beispiel:

def greet(name: str) -> str:
    return f"Hello, {name}"

result = greet(42)  # Pyright-Fehler: Argument vom Typ 'int' kann nicht dem Parameter 'str' zugewiesen werden

Wichtiger Unterschied:


10.2 Wie sich die Konzepte überschneiden

Hier passiert oft Verwirrung:

┌─────────────────────────────────────────────────────────────┐
│                        PEP 8                                │
│              (Der Style Guide - Die Regeln)                 │
│                                                             │
│  ┌────────────────────────────────────────────────────┐     │
│  │              Linting (ruff check)                  │     │
│  │                                                    │     │
│  │  • Prüft PEP 8-Style-Regeln ←───────────────────────────── Überschneidung!
│  │  • Prüft auf Bugs (ungenutzte Imports, undefinierte Vars)│ 
│  │  • Prüft Best Practices (Anti-Patterns)            │     │
│  │  • Prüft Code-Smells                               │     │
│  │                                                    │     │
│  │     ┌──────────────────────────────────────┐       │     │
│  │     │   Formatierung (ruff format)         │       │     │
│  │     │                                      │       │     │
│  │     │  • Behebt Style-Probleme automatisch ←───────┼─────┼───── Teilmenge!
│  │     │  • Leerzeichen, Einrückung, Anführungszeichen│     │     
│  │     └──────────────────────────────────────┘       │     │
│  └────────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                  Typsystem (Separat!)                       │
│                                                             │
│  Sie schreiben:             Tool validiert:                 │
│  ┌─────────────────┐       ┌──────────────────────┐         │
│  │  Type Hints     │  ──→  │  Type Checking       │         │
│  │  (Annotationen) │       │  (pyright)           │         │
│  └─────────────────┘       └──────────────────────┘         │
└─────────────────────────────────────────────────────────────┘

Wichtige Überschneidungen:

  1. Linting beinhaltet Style-Checking
    • ruff check validiert PEP 8-Style-Regeln
    • Aber es prüft auch auf Bugs und Best Practices, die PEP 8 nicht abdeckt
  2. Formatierung ist eine Teilmenge von Linting
    • Beide befassen sich mit Code-Style
    • Formatter behebt automatisch, Linter meldet
    • Formatter behandelt nur Layout/Leerzeichen, Linter prüft auch Logik
  3. Type Hints werden von Lintern UND Type Checkern geprüft
    • ruff check kann fehlende Type Hints finden (wenn konfiguriert)
    • pyright validiert, dass Type Hints korrekt verwendet werden
    • Verschiedene Tools, komplementäre Zwecke

10.3 Die Python-Realisierungen: Ruff und Pyright

10.3.1 Ruff: Das Multi-Tool

Ruff kombiniert mehrere Qualitätschecks:

Befehl Was es tut Welches Konzept Beispiel
ruff check Linting Style Guide + Bug-Erkennung Findet E501 (Zeile zu lang), F401 (ungenutzter Import)
ruff format Formatierung Style Guide-Durchsetzung Behebt Abstände: x=1x = 1
ruff check --select I Import-Sortierung Style Guide (PEP 8 Imports) Organisiert Imports alphabetisch

Warum das verwirrend ist: Ruff macht Linting UND Formatierung, was traditionell separate Tools waren (Flake8 + Black). Jetzt ist es ein Tool mit zwei Modi.

Mentales Modell:


10.3.2 Pyright: Die Typ-Polizei

Pyright konzentriert sich auf Typ-Korrektheit:

Was es tut Welches Konzept Beispiel
Validiert Type Hints Type Checking Fängt greet(42), wenn Signatur greet(name: str) ist
Leitet Typen ab Type Checking Weiß x = 5 bedeutet x: int auch ohne Annotation
Findet None-Probleme Type Checking Fängt user.name, wenn user möglicherweise None ist
Meldet fehlende Typen Code-Qualität Warnt, wenn Funktionen Typ-Annotationen fehlen

Warum sowohl Ruff ALS AUCH Pyright verwenden?

Sie ergänzen sich—das eine ersetzt nicht das andere.


10.4 Ihr Qualitäts-Workflow

Schritt-für-Schritt was passiert:

# 1. Sie schreiben Code (mit Type Hints)
def calculate_total(prices: list[float]) -> float:
    x=sum(prices)  # Hoppla, fehlende Leerzeichen
    return x

# 2. Formatter ausführen
$ uv run ruff format .
→ Behebt Abstände automatisch: x = sum(prices)

# 3. Linter ausführen
$ uv run ruff check .
→ Prüft PEP 8-Konformität ✓
→ Prüft auf Bugs ✓
→ Prüft Best Practices ✓

# 4. Type Checker ausführen
$ uv run pyright
→ Validiert, dass Type Hints korrekt verwendet werden ✓
→ Leitet Typen ab und fängt Nichtübereinstimmungen ✓

Jedes Tool hat eine spezifische Aufgabe:

  1. Formatter (ruff format): Macht Code konsistent aussehend
  2. Linter (ruff check): Findet Style-Probleme + Bugs + Code-Smells
  3. Type Checker (pyright): Validiert Typ-Sicherheit

10.5 Häufige Verwirrung geklärt

F: “Ist Linting dasselbe wie PEP 8-Prüfung?” A: Nein. Linting beinhaltet PEP 8-Checks, prüft aber auch auf Bugs, Best Practices und Code-Smells. PEP 8 ist nur ein Standard, gegen den Linters prüfen.

F: “Brauche ich sowohl ruff check als auch ruff format?” A: Ja! Sie dienen unterschiedlichen Zwecken:

F: “Warum brauche ich Pyright, wenn Ruff Code-Qualität prüft?” A: Ruff prüft Style und allgemeine Bugs. Pyright prüft Typ-Sicherheit. Beispiel:

def greet(name: str) -> str:
    return f"Hello, {name}"

result = greet(42)  # Ruff wird das nicht fangen, Pyright schon!

F: “Kann Ruff alles automatisch beheben?” A: Nein. ruff format behebt Style. ruff check --fix behebt einige Probleme (wie ungenutzte Imports). Aber logische Bugs und Benennungsverstöße brauchen manuelle Fixes.

F: “Sind Type Hints erforderlich?” A: Nein, Python funktioniert ohne sie gut. Aber sie:

F: “Wenn ich PEP 8 befolge, warum brauche ich dann Tools?” A: Menschen machen Fehler und übersehen Dinge. Tools:


10.6 Das vollständige Bild

Der Qualitäts-Stack für Python in 2025:

┌───────────────────────────────────────────┐
│      Entwickler schreibt Code             │
│         (mit Type Hints)                  │
└─────────────────┬─────────────────────────┘
                  │
        ┌─────────┴─────────┐
        │                   │
        ▼                   ▼
┌───────────────┐   ┌──────────────────┐
│  Ruff         │   │  Pyright         │
│               │   │                  │
│ • Prüft Style │   │ • Prüft Typen    │
│ • Format Code │   │ • Leitet Typen ab│
│ • Findet Bugs │   │ • Findet None-   │
│ • Best Pract. │   │   Probleme       │
└───────────────┘   └──────────────────┘
        │                   │
        └─────────┬─────────┘
                  │
                  ▼
        ┌─────────────────┐
        │  Qualitätscode  │
        │                 │
        │ ✓ PEP 8         │
        │ ✓ Weniger Bugs  │
        │ ✓ Typsicher     │
        │ ✓ Konsistent    │
        └─────────────────┘

Zusammenfassung in einem Satz: Wir verwenden PEP 8 als unseren Style Guide, Ruff um ihn durchzusetzen und Bugs zu fangen, und Pyright um Typ-Sicherheit zu gewährleisten—drei komplementäre Schichten der Qualitätssicherung.


11. Praktische Aufgabe

11.1 Aufgabe: Road Profile Viewer reparieren

Lassen Sie uns alle Probleme in unserer main.py-Datei Schritt für Schritt beheben.

11.2 Schritt 1: Ungenutzte Imports entfernen

Vorher:

import sys,os  # Mehrere Imports, beide ungenutzt

Nachher:

# Entfernt - nicht benötigt

11.3 Schritt 2: Import-Formatierung beheben

Vorher:

import numpy as np
from dash import Dash, html, dcc, Input, Output
import plotly.graph_objects as go

Nachher:

import numpy as np
from numpy.typing import NDArray

from dash import Dash, Input, Output, dcc, html
import plotly.graph_objects as go

Beachten Sie:

11.4 Schritt 3: Funktionsabstände beheben

Vorher:

def generate_road_profile(num_points=100,x_max=80):
    y=0.015 * x_norm**3 * x_max
    return x,y

Nachher:

def generate_road_profile(num_points=100, x_max=80):
    y = 0.015 * x_norm**3 * x_max
    return x, y

11.5 Schritt 4: Type Hints hinzufügen

Vorher:

def generate_road_profile(num_points=100, x_max=80):
    """Generate a road profile using a clothoid-like approximation."""
    # ...
    return x, y

Nachher:

def generate_road_profile(
    num_points: int = 100,
    x_max: float = 80
) -> tuple[NDArray[np.float64], NDArray[np.float64]]:
    """
    Generiert ein Straßenprofil mit einer Klothoiden-ähnlichen Approximation.
    
    Args:
        num_points: Anzahl der zu generierenden Punkte
        x_max: Maximaler x-Koordinatenwert
        
    Returns:
        Tupel von (x_koordinaten, y_koordinaten) als NumPy-Arrays
    """
    # ...
    return x, y

11.6 Schritt 5: Namenskonvention beheben

Vorher:

def HelperFunction(val):
    result=val*2
    return result

Nachher:

# Entfernt - Funktion war ungenutzter toter Code

11.7 Schritt 6: Variablenabstände beheben

Vorher:

camera_x,camera_y = 0,2.0
marker=dict(size=12,color='red',symbol='circle')

Nachher:

camera_x, camera_y = 0, 2.0
marker = dict(size=12, color='red', symbol='circle')

11.8 Schritt 7: Lange Zeilen beheben

Vorher:

# Add camera ray - This is a very long comment that exceeds the recommended 79 character line length limit specified in PEP8 style guide

Nachher:

# Füge Kamerastrahl zum Plot hinzu
# Dies zeigt die Linie von der Kamera in Richtung des angegebenen Winkels

11.9 Checks nach Fixes ausführen

$ uv run ruff check .
All checks passed!

$ uv run ruff format --check .
All files formatted correctly!

$ uv run pyright
0 errors, 0 warnings, 0 informations

Erfolg! 🎉


12. Teil 9: Der Business Case für Code-Qualität

12.1 Warum sich Unternehmen für Code-Qualität interessieren

1. Schnellere Entwicklung

2. Weniger Bugs

3. Niedrigere Wartungskosten

4. Bessere Zusammenarbeit

5. Wettbewerbsvorteil

12.2 Reale Auswirkung: Eine Fallstudie

Szenario: Ein Startup mit 20 Entwicklern.

Ohne automatisierte Qualitätschecks:

Mit automatisierten Qualitätschecks:

Ersparnis: 123.500€ pro Jahr

Plus immaterielle Vorteile:


13. Teil 10: Häufige Fallstricke und wie man sie vermeidet

13.1 Fallstrick 1: “Ich füge Qualitätschecks später hinzu”

Das Problem: Qualitätschecks zu einer bestehenden Codebasis mit Tausenden Verstößen hinzuzufügen ist überwältigend.

Die Lösung: Beginnen Sie mit Qualitätschecks vom ersten Tag an. Machen Sie den ersten Commit zu:

  1. Projektstruktur
  2. pyproject.toml mit Ruff-Konfiguration
  3. GitHub Actions Workflow für Qualitätschecks

13.2 Fallstrick 2: “Mein Code funktioniert, warum ist Style wichtig?”

Das Problem: Fokus nur auf Funktionalität, Wartbarkeit ignorieren.

Die Lösung: Denken Sie daran: Code wird 10x mehr gelesen als geschrieben. Qualität ist eine Investition in zukünftige Produktivität.

13.3 Fallstrick 3: “Auto-Formatter machen meinen Code hässlich”

Das Problem: Persönliche Style-Präferenzen kollidieren mit automatisierten Formattern.

Die Lösung: Vertrauen Sie dem Formatter. Konsistenz im Team ist wertvoller als individuelle Präferenz.

13.4 Fallstrick 4: “Type Hints sind zu viel Arbeit”

Das Problem: Type Hints vermeiden, weil sie zusätzliche Zeit zum Schreiben brauchen.

Die Lösung: Type Hints sparen weit mehr Zeit als sie kosten, indem sie Bugs früh fangen. Beginnen Sie mit Funktionssignaturen.

13.5 Fallstrick 5: “CI/CD-Checks verlangsamen uns”

Das Problem: Fehlgeschlagene Checks als Blocker statt als Helfer sehen.

Die Lösung: Führen Sie Checks lokal vor dem Pushen aus. Verwenden Sie Pre-commit-Hooks. CI wird ein Sicherheitsnetz, kein Flaschenhals.


14. Teil 11: Tools-Vergleich und Ökosystem

14.1 Die Python-Qualitäts-Tools-Landschaft

14.2 Linters: Ruff vs. Flake8 vs. Pylint

Geschwindigkeit

  • Ruff: 10-100x schneller (Rust-basiert)
  • Flake8: Moderate Geschwindigkeit (Python)
  • Pylint: Am langsamsten (am gründlichsten)
  • Gewinner: Ruff - Geschwindigkeit ermöglicht häufiges Prüfen

Regeln

  • Ruff: 800+ Regeln (umfassend)
  • Flake8: 200+ Regeln (erweiterbar mit Plugins)
  • Pylint: 300+ Regeln (opinionated)
  • Gewinner: Ruff - Am umfassendsten out of the box

Konfiguration

  • Ruff: Einfach, funktioniert mit pyproject.toml
  • Flake8: Verwendet .flake8 oder setup.cfg
  • Pylint: Komplexe .pylintrc
  • Gewinner: Ruff - Moderne Konfiguration

Auto-Fix

  • Ruff: Umfangreiche Auto-Fix-Unterstützung
  • Flake8: Begrenzt (über Plugins)
  • Pylint: Minimales Auto-Fix
  • Gewinner: Ruff - Beste Auto-Fix-Fähigkeiten

Empfehlung: Verwenden Sie Ruff für neue Projekte. Erwägen Sie Flake8 nur, wenn Sie spezifische Plugins benötigen, die in Ruff noch nicht verfügbar sind.

14.3 Formatter: Ruff Format vs. Black

Geschwindigkeit

  • Ruff Format: 10-100x schneller (Rust)
  • Black: Standardgeschwindigkeit (Python)
  • Gewinner: Ruff Format - Signifikant schneller

Style

  • Ruff Format: Kompatibel mit Black
  • Black: Der ursprüngliche opinionated Style
  • Gewinner: Unentschieden - Nahezu identische Ausgabe

Konfiguration

  • Ruff Format: Teil der vereinheitlichten Ruff-Konfiguration
  • Black: Separate Konfiguration
  • Gewinner: Ruff Format - Ein Tool, eine Konfiguration

Stabilität

  • Ruff Format: Neuer (2023+), schnell stabilisierend
  • Black: Ausgereift (2018+), kampferprobt
  • Gewinner: Black für ultra-konservative Projekte, Ruff Format für moderne Entwicklung

Empfehlung: Verwenden Sie Ruff Format für vereinheitlichtes Tooling. Bleiben Sie nur bei Black, wenn Sie spezifische Kompatibilitätsanforderungen haben.

14.4 Type Checker: Pyright vs. mypy

Geschwindigkeit

  • Pyright: 5-10x schneller (TypeScript/Node.js)
  • mypy: Standardgeschwindigkeit (Python)
  • Gewinner: Pyright - Viel schneller bei großen Codebasen

IDE-Integration

  • Pyright: In VS Code Pylance eingebaut
  • mypy: Benötigt separate Extension
  • Gewinner: Pyright - Nahtlose VS Code-Erfahrung

Type Inference

  • Pyright: Intelligentere Inferenz
  • mypy: Gute Inferenz, weniger ausgeklügelt
  • Gewinner: Pyright - Besser beim Ableiten komplexer Typen

Reife

  • Pyright: Neuer (2019+), Microsoft-unterstützt
  • mypy: Älter (2012+), weit verbreitet
  • Gewinner: mypy für Legacy-Projekte, Pyright für neue Projekte

Empfehlung: Verwenden Sie Pyright, wenn Sie VS Code verwenden. Verwenden Sie mypy, wenn Sie bestehende mypy-Konfiguration haben oder spezifische Plugins benötigen.


15. Zusammenfassung: Wichtige Erkenntnisse

15.1 Funktionierender Code ≠ Qualitätscode

Code, der läuft, ist erst der Anfang. Professionelle Software muss sein:

15.2 Qualitätschecks automatisieren

Verlassen Sie sich nicht auf Menschen, um Style-Probleme zu fangen:

15.3 Folgen Sie PEP 8

Pythons Style Guide ist nicht optional:

15.4 Type Hints sind Ihr Freund

Type Hints fangen Bugs, bevor sie die Produktion erreichen:

15.5 Qualität einbauen, nicht nachträglich anbringen

Qualität ist keine Phase—es ist eine Praxis:

15.6 Der ROI ist real

Automatisierte Qualitätschecks sparen Zeit und Geld:


16. Praktische Aufgabe

16.1 Aufgabe: Road Profile Viewer reparieren

  1. Repository klonen:
    git clone https://github.com/your-username/road-profile-viewer.git
    cd road-profile-viewer
    
  2. Umgebung einrichten:
    uv sync --dev
    
  3. Qualitätschecks ausführen:
    uv run ruff check .
    uv run ruff format --check .
    uv run pyright
    
  4. Alle Probleme beheben:
    • Ungenutzte Imports entfernen
    • Abstandsverstöße beheben
    • Namenskonventionen korrigieren
    • Toten Code entfernen
    • Type Hints zu allen Funktionen hinzufügen
  5. Fixes verifizieren:
    uv run ruff check .  # Sollte 0 Fehler zeigen
    uv run ruff format --check .  # Sollte alle Dateien OK zeigen
    uv run pyright  # Sollte 0 Fehler zeigen
    
  6. Committen und pushen:
    git add .
    git commit -m "Fix code quality issues"
    git push origin main
    
  7. GitHub Actions verifizieren: Prüfen Sie, dass alle CI/CD-Checks auf GitHub bestehen.

17. Zusätzliche Ressourcen

17.1 Offizielle Dokumentation

17.2 Lernressourcen

17.3 Tools und Extensions


19. Referenzen

[1] PEP 8 - Style Guide for Python Code. https://www.python.org/dev/peps/pep-0008/

[2] Ruff Official Documentation. https://docs.astral.sh/ruff/

[3] Astral - Modern Python Tooling. https://astral.sh/

[4] Pyright Documentation. https://microsoft.github.io/pyright/

[5] Black - The Uncompromising Code Formatter. https://black.readthedocs.io/

[6] Flake8 Documentation. https://flake8.pycqa.org/

[7] mypy - Optional Static Typing for Python. https://mypy-lang.org/

[8] Python Type Hints - Official Documentation. https://docs.python.org/3/library/typing.html

[9] Real Python - Python Code Quality Tutorial. https://realpython.com/python-code-quality/

[10] Martin, Robert C. “Clean Code: A Handbook of Agile Software Craftsmanship.” Prentice Hall, 2008.

[11] Slatkin, Brett. “Effective Python: 90 Specific Ways to Write Better Python.” Addison-Wesley, 2019.

[12] Anaya, Mariano. “Clean Code in Python: Develop Maintainable and Efficient Code.” Packt Publishing, 2021.

[13] GitHub Actions Documentation. https://docs.github.com/en/actions

[14] pre-commit Framework. https://pre-commit.com/

[15] NumPy Type Hints Documentation. https://numpy.org/doc/stable/reference/typing.html


Hinweis: Diese Vorlesung basiert auf Python 3.12+ und dem Tooling, das ab Oktober 2025 verfügbar ist. Tool-Versionen und spezifische Features können sich im Laufe der Zeit weiterentwickeln.

© 2026 Dominik Mueller   •  Powered by Soopr   •  Theme  Moonwalk