
OOP vs Funktionale Programmierung
Programmierparadigmen sind Ansätze, wie wir Code strukturieren und darüber denken. Objektorientiert und Funktional sind die beiden am weitesten verbreiteten Paradigmen.
Objektorientierte Programmierung (OOP)
Kernkonzept
OOP bündelt Daten und Methoden, die diese Daten verarbeiten, in Objekten.
// Objektorientierter Ansatz
class BankAccount {
constructor(owner, balance) {
this.owner = owner;
this.balance = balance;
}
deposit(amount) {
this.balance += amount;
return this.balance;
}
withdraw(amount) {
if (this.balance >= amount) {
this.balance -= amount;
return this.balance;
}
throw new Error("Unzureichendes Guthaben");
}
}
const account = new BankAccount("Max", 10000);
account.deposit(5000); // 15000
account.withdraw(3000); // 12000
Vier Säulen von OOP
1. Kapselung
class User {
#password; // privates Feld
constructor(username, password) {
this.username = username;
this.#password = this.#hashPassword(password);
}
#hashPassword(password) {
return btoa(password);
}
verifyPassword(inputPassword) {
return this.#hashPassword(inputPassword) === this.#password;
}
}
2. Vererbung
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} macht ein Geräusch.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} bellt.`);
}
}
3. Polymorphismus
class Shape {
area() {
throw new Error("Implementierung erforderlich");
}
}
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}
area() {
return Math.PI * this.radius ** 2;
}
}
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
area() {
return this.width * this.height;
}
}
4. Abstraktion
class CoffeeMachine {
#water = 0;
#beans = 0;
addWater(amount) {
this.#water += amount;
}
addBeans(amount) {
this.#beans += amount;
}
makeCoffee() {
if (this.#water < 100 || this.#beans < 10) {
throw new Error("Unzureichende Zutaten");
}
this.#water -= 100;
this.#beans -= 10;
return "☕ Kaffee fertig!";
}
}
Funktionale Programmierung (FP)
Kernkonzept
FP konzentriert sich auf reine Funktionen und Unveränderlichkeit.
// Funktionaler Ansatz
const createAccount = (owner, balance) => ({
owner,
balance
});
const deposit = (account, amount) => ({
...account,
balance: account.balance + amount
});
const withdraw = (account, amount) => {
if (account.balance >= amount) {
return {
...account,
balance: account.balance - amount
};
}
throw new Error("Unzureichendes Guthaben");
};
// Verwendung (Originaldaten unverändert)
const account1 = createAccount("Max", 10000);
const account2 = deposit(account1, 5000);
const account3 = withdraw(account2, 3000);
console.log(account1.balance); // 10000 (Original erhalten)
console.log(account3.balance); // 12000
Kernprinzipien von FP
1. Reine Funktionen
// Reine Funktion (Gut)
const add = (a, b) => a + b;
add(2, 3); // Immer 5
// Unreine Funktion (Schlecht)
let total = 0;
const addToTotal = (value) => {
total += value; // Ändert externen Zustand
return total;
};
2. Unveränderlichkeit
// Schlecht: Original ändern
const numbers = [1, 2, 3];
numbers.push(4); // Ändert Original
// Gut: Neues Array erstellen
const numbers2 = [1, 2, 3];
const newNumbers = [...numbers2, 4]; // Neues Array
3. Funktionen höherer Ordnung
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);
4. Funktionskomposition
const compose = (...fns) => (x) =>
fns.reduceRight((acc, fn) => fn(acc), x);
const addOne = (x) => x + 1;
const double = (x) => x * 2;
const square = (x) => x ** 2;
const calculate = compose(square, double, addOne);
console.log(calculate(3)); // ((3 + 1) * 2) ** 2 = 64
Vergleich: Warenkorb-Implementierung
Objektorientierter Ansatz
class ShoppingCart {
constructor() {
this.items = [];
}
addItem(product, quantity) {
const existingItem = this.items.find(item => item.product.id === product.id);
if (existingItem) {
existingItem.quantity += quantity;
} else {
this.items.push({ product, quantity });
}
}
getTotal() {
return this.items.reduce((sum, item) =>
sum + (item.product.price * item.quantity), 0
);
}
}
Funktionaler Ansatz
const createCart = () => [];
const addItem = (cart, product, quantity) => {
const existingItem = cart.find(item => item.product.id === product.id);
if (existingItem) {
return cart.map(item =>
item.product.id === product.id
? { ...item, quantity: item.quantity + quantity }
: item
);
}
return [...cart, { product, quantity }];
};
const getTotal = (cart) =>
cart.reduce((sum, item) => sum + (item.product.price * item.quantity), 0);
Vor- und Nachteile
OOP-Vorteile
- Intuitiv: Einfach, reale Welt zu modellieren
- Kapselung: Datenschutz und -verbergung
- Wiederverwendbarkeit: Code-Wiederverwendung durch Vererbung
- Große Systeme: Gut für Strukturierung komplexer Systeme
OOP-Nachteile
- Zustandsverwaltung: Fehler durch Objektzustandsänderungen
- Testschwierigkeit: Komplex mit vielen Abhängigkeiten
- Parallele Verarbeitung: Gleichzeitigkeitsprobleme mit gemeinsamem Zustand
FP-Vorteile
- Vorhersagbar: Reine Funktionen geben immer gleiches Ergebnis zurück
- Einfaches Testen: Einfaches Testen ohne Nebeneffekte
- Parallele Verarbeitung: Keine Gleichzeitigkeitsprobleme mit Unveränderlichkeit
- Debugging: Einfach, Zustandsänderungen zu verfolgen
FP-Nachteile
- Lernkurve: Schwierige Konzepte
- Leistung: Speichernutzung durch Aufrechterhaltung der Unveränderlichkeit
- Realwelt-Modellierung: Einige Domänen natürlicher mit OOP
Wann welches verwenden
Wählen Sie OOP für:
- Spieleentwicklung: Charakter-, gegenstandszentrierte Objekte
- GUI-Anwendungen: Schaltflächen, Fensterkomponenten
- Simulationen: Realwelt-Modellierung
- Große Unternehmen: Komplexe Geschäftslogik
Wählen Sie FP für:
- Datentransformation: Pipeline-Verarbeitung
- Async-Verarbeitung: Promise, async/await
- Zustandsverwaltung: Redux, Zustand
- Mathematische Berechnungen: Algorithmen, Datenanalyse
Hybridansatz
Modernes JavaScript mischt beide Paradigmen.
// React: OOP + FP-Hybrid
class UserProfile extends React.Component { // OOP: Klasse
render() {
const { user } = this.props;
// FP: reine Funktion, Unveränderlichkeit
const fullName = [user.firstName, user.lastName]
.filter(Boolean)
.join(' ');
return <div>{fullName}</div>;
}
}
// Oder funktionale Komponente (bevorzugt)
const UserProfile = ({ user }) => {
const fullName = [user.firstName, user.lastName]
.filter(Boolean)
.join(' ');
return <div>{fullName}</div>;
};
| Vergleich | OOP | Funktional |
|---|---|---|
| Kernkonzept | Objekte und Zustand | Funktionen und Daten |
| Datenmutation | Erlaubt (Veränderlich) | Nicht erlaubt (Unveränderlich) |
| Code-Wiederverwendung | Vererbung | Funktionskomposition |
| Zustandsverwaltung | Interner Objektzustand | Externe Zustandsübergabe |
| Lernschwierigkeit | Einfach | Schwierig |
| Geeignete Bereiche | UI, Spiele, Simulation | Datenverarbeitung, Parallele Verarbeitung |
Es gibt keine einzige Antwort. Wählen Sie basierend auf der Situation oder mischen Sie beide. JavaScript, Python und andere moderne Sprachen unterstützen Multi-Paradigma und ermöglichen es Ihnen, die Stärken jedes Paradigmas zu nutzen.
