İçeriğe geç / Skip to content / Zum Inhalt
Ahmet Balaman LogoAhmet Balaman

Einführung in OOP: Warum prozedurale Programmierung an Grenzen stößt

Ahmet Balaman
C#OOPObject-Oriented Programming.NETProgramming Fundamentals

Einführung in OOP: Mit meinem Code stimmte etwas nicht

Vor Jahren war mein erster Kontakt mit dem Programmieren einfach: Code von oben nach unten schreiben, Zeile für Zeile. Variablen deklarieren, Funktionen schreiben, aufrufen, Ergebnis erhalten. Das wirkte übersichtlich – bis die Projekte größer wurden.

Eines Tages fand ich mich in einer einzigen Datei mit 2000 Zeilen wieder. „Welche Funktion ruft welche auf?“, „Wer hat diese Variable verändert?“ – während ich mit diesen Fragen kämpfte, wurde mir klar: Hier stimmte etwas grundsätzlich nicht.

Prozedurale Programmierung: guter Start, aber …

Prozedurale Programmierung ist eigentlich ein logischer Ansatz. Stellen Sie sich ein Rezept vor:

// Procedural approach - Simple calculator
double balance = 1000;

void Deposit(double amount)
{
    balance += amount;
    Console.WriteLine($"Deposited: ${amount}, New balance: ${balance}");
}

void Withdraw(double amount)
{
    if (balance >= amount)
    {
        balance -= amount;
        Console.WriteLine($"Withdrawn: ${amount}, New balance: ${balance}");
    }
    else
    {
        Console.WriteLine("Insufficient balance!");
    }
}

// Usage
Deposit(500);
Withdraw(200);

Schön, es funktioniert. Aber was, wenn wir mehrere Konten hätten? Und wenn jedes Konto andere Eigenschaften hätte? Kreditkonten, Sparkonten, Fremdwährungskonten …

Genau hier beginnt der prozedurale Ansatz zu bröckeln.

Spaghetticode: der Albtraum aller Entwickler

Das größte Problem prozeduralen Codes: Alles hängt mit allem zusammen. Sie ändern eine Sache, und etwas anderes geht kaputt. Wir nennen das „Spaghetticode“. Können Sie bei einem Teller Spaghetti sagen, welche Nudel wohin führt? Genau so wird der Code.

// Spaghetti code example - Real-life code to avoid
string account1_owner = "John";
double account1_balance = 1000;
string account1_type = "checking";

string account2_owner = "Jane";
double account2_balance = 5000;
string account2_type = "savings";

string account3_owner = "Bob";
double account3_balance = 2500;
string account3_type = "foreign";

// Money transfer? Which one to which? Which variable to use?
// Add new account? account4, account5, account6...
// What about 100 accounts? 🤯

Je größer dieser Code wird, desto unbeherrschbarer wird er. Jede neue Funktion erhöht die Komplexität exponentiell.

In der echten Welt läuft es anders

Halten wir kurz inne. In der echten Welt gibt es Objekte:

  • Auto: Hat Farbe, Geschwindigkeit, Marke. Kann gestartet und angehalten werden.
  • Bankkonto: Hat Inhaber und Saldo. Man kann Geld einzahlen und abheben.
  • Telefon: Hat Modell und Akkustand. Kann telefonieren und Nachrichten senden.

Diese Objekte haben Eigenschaften und Verhalten (Methoden). Und das Beste: Sie sind voneinander unabhängig!

Ein Auto zu starten wirkt sich nicht auf ein anderes Auto aus. Eine Nachricht von einem Telefon zu senden leert nicht den Akku eines anderen.

Genau das leistet OOP: Sie überträgt Objekte der echten Welt in Code.

OOP: die echte Welt in den Code holen

Schreiben wir dasselbe Bankkonto-Beispiel mit objektorientierter Programmierung (OOP):

public class BankAccount
{
    // Properties
    public string AccountOwner { get; set; }
    public double Balance { get; private set; }
    public string AccountType { get; set; }
    
    // Constructor - Called when object is created
    public BankAccount(string owner, double initialBalance, string type)
    {
        AccountOwner = owner;
        Balance = initialBalance;
        AccountType = type;
    }
    
    // Behaviors (Methods)
    public void Deposit(double amount)
    {
        Balance += amount;
        Console.WriteLine($"${amount} deposited to {AccountOwner}'s account.");
    }
    
    public bool Withdraw(double amount)
    {
        if (Balance >= amount)
        {
            Balance -= amount;
            Console.WriteLine($"${amount} withdrawn from {AccountOwner}'s account.");
            return true;
        }
        Console.WriteLine("Insufficient balance!");
        return false;
    }
    
    public void ShowBalance()
    {
        Console.WriteLine($"{AccountOwner} - {AccountType}: ${Balance}");
    }
}

Wenn wir nun 100 Konten anlegen möchten:

// Each account carries its own data and behavior
BankAccount johnAccount = new BankAccount("John", 1000, "Checking");
BankAccount janeAccount = new BankAccount("Jane", 5000, "Savings");
BankAccount bobAccount = new BankAccount("Bob", 2500, "Foreign");

johnAccount.Deposit(500);
janeAccount.Withdraw(1000);
bobAccount.ShowBalance();

// Operations on John's account don't affect Jane's!

Wie sauber ist das denn? Jedes Konto lebt in seinem eigenen Universum und beeinflusst die anderen nicht.

Die vier Säulen der OOP

Bei OOP geht es nicht nur darum, Klassen zu schreiben. Dahinter stehen vier Grundprinzipien. Wir behandeln sie in den kommenden Beiträgen ausführlich, hier eine kurze Vorstellung:

1. Kapselung

Daten schützen. Die Variable Balance kann nicht direkt von außen verändert werden, sondern nur über die Methoden Deposit und Withdraw.

2. Vererbung

Codewiederholung vermeiden. Die Klassen SavingsAccount und CheckingAccount können gemeinsame Eigenschaften von BankAccount erben.

3. Polymorphie

Dieselbe Methode zeigt unterschiedliches Verhalten. Die Methode Withdraw kann bei einem Sparkonto Zinsgebühren abziehen, bei einem Girokonto dagegen nicht.

4. Abstraktion

Komplexität verbergen. Die Nutzerin ruft einfach Deposit() auf, ohne von Datenbankzugriffen, Protokollierung oder Benachrichtigungen im Hintergrund wissen zu müssen.

Welche Sprachen unterstützen OOP?

OOP ist nicht an eine Sprache gebunden. Viele moderne Sprachen unterstützen sie:

Sprache OOP-Unterstützung Anmerkungen
C# ✅ Vollständig Die OOP-orientierte Sprache von Microsoft
Java ✅ Vollständig Philosophie „Alles ist ein Objekt“
Python ✅ Vollständig Dynamische und flexible OOP
Dart ✅ Vollständig Die Sprache von Flutter
Swift ✅ Vollständig Apple-Ökosystem
JavaScript ⚠️ Prototypbasiert Klassen-Syntax kam mit ES6 hinzu
C ❌ Keine Prozedurale Sprache

In dieser Blogreihe verwenden wir C#. Warum?

  • Klare und gut lesbare Syntax
  • Vollständige OOP-Unterstützung
  • Hervorragende IDE-Unterstützung (Visual Studio, Rider)
  • Weit verbreitet in echten Projekten

Wann sollten Sie OOP einsetzen?

OOP ist kein Allheilmittel. Für kleine Skripte und einfache Automatisierungen kann prozedurales Vorgehen genügen. Aber:

OOP verwenden:

  • Wenn das Projekt wachsen wird
  • Wenn mehrere Entwickler daran arbeiten
  • Wenn Wartbarkeit und Erweiterbarkeit zählen
  • Wenn Sie Objekte der echten Welt modellieren

Prozedural genügt:

  • Einmalige Skripte
  • Kleine Automatisierungsaufgaben
  • Performancekritische hardwarenahe Abläufe

Nächster Schritt: Klasse und Objekt

In diesem Beitrag haben wir gelernt, warum es OOP gibt, wo der prozedurale Ansatz an Grenzen stößt und welche vier Grundprinzipien dahinterstehen.

Im nächsten Beitrag tauchen wir tief in die Konzepte Klasse und Objekt ein. Mit der Analogie „Backform und Kuchen“ machen wir sie greifbar.

Halten Sie Ihren Code sauber und Ihren Kopf frei! 🚀


Dies ist der erste Beitrag der Reihe „OOP mit C#“. Im weiteren Verlauf behandeln wir Klassen, Konstruktoren, Zugriffsmodifizierer und viele weitere Themen.

Kommentare