SOLID-Prinzipien in TypeScript: Theorie und Praxis von A bis Z

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum SOLID für TypeScript-Entwickler wichtig ist

SOLID sind fünf fundamentale Prinzipien der objektorientierten Programmierung, formuliert von Robert C. Martin (Uncle Bob). Im Kontext von TypeScript, das statische Typisierung mit der Flexibilität von JavaScript kombiniert, ermöglicht die Anwendung der SOLID-Prinzipien die Erstellung skalierbarer, testbarer und leicht wartbarer Anwendungen. In diesem Artikel analysieren wir jedes Prinzip mit theoretischer Grundlage und praktischen Beispielen in TypeScript.



1. Single Responsibility Principle (SRP) — Prinzip der einzigen Verantwortung

Theorie

Eine Klasse sollte nur einen einzigen Grund für eine Änderung haben. Das bedeutet, dass jedes Modul, jede Klasse oder Funktion für genau eine Funktionalität verantwortlich ist.



Praxis in TypeScript

Betrachten wir eine Verletzung des SRP am Beispiel einer Klasse, die Benutzer verwaltet und Benachrichtigungen versendet:



// ❌ Verletzung des SRPclass UserManager {  constructor(private name: string, private email: string) {}

saveUser(): void { console.log(`Benutzer ${this.name} in der DB gespeichert`); }

sendWelcomeEmail(): void { console.log(`Willkommens-E-Mail an ${this.email} gesendet`); }}


Korrigierte Version mit getrennter Verantwortung:



// ✅ Einhaltung des SRPclass User {  constructor(public name: string, public email: string) {}}

class UserRepository { save(user: User): void { console.log(`Benutzer ${user.name} in der DB gespeichert`); }}

class EmailService { sendWelcomeEmail(user: User): void { console.log(`Willkommens-E-Mail an ${user.email} gesendet`); }}


2. Open/Closed Principle (OCP) — Prinzip der Offenheit/Geschlossenheit

Theorie

Software-Entitäten sollten offen für Erweiterungen, aber geschlossen für Modifikationen sein. Mit anderen Worten: Sie sollten in der Lage sein, neue Funktionalität hinzuzufügen, ohne vorhandenen Code zu ändern.



Praxis in TypeScript

Beispiel mit Rabattberechnung für verschiedene Kundentypen:



// ❌ Verletzung des OCPclass DiscountCalculator {  calculateDiscount(customerType: string, amount: number): number {    if (customerType === 'regular') {      return amount * 0.1;    } else if (customerType === 'premium') {      return amount * 0.2;    } else if (customerType === 'vip') {      return amount * 0.3;    }    return 0;  }}


// ✅ Einhaltung des OCP durch Polymorphieinterface DiscountStrategy {  calculate(amount: number): number;}

class RegularDiscount implements DiscountStrategy { calculate(amount: number): number { return amount * 0.1; }}

class PremiumDiscount implements DiscountStrategy { calculate(amount: number): number { return amount * 0.2; }}

class DiscountCalculator { constructor(private strategy: DiscountStrategy) {}

calculate(amount: number): number { return this.strategy.calculate(amount); }}


3. Liskov Substitution Principle (LSP) — Prinzip der Substitution von Barbara Liskov

Theorie

Objekte in einem Programm sollten durch Instanzen ihrer Untertypen ersetzbar sein, ohne die Korrektheit des Programms zu beeinträchtigen. Einfach ausgedrückt: Wenn Sie eine Basisklasse haben, sollte jeder ihrer Ableger überall dort korrekt funktionieren, wo die Basisklasse verwendet wird.



Praxis in TypeScript

Klassisches Beispiel mit geometrischen Figuren:



// ❌ Verletzung des LSPclass Rectangle {  constructor(protected width: number, protected height: number) {}

setWidth(width: number): void { this.width = width; }

setHeight(height: number): void { this.height = height; }

getArea(): number { return this.width * this.height; }}

class Square extends Rectangle { setWidth(width: number): void { this.width = width; this.height = width; // Verletzung! }

setHeight(height: number): void

Blogs

Buchempfehlungen