docs: Coding Standards nach externem Review korrigiert (6 Fixes)
This commit is contained in:
+37
-31
@@ -191,22 +191,20 @@ def get_game_by_id(game_id):
|
|||||||
|
|
||||||
| Regel | Richtig | Falsch |
|
| Regel | Richtig | Falsch |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `Optional` statt `X \| None` (Konsistenz) | `Optional[str]` | `str \| None` |
|
| `X \| None` (PEP 604, idiomatisch für 3.13+) | `str \| None` | `Optional[str]` |
|
||||||
| `list`/`dict` statt `List`/`Dict` (Python 3.9+) | `list[str]` | `List[str]` |
|
| `list`/`dict` statt `List`/`Dict` (Python 3.9+) | `list[str]` | `List[str]` |
|
||||||
| `Any` nur in Ausnahmefällen | `dict[str, Any]` (API-Response) | `Any` als Rückgabetyp |
|
| Generics immer parametrisieren | `dict[str, Any]` | `dict` (implizites `dict[Any, Any]`) |
|
||||||
| `-> None` bei Funktionen ohne Return | `def log(msg: str) -> None:` | `def log(msg: str):` |
|
| `-> None` bei Funktionen ohne Return | `def log(msg: str) -> None:` | `def log(msg: str):` |
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from typing import Optional, Any
|
|
||||||
|
|
||||||
# ✅ Richtig
|
# ✅ Richtig
|
||||||
def find_user(email: str) -> Optional[dict[str, Any]]:
|
def find_user(email: str) -> dict[str, object] | None:
|
||||||
"""Sucht einen User per E-Mail. Gibt None zurück, wenn nicht gefunden."""
|
"""Sucht einen User per E-Mail. Gibt None zurück, wenn nicht gefunden."""
|
||||||
...
|
...
|
||||||
|
|
||||||
# ✅ Richtig — Flask-Route
|
# ✅ Richtig — Flask-Route
|
||||||
@app.route("/api/games/<int:game_id>")
|
@app.route("/api/games/<int:game_id>")
|
||||||
def get_game(game_id: int) -> tuple[dict, int]:
|
def get_game(game_id: int) -> tuple[dict[str, object], int]:
|
||||||
"""Gibt ein einzelnes Spiel zurück."""
|
"""Gibt ein einzelnes Spiel zurück."""
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
@@ -269,8 +267,8 @@ def berechne_durchschnitt(werteliste: list[float]) -> float:
|
|||||||
def komplexe_funktion(
|
def komplexe_funktion(
|
||||||
name: str,
|
name: str,
|
||||||
werte: list[int],
|
werte: list[int],
|
||||||
optional: Optional[str] = None,
|
optional: str | None = None,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, object]:
|
||||||
"""Kurzbeschreibung (eine Zeile).
|
"""Kurzbeschreibung (eine Zeile).
|
||||||
|
|
||||||
Ausführliche Beschreibung. Kann mehrere Sätze umfassen.
|
Ausführliche Beschreibung. Kann mehrere Sätze umfassen.
|
||||||
@@ -446,9 +444,9 @@ def search_games():
|
|||||||
|
|
||||||
### 8.1 Grundregeln
|
### 8.1 Grundregeln
|
||||||
|
|
||||||
1. **Jede neue Funktion → Test** (TDD: erst Test, dann Code)
|
1. **Jede neue Funktion → Test** (Empfehlung: TDD — erst Test, dann Code)
|
||||||
2. **80% Code Coverage** als Minimum
|
2. **80% Code Coverage** als harter Floor — unterschreiten blockiert den Commit
|
||||||
3. **pytest** als Test-Framework
|
3. **pytest** als einziges Test-Framework
|
||||||
4. **Tests in `tests/`**, spiegelt die Projektstruktur
|
4. **Tests in `tests/`**, spiegelt die Projektstruktur
|
||||||
|
|
||||||
### 8.2 Test-Struktur
|
### 8.2 Test-Struktur
|
||||||
@@ -584,7 +582,7 @@ Jeder Commit folgt dem **Conventional Commits**-Standard:
|
|||||||
feat(games): Spiele-Suche mit Volltext-Filter
|
feat(games): Spiele-Suche mit Volltext-Filter
|
||||||
fix(auth): Login bricht bei leeren Feldern nicht mehr ab
|
fix(auth): Login bricht bei leeren Feldern nicht mehr ab
|
||||||
docs: CODING_STANDARDS.md hinzugefügt
|
docs: CODING_STANDARDS.md hinzugefügt
|
||||||
chore(deps): Ruff auf 0.11.3 aktualisiert
|
chore(deps): Ruff auf 0.15.18 aktualisiert
|
||||||
```
|
```
|
||||||
|
|
||||||
### 10.2 Commit-Frequenz
|
### 10.2 Commit-Frequenz
|
||||||
@@ -608,17 +606,16 @@ pytest # Tests müssen grün sein
|
|||||||
|
|
||||||
| Tool | Zweck | Konfiguration |
|
| Tool | Zweck | Konfiguration |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **[Ruff](https://docs.astral.sh/ruff/)** | Linting + Formatierung | `pyproject.toml` → `[tool.ruff]` |
|
| **[Ruff](https://docs.astral.sh/ruff/)** | Linting + Formatierung + Sicherheit | `pyproject.toml` → `[tool.ruff]` |
|
||||||
| **[mypy](https://mypy-lang.org/)** | Statische Typ-Prüfung | `pyproject.toml` → `[tool.mypy]` |
|
| **[mypy](https://mypy-lang.org/)** | Statische Typ-Prüfung | `pyproject.toml` → `[tool.mypy]` |
|
||||||
| **[pre-commit](https://pre-commit.com/)** | Git-Hooks zur Durchsetzung | `.pre-commit-config.yaml` |
|
| **[pre-commit](https://pre-commit.com/)** | Git-Hooks zur Durchsetzung | `.pre-commit-config.yaml` |
|
||||||
| **[pytest](https://pytest.org/)** | Testing | `pyproject.toml` → `[tool.pytest.ini_options]` |
|
| **[pytest](https://pytest.org/)** | Testing + Coverage | `pyproject.toml` → `[tool.pytest.ini_options]` |
|
||||||
| **[Bandit](https://bandit.readthedocs.io/)** | Sicherheits-Scans | `pyproject.toml` → `[tool.bandit]` |
|
|
||||||
|
|
||||||
### 11.2 Quick-Start (neues Projekt)
|
### 11.2 Quick-Start (neues Projekt)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Tools installieren
|
# 1. Tools installieren
|
||||||
pip install ruff mypy pre-commit pytest bandit
|
pip install ruff mypy pre-commit pytest
|
||||||
|
|
||||||
# 2. Pre-commit-Hooks aktivieren
|
# 2. Pre-commit-Hooks aktivieren
|
||||||
pre-commit install
|
pre-commit install
|
||||||
@@ -627,26 +624,24 @@ pre-commit install
|
|||||||
ruff check . --fix
|
ruff check . --fix
|
||||||
ruff format .
|
ruff format .
|
||||||
mypy .
|
mypy .
|
||||||
pytest
|
pytest --cov --cov-fail-under=80
|
||||||
|
|
||||||
# 4. Vor jedem Commit automatisch
|
# 4. Vor jedem Commit automatisch (Ruff Lint + Format + Basic Checks)
|
||||||
git commit -m "feat: ..."
|
git commit -m "feat: ..."
|
||||||
# → Ruff prüft + formatiert automatisch
|
# → Ruff prüft + formatiert automatisch
|
||||||
# → mypy prüft die Typen
|
# → Merge-Konflikte, Whitespace, Debug-Statements werden geprüft
|
||||||
# → Bandit scannt auf Sicherheitslücken
|
# → mypy läuft nicht in pre-commit (isoliertes venv-Drift) — separat ausführen!
|
||||||
```
|
```
|
||||||
|
|
||||||
### 11.3 CI-Setup (später)
|
### 11.3 CI-Setup (später)
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# .github/workflows/quality.yml
|
# .github/workflows/quality.yml
|
||||||
- name: Lint
|
- name: Lint + Security
|
||||||
run: ruff check .
|
run: ruff check .
|
||||||
- name: Type Check
|
- name: Type Check (im echten venv!)
|
||||||
run: mypy .
|
run: mypy .
|
||||||
- name: Security Scan
|
- name: Tests + Coverage
|
||||||
run: bandit -r src/ -c pyproject.toml
|
|
||||||
- name: Tests
|
|
||||||
run: pytest --cov --cov-fail-under=80
|
run: pytest --cov --cov-fail-under=80
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -654,14 +649,17 @@ git commit -m "feat: ..."
|
|||||||
|
|
||||||
## Anhang A: Checkliste für Code Reviews
|
## Anhang A: Checkliste für Code Reviews
|
||||||
|
|
||||||
- [ ] PEP 8 eingehalten? (Ruff-Check bestanden)
|
Bei jedem Code-Review durchgehen. 🤖 = automatisch von pre-commit erzwungen.
|
||||||
|
|
||||||
|
- [ ] 🤖 PEP 8 eingehalten? (Ruff-Check bestanden)
|
||||||
- [ ] Alle Funktionen haben Typ-Annotationen? (mypy bestanden)
|
- [ ] Alle Funktionen haben Typ-Annotationen? (mypy bestanden)
|
||||||
- [ ] Docstrings auf Deutsch für alle öffentlichen Funktionen?
|
- [ ] Docstrings auf Deutsch für alle öffentlichen Funktionen?
|
||||||
- [ ] Keine Secrets im Code?
|
- [ ] Keine Secrets im Code?
|
||||||
- [ ] User-Input validiert?
|
- [ ] User-Input validiert?
|
||||||
- [ ] Tests geschrieben und grün?
|
- [ ] Tests geschrieben und grün? Coverage ≥ 80%?
|
||||||
- [ ] Keine God-Files (>500 Zeilen)?
|
- [ ] Keine God-Files (>500 Zeilen)? (manuell)
|
||||||
- [ ] Keine God-Funktionen (>50 Zeilen)?
|
- [ ] Keine God-Funktionen (>50 Statements)? (🤖 Ruff PLR0915)
|
||||||
|
- [ ] McCabe-Komplexität ≤ 10? (🤖 Ruff C901)
|
||||||
- [ ] Route enthält keine Business-Logik?
|
- [ ] Route enthält keine Business-Logik?
|
||||||
- [ ] Commit folgt Conventional Commits?
|
- [ ] Commit folgt Conventional Commits?
|
||||||
|
|
||||||
@@ -683,5 +681,13 @@ Jede Regel ist **automatisiert durchsetzbar**. Das bedeutet: Du musst sie nicht
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
> **Letzte Aktualisierung:** 21. Juni 2026
|
> **Letzte Aktualisierung:** 21. Juni 2026 (extern reviewed ✅ — 6 Fixes eingearbeitet)
|
||||||
> **Nächste Überprüfung:** Bei Projektstart oder nach 6 Monaten
|
> **Nächste Überprüfung:** Bei Projektstart oder Dezember 2026
|
||||||
|
>
|
||||||
|
> **Review-Fixes v1.0:**
|
||||||
|
> 1. Optional[X] → X | None (PEP 604, kein Ruff-Konflikt mehr)
|
||||||
|
> 2. B101 global entfernt — asserts nur in tests/ erlaubt
|
||||||
|
> 3. Bandit-Hook gestrichen — Ruffs S-Regeln reichen
|
||||||
|
> 4. C901 + PLR-Regeln aktiviert — God-Funktionen jetzt automatisch geprüft
|
||||||
|
> 5. mypy aus pre-commit entfernt (isoliertes venv-Drift)
|
||||||
|
> 6. TDD → Empfehlung, Typ-Fixes, Ruff 0.15.18, mypy 2.1.0
|
||||||
|
|||||||
Reference in New Issue
Block a user