Part 7

Programmierparadigmen

Hinweis: Bitte beachten Sie, dass die Vorlesungen ergänzende Inhalte und besondere Schwerpunkte bieten, die über den Text dieser Webseite hinausgehen. Obwohl die Webseite ausführliche Informationen bereitstellt, werden in der Vorlesung spezielle Themen vertieft behandelt und zusätzliche Einblicke gegeben. Um ein umfassendes Verständnis des Stoffes zu erlangen und die in der Vorlesung besprochenen Aspekte vollständig zu erfassen, empfehlen wir Ihnen insbesondere, an den Vorlesungen teilzunehmen.

Ein Programmierparadigma ist eine Art und Weise, über die Struktur und Funktionalität eines Programms nachzudenken und diese zu gestalten. Programmierparadigmen unterscheiden sich zum Beispiel darin, wie die Ausführung und Steuerung des Programms definiert werden und aus welchen Komponenten die Programme bestehen.

Die meisten derzeit verwendeten Programmiersprachen unterstützen mehrere Programmierparadigmen. Ein Teil des Wachstums eines Programmierenden besteht darin, durch Erfahrung die geeignete Programmiersprache und das passende Paradigma zu wählen; es gibt derzeit keine universelle Programmiersprache und kein einziges Programmierparadigma.

Die häufigsten Programmierparadigmen heutzutage sind objektorientierte Programmierung, prozedurale Programmierung und funktionale Programmierung. Die ersten beiden dieser Paradigmen werden im Folgenden kurz behandelt.

Objektorientierte Programmierung

In der objektorientierten Programmierung wird Information in Form von Klassen dargestellt, die die Konzepte des Problembereichs und die Logik der Anwendung beschreiben. Klassen definieren die Methoden, die festlegen, wie Informationen verarbeitet werden. Während der Programmausführung werden Objekte aus Klassen instanziiert, die Laufzeitinformationen enthalten und die Programmausführung beeinflussen: Die Programmausführung erfolgt typischerweise durch eine Reihe von Methodenaufrufen, die sich auf die Objekte beziehen. Wie vor einigen Wochen erwähnt, "wird das Programm aus kleinen, klaren und kooperativen Einheiten aufgebaut."

Die Grundideen der objektorientierten Programmierung, d. h. die Darstellung von Informationen und deren Verarbeitungsmethoden mithilfe von Klassen und Objekten, erschienen erstmals in Simula 67, das für die Entwicklung von Simulationen entwickelt wurde, und in der Programmiersprache Smalltalk. Ihren Durchbruch erlangte die objektorientierte Programmierung in den 1980er Jahren durch die Programmiersprache C++, und durch Java hat sie sich zu einem der weltweit am häufigsten verwendeten Programmierparadigmen entwickelt.

Einer der großen Vorteile der objektorientierten Programmierung ist die Modellierung von Problembereichskonzepten durch Klassen und Objekte, was Programme leichter verständlich macht. Darüber hinaus erleichtert die Strukturierung des Problembereichs in Klassen den Aufbau und die Wartung von Programmen. Allerdings ist die objektorientierte Programmierung nicht von Natur aus für alle Probleme geeignet: Zum Beispiel werden in wissenschaftlichen Berechnungen und Statistik-Anwendungen typischerweise Sprachen wie R und Python verwendet.

Prozedurale Programmierung

Während in der objektorientierten Programmierung die Struktur eines Programms durch die Daten bestimmt wird, die es verarbeitet, wird in der prozeduralen Programmierung die Struktur des Programms durch die gewünschte Funktionalität des Programms bestimmt: Das Programm fungiert als schrittweise Anleitung für die auszuführende Funktionalität. Das Programm wird Schritt für Schritt ausgeführt, und bei Bedarf werden Unterprogramme (Methoden) aufgerufen.

In der prozeduralen Programmierung wird der Zustand des Programms in Variablen und Tabellen gehalten, und die Methoden verarbeiten nur die ihnen als Parameter übergebenen Werte. Das Programm sagt dem Computer, was geschehen soll. Zum Beispiel zeigt der folgende Code, wie die Werte von zwei Variablen a und b vertauscht werden.

int a = 10;
int b = 15;

// let's swap the values of variables a and b
int c = b;
b = a;
a = c;

Beim Vergleich der objektorientierten Programmierung mit der prozeduralen Programmierung treten einige wesentliche Unterschiede zutage. In der objektorientierten Programmierung kann sich der Zustand eines Objekts im Prinzip bei jeder Objektmethode ändern, und diese Zustandsänderung kann auch die Funktionsweise der Methoden anderer Objekte beeinflussen. Infolgedessen können auch andere Aspekte der Programmausführung betroffen sein, da Objekte an mehreren Stellen im Programm verwendet werden können.

Der Unterschied zwischen objektorientierter Programmierung und prozeduraler Programmierung wird im konkreten Beispiel der Uhr, das zu Beginn von Teil Fünf vorgestellt wurde, deutlich. Die folgende Lösung zeigt einen prozeduralen Stil, bei dem die Ausgabe der Zeit in eine Methode ausgelagert wird.

int hours = 0;
int minutes = 0;
int seconds = 0;

while (true) {
    // 1. printing the time
    print(hours, minutes, seconds);
    System.out.println();

    // 2. advancing the second hand
    seconds = seconds + 1;

    // 3. advancing the other hands when necessary
    if (seconds > 59) {
        minutes = minutes + 1;
        seconds = 0;

        if (minutes > 59) {
            hours = hours + 1;
            minutes = 0;

            if (hours > 23) {
                hours = 0;
            }
        }
    }
}
public static void print(int hours, int minutes, int seconds) {
    print(hours);
    print(minutes);
    print(seconds);
}

public static void print(int value) {
    if (value < 10) {
        System.out.print("0");
    }
    System.out.print(value);
}

Die gleiche Implementierung in objektorientierter Weise:

public class Hand {
    private int value;
    private int upperBound;

    public Hand(int upperBound) {
        this.upperBound = upperBound;
        this.value = 0;
    }

    public void advance() {
        this.value = this.value + 1;

        if (this.value >= this.upperBound) {
            this.value = 0;
        }
    }

    public int value() {
        return this.value;
    }

    public String toString() {
        if (this.value < 10) {
            return "0" + this.value;
        }

        return "" + this.value;
    }
}
public class Clock() {
    private Hand hours;
    private Hand minutes;
    private Hand seconds;

    public Clock() {
        this.hours = new Hand(24);
        this.minutes = new Hand(60);
        this.seconds = new Hand(60);
    }

    public void advance() {
        this.seconds.advance();

        if (this.seconds.value() == 0) {
            this.minutes.advance();

            if (this.minutes.value() == 0) {
                this.hours.advance();
            }
        }
    }

    public String toString() {
        return hours + ":" + minutes + ":" + seconds;
    }
}
Clock clock = new Clock();

while (true) {
    System.out.println(clock);
    clock.advance();
}
Sie haben das Ende dieses Abschnitts erreicht! Weiter zum nächsten Abschnitt: