branch-coexist: 3 neue decks 223015b-2026 / 223015c-2026 / dhbw-2026 daneben main

per user-request einen branch der main-content UND rewrite-content trägt — saubere separierung statt symlink/merge-conflict.

struktur:
- slides/<course>/ → main-content restored, eigene assets (kein new-demo-leak)
- slides/<course>-2026/ → rewrite-content, eigene assets (komplett kopiert + new demos)

Makefile: COURSES += 223015b-2026 223015c-2026 dhbw-2026 mit eigenen NAME/KAPITEL/DEPLOY/KLAUSUR-konfig. Klausur für b+c=1, dhbw=leer. Deploy-paths /hdm/223015b-2026 etc.

make build durchlaufen für alle 6 decks, 0 fehler.

dedup: 223015c+dhbw assets identisch in beiden ordnern (kein neu-demos auf b ergänzt). 223015b 86 → 120 files in -2026 (= +34 neue eroeffner/usb-c-drei-achsen/container-vs-codec/etc).
This commit is contained in:
libretech committed 2026-05-14 21:54:15 +02:00
1 parent 6209f9f3a0
commit 351e3dfc23
467 files changed
+32391 -4701

No files matched your search

+257 -373
View File
@@ -9,469 +9,353 @@ title: Best Practices
---
<style>
:root { --color-foreground: #1a1a2e; --color-highlight: #d63384; }
section.invert { --color-foreground: #fff; }
section { font-size: 1.4rem; }
h1 { color: #a02060; }
section.invert h1 { color: #fff; }
h2 { color: #1f2937; }
pre { background: #0f0f23; color: #f48fb1; border-radius: 8px; border-left: 3px solid #d63384; }
pre code { background: transparent; color: inherit; }
code { background: #1a1a2e; color: #f48fb1; padding: 0.15em 0.4em; border-radius: 4px; }
a { color: var(--color-highlight); }
:root {
--color-foreground: #1a1a2e;
--color-highlight: #d63384;
--color-dimmed: #4a4a6a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.4rem;
}
h1 {
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937;
}
section.invert h2 {
color: #f48fb1;
}
pre {
background: #0f0f23;
color: #f48fb1;
border-radius: 8px;
border-left: 3px solid #d63384;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a1a2e;
color: #f48fb1;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: lead -->
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# Kapitel 8 — Best Practices
## Git · README · SOLID · 12-Factor · SemVer
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026** · Sitzung 10 — Wrap-up & Projektsupport
---
<!-- _class: lead -->
<!-- _class: invert -->
<!-- _backgroundColor: #000 -->
# Git-Hygiene
# Best Practices
## Wrap-up & Projektsupport
---
# Sinnvolle Commits
# Inhalt
1. Semantic Versioning
2. Git Commit Messages (Udacity Style)
3. 12 Factor App
4. Make it Work · Make it Right · Make it Fast
5. Präsentations-Tipps
6. Feedback (Sandwich-Methode)
7. Prüfungsleistung Recap
---
# Semantic Versioning (SemVer 2.0.0)
**Schlecht:**
```
fix
wip
asdf
final
final2
final-final
MAJOR.MINOR.PATCH
│ │ └─ Bugfix, abwärtskompatibel
│ └────── Neue Funktion, abwärtskompatibel
└──────────── Breaking Change
```
**Beispiele:**
- `1.4.2` → `1.4.3` Bugfix
- `1.4.3` → `1.5.0` neues Feature
- `1.5.0` → `2.0.0` Breaking Change
Pre-Release: `1.0.0-alpha.1`, `1.0.0-rc.2`
→ https://semver.org/
---
# package.json: Versionsranges
```json
{
"dependencies": {
"express": "^4.19.2", // ≥4.19.2 < 5.0.0 (gleiche MAJOR)
"lodash": "~4.17.21", // ≥4.17.21 < 4.18.0 (gleiche MINOR)
"react": "19.0.0" // exakt
}
}
```
`package-lock.json` pinnt die **tatsächlich installierten** Versionen.
---
# Git Commit Messages – Udacity Style
```
<type>: <Subject>
<blank>
<Body>
<blank>
<Footer>
```
**Type:** `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
**Subject:** Imperativ, ≤50 Zeichen, klein, kein Punkt
**Body:** **Was** und **Warum** – nicht **Wie**
**Footer:** Issue-Refs, Breaking Changes
---
# Commit-Beispiele
**Gut:**
```
fix(auth): handle expired JWT correctly
feat(api): add /users/:id/posts endpoint
docs(readme): update Docker setup instructions
test(utils): cover edge cases in greet()
feat: add user logout endpoint
Allows authenticated clients to invalidate their session token
on the server side instead of only deleting the cookie.
Closes #142
```
**Eine Commit-Message = Was + Warum, nicht Wie.**
**Schlecht:**
```
fixed stuff
WIP
update
asdf
```
→ https://udacity.github.io/git-styleguide/
---
# Conventional Commits
```
<type>(<scope>): <subject>
[optional body]
[optional footer]
feat(auth): add OAuth2 login
fix(api): return 404 instead of 500 on missing user
docs: update README install steps
chore(deps): bump express from 4.18 to 4.19
BREAKING CHANGE: drop Node 16 support
```
**Types:**
- `feat:` neue Funktion
- `fix:` Bugfix
- `docs:` Doku
- `refactor:` Code-Restrukturierung
- `test:` Tests
- `chore:` Build/Tools
- `perf:` Performance
- `style:` Formatierung
Automatisches Changelog + SemVer-Bump möglich.
Vorteile: automatische Changelogs, automatische Version-Bumps (`semantic-release`).
---
# .gitignore — was nie rein gehört
# 12 Factor App
```
# Dependencies + Build
node_modules/
dist/
build/
.cache/
Methodik für moderne, skalierbare SaaS-Apps – https://12factor.net/
# Secrets
.env
.env.local
*.pem *.key
# Editor + OS
.vscode/ .idea/
.DS_Store
# Logs
*.log
```
Vorlagen: [github.com/github/gitignore](https://github.com/github/gitignore)
| # | Faktor |
|---|--------|
| 1 | Codebase – ein Repo, viele Deploys |
| 2 | Dependencies – explizit deklariert (`package.json`) |
| 3 | Config – via Environment-Variablen |
| 4 | Backing Services – als Attached Resources |
| 5 | Build, Release, Run – getrennt |
| 6 | Processes – stateless |
---
# Branches + PRs
# 12 Factor (2/2)
```sh
# Neuer Feature-Branch
git checkout -b feat/user-profile
# Arbeit, Commits
git add .
git commit -m "feat(profile): add avatar upload"
# Push + PR
git push -u origin feat/user-profile
# → PR via GitHub/Gitea-UI
# Nach Merge: aufräumen
git checkout main
git pull
git branch -d feat/user-profile
```
**Faustregel:** kurzlebige Branches (Tage, nicht Monate).
| # | Faktor |
|---|--------|
| 7 | Port Binding – self-contained, exportiert HTTP |
| 8 | Concurrency – horizontal skalieren via Prozesse |
| 9 | Disposability – schneller Start, Graceful Shutdown |
| 10 | Dev/Prod Parity – möglichst gleiche Umgebung |
| 11 | Logs – als Event-Streams (`stdout`) |
| 12 | Admin Processes – als One-Off |
---
<!-- _class: lead -->
# README
---
# README — das Visitenkarten-Dokument
Wenn jemand euer Projekt im Browser sieht: **die README ist die erste und oft einzige Berührung.**
Schlechte README = Repo nicht verwendet.
**Eine gute README beantwortet:**
1. Was tut das Projekt?
2. Wie installiere ich es?
3. Wie starte ich es?
4. Wie teste ich es?
5. Wie deploye ich es?
6. Lizenz?
---
# README-Template
```markdown
# Mein Projekt
> Eine Zeile Beschreibung.
## Features
- ✓ etwas
- ✓ etwas anderes
## Setup
```sh
git clone https://...
cd projekt
cp .env.example .env
npm install
npm run dev
```
## Tests
```sh
npm test
npm run test:e2e
```
## Stack
Node 24, Express, SQLite, Vitest.
## License
MIT
```
---
<!-- _class: lead -->
# SOLID — OO-Prinzipien
---
# SOLID — die fünf
| | Prinzip | Bedeutung |
|--|---------|-----------|
| **S** | Single Responsibility | jede Klasse/Modul = eine Verantwortung |
| **O** | Open / Closed | offen für Erweiterung, geschlossen für Änderung |
| **L** | Liskov Substitution | Subtyp ersetzbar durch Basistyp |
| **I** | Interface Segregation | kleine, fokussierte Interfaces |
| **D** | Dependency Inversion | abhängig von Abstraktionen |
Robert C. Martin („Uncle Bob"), 2000er.
---
# S — Single Responsibility
# Config via ENV
```javascript
// Schlecht — alles in einer Klasse
class UserManager {
validate() { /* ... */ }
saveToDb() { /* ... */ }
sendEmail() { /* ... */ }
generateReport() { /* ... */ }
}
// schlecht
const db = "postgres://user:secret@prod-db:5432/app";
// Besser — getrennte Verantwortlichkeiten
class UserValidator { /* ... */ }
class UserRepository { /* ... */ }
class EmailService { /* ... */ }
class ReportGenerator { /* ... */ }
// gut
const db = process.env.DATABASE_URL;
```
---
# D — Dependency Inversion
```javascript
// Schlecht — direkt von konkreter Klasse
class OrderService {
charge(order) {
const stripe = new StripeClient();
stripe.charge(order.amount);
}
}
// Besser — Abhängigkeit injizieren
class OrderService {
constructor(paymentProvider) {
this.payment = paymentProvider;
}
charge(order) {
this.payment.charge(order.amount);
}
}
new OrderService(new StripeClient()); // im Production
new OrderService(new MockClient()); // im Test
```bash
# .env (NICHT committen!)
DATABASE_URL=postgres://user:secret@db:5432/app
NODE_ENV=production
PORT=8080
```
---
<!-- _class: lead -->
# 12-Factor App
`.env.example` mit Dummy-Werten committen.
---
# 12-Factor — die wichtigsten
| # | Faktor | Was |
|---|--------|-----|
| 1 | Codebase | ein Repo pro App, mehrere Deploys |
| 2 | Dependencies | explizit deklariert (package.json) |
| 3 | **Config** | über Environment Variables, nicht im Code |
| 4 | Backing Services | als Resources behandeln (z.B. DB-URL) |
| 6 | **Processes** | stateless |
| 9 | Disposability | schnell startbar + stoppbar |
| 12 | Admin Processes | als One-Off im selben Stack |
Heroku, 2011. Heute Industrie-Standard für Cloud-Apps.
---
# Factor 3 — Config in env
```javascript
// SCHLECHT — Hardcoded
const db = new Pool({ host: 'localhost', user: 'dev' });
// GUT — aus env
const db = new Pool({
connectionString: process.env.DATABASE_URL,
});
```
`.env` lokal, **Environment-Variablen** auf Server. Gleicher Code überall.
---
# Factor 6 — Stateless Processes
**Schlecht:** Session-State im RAM.
```javascript
const sessions = new Map(); // pro Server-Instanz!
```
→ Load-Balancer mit 2 Servern: User-Session geht verloren beim 2. Request.
**Gut:** State in DB / Redis.
```javascript
await redis.set(`session:${id}`, JSON.stringify(data));
```
Server-Restart → kein Datenverlust. Horizontale Skalierung möglich.
---
<!-- _class: lead -->
# SemVer — semantisches Versioning
---
# SemVer — Format
# Make It Work · Right · Fast
```
MAJOR.MINOR.PATCH
1 . 4 . 3
1. Make It Work → MVP, hässlich aber funktional
2. Make It Right → Refactor, Tests, Clean Code
3. Make It Fast → Profiling, Optimierung
```
| Teil | Bump bei |
|------|----------|
| **MAJOR** | breaking change (API-incompatible) |
| **MINOR** | neues Feature (rückwärts-kompatibel) |
| **PATCH** | Bugfix (rückwärts-kompatibel) |
Don't optimize what doesn't work.
Don't refactor what isn't working yet.
**Pre-Release:** `1.0.0-beta.1`, `1.0.0-rc.2`.
→ https://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast
---
# SemVer in package.json
# KISS · DRY · YAGNI · SOLID
```json
{
"dependencies": {
"express": "^5.0.0", // ≥ 5.0.0, < 6.0.0
"lodash": "~4.17.0", // ≥ 4.17.0, < 4.18.0
"react": "5.2.1", // exakt
"vite": "*" // jede (vermeiden)
}
}
```
- **KISS** – Keep It Simple, Stupid
- **DRY** – Don't Repeat Yourself
- **YAGNI** – You Aren't Gonna Need It
- **SOLID**:
- **S**ingle Responsibility
- **O**pen/Closed
- **L**iskov Substitution
- **I**nterface Segregation
- **D**ependency Inversion
**Faustregel:** `^` (Caret) ist Default — major-version-lock.
→ Faustregeln, keine Dogmen.
---
<!-- _class: lead -->
# Präsentation – Aufbau
# Code-Reviews
- **Einstieg** mit aktuellem Bezug (optional)
- **Problemdefinition**: welches Bedürfnis / welches Problem?
- Was hat **blockiert**, wie gelöst?
- **Geschichte mit Spannungsbogen**
- Vorher klären: Fragen während oder nach der Präsentation?
---
# Constructive Code-Reviews
# Präsentation – Pitfalls
**Geben:**
- Konkret: Zeilennummern + Beispiel
- Wertschätzend: gut gemachte Stellen erwähnen
- Fragend statt fordernd: „Wäre `X` hier robuster?"
- Klar zwischen MUST/SHOULD/CONSIDER unterscheiden
- Am Thema vorbeireden
- Folien vorlesen
- Live-Demo ohne Backup-Video
- "Sieht man hier nicht so gut, aber..."
- Zu viel Text pro Folie
- Keine klare Botschaft pro Slide
**Nehmen:**
- Egoless: Code ≠ Person
- Frage zurück bei Unklarheit
- Bedanken für detaillierte Feedback
→ **1 Folie = 1 Aussage.**
---
# Code-Review-Checkliste
# Feedback – Sandwich-Methode
| Bereich | Was prüfen |
|---------|------------|
| **Correctness** | macht's, was es soll? Edge-cases? |
| **Readability** | Namen, Struktur, Kommentare? |
| **Tests** | abgedeckt? Sinnvolle Assertions? |
| **Security** | Input-Validation, Secrets, Auth |
| **Performance** | N+1, Sync-IO, Memory-Leak |
| **A11y** (Frontend) | Semantik, Kontrast, Keyboard |
| **Doku** | README aktualisiert? CHANGELOG? |
1. **Eröffnung** — Lob / positive Beobachtungen
2. **Kern** — Kritik + konkreter Verbesserungsvorschlag
3. **Abschluss** — Lob / wertschätzender Ausklang
**Pitfalls:**
- Am Thema vorbeireden
- Bei Unklarheiten keine Fragen stellen
- Subjektives Feedback ("Farbe gefällt mir nicht")
→ **Konkret, sachlich, umsetzbar.**
---
<!-- _class: lead -->
# Prüfungsleistung – Recap
# Doku lesen lernen
**Grundanforderungen (75 Punkte):**
| Punkte | Kriterium |
|--------|-----------|
| 20 | Idee, Konzeption, Planung |
| 5 | Plattformunabhängigkeit |
| 25 | Clean Code (KISS, SOLID, DI, Testing, Error Handling) |
| 15 | Präsentation |
| 10 | Dokumentation (README, etc.) |
**Zusatzpunkte (max. 10):** TypeScript, Docker, Dev/Prod-Parity, `.env`, npm-Publish, Domain, HTTPS, Responsive Design.
→ https://librete.ch/DHBW/pruefungsleistung
---
# Wo finde ich was?
# Abgabe + Termine
| Ziel | Quelle |
|------|--------|
| Web-APIs (HTML, CSS, JS) | **MDN** — developer.mozilla.org |
| Node-APIs | **nodejs.org/docs** |
| npm-Package | `npmjs.com/package/<name>` + GitHub README |
| Sprach-Standards (ES) | **tc39.es** |
| Browser-Kompatibilität | **caniuse.com** |
| Fehler-Suche | Stack Overflow + GitHub Issues |
**Faustregel:** offizielle Doku zuerst, dann Stack Overflow.
- **Code-Upload:** bis 27.07.
- **Präsentation:** 17.07. (in Gruppen, ~10 Min)
- Pitch (~1 Min)
- Agenda
- Idee / Problem
- Learnings & Pitfalls
- "It is what it is" – Doku
---
# Stack Overflow gut nutzen
# 70 Things I Regret as a Developer (Auswahl)
**Bevor du fragst:**
- Existiert die Frage schon? (Suche oben)
- Gibt es ein Minimal-Reproduction-Beispiel?
- Welche Versionen (Node, OS, Library)?
- Was hast du schon versucht?
- Nicht früher Tests geschrieben zu haben
- Zu viel Zeit mit "perfektem" Setup statt Code
- Nicht öfter `git commit`
- Nicht früher in Pull Requests reviewt
- Keine Doku gepflegt
- Eigene Lösungen für Standard-Probleme
- Frameworks gehyped, Grundlagen vernachlässigt
- "Funktioniert bei mir" akzeptiert
**Bei der Frage:**
- Konkreter Titel (nicht "JavaScript Hilfe")
- Code-Block für Code
- Was war erwartet, was passiert
- Error-Message als Text (nicht Screenshot)
→ Lehre: **Disziplin > Talent.**
---
# AI-Assistenten (ChatGPT, Claude, Copilot)
# Weiterlesen
**Pro:**
- Schneller Antworten zu allgemeinen Fragen
- Boilerplate-Code in Sekunden
- Erklärung fremden Codes
**Contra:**
- Halluziniert APIs, die nicht existieren
- Verstärkt Anti-Patterns aus dem Training
- Lernkurve geht zurück, wenn nur kopiert wird
**Faustregel:** als Sparring-Partner, nicht als Wahrheitsquelle. **Verstehen, nicht kopieren.**
- https://12factor.net/
- https://semver.org/
- https://udacity.github.io/git-styleguide/
- https://www.conventionalcommits.org/
- https://refactoring.guru/
- https://martinfowler.com/
- MDN Web Docs · web.dev · web.dev/learn
---
<!-- _class: aufgabe -->
<!-- _class: invert -->
<!-- _backgroundColor: #000 -->
# Selbstlernen — Projekt-Hygiene-Check
# Viel Erfolg mit den Projekten!
Geht euer Projekt durch:
1. **README:** hat alle 6 Sektionen?
2. **.gitignore:** komplett, keine Secrets im Repo?
3. **Conventional Commits:** letzte 10 Commits durchgehen
4. **package.json:** `version`, `description`, `scripts`?
5. **Tests:** Coverage > 70 %?
6. **Dockerfile + compose.yml:** funktionieren?
7. **Environment:** `.env.example` vorhanden, `.env` gitignored?
**Bonus:** GitHub-Actions-Workflow für Tests + Build.
---
# Abschluss
**Über 8 Termine gelernt:**
1. Web Engineering — Foundation
2. CSS Extended — Layout + Animation
3. Node.js Basics — Runtime + REST
4. Node.js Advanced — async + DB + Auth
5. Testing — Unit + Integration + E2E
6. TypeScript — Typen + Schemas
7. Docker — Container + compose
8. Best Practices — Git + README + SOLID + 12-Factor
**Nächste Schritte:** eigenes Projekt für die Prüfungsleistung. Code-Abgabe + Präsentation.
Fragen? Probleme? → Telegram, Mail, Sprechstunde.