Archivo Explosivo: OOP

FIAE – Objektorientierte Programmierung – Einführung

Was ist Objektorientierte Programmierung?
Laut ISO/IEC 2382:
„Ein Programmier-Stil, der Objekte, Klassen und Vererbung einsetzt.“
Nach Allen Kay (Erfinder von SmallTalk):
„Alles ist ein Objekt. Objekte kommunizieren duch das Senden und Empfangen von Nachrichten – diese Nachrichten sind wiederum Objekte. Objekte haben Ihren eigenen Speicher, jedes Objekt ist die Instanz einer Klasse (die auch wiederum ein Objekt ist). Eine Klasse beinhaltet das Verhalten aller Ihrer Instanzen (Objekte in einer Programmliste). Für das Ausführen einer Programmliste, wird die Ausführungskontrolle dem ersten Objekt gegeben und das verbleibende als dessen Nachricht behandelt“.
In 2003 revidierte Kay seine Aussage und definierte Objektorientierung folgendermaßen:
„OOP bedeutet für mich nur Messaging, lokales Beibehalten und Schützen und Verbergen des Prozesszustands sowie spätestmögliche Bindung aller Dinge.“

Als Anmerkung sei gesagt: Es existieren auch klassenlose objektorientierte Programmiersprachen (Prototypen basierend – zum Beispiel Javascript) und der Vererbung wird heutzutage weniger Bedeutung zugesprochen, als noch in den 1990ern. Deswegen gilt der erstgenannte Ansatz der ISO/IEC als veraltet.

Die Schlagworte objektorientierter Programmierung
Abstraktion: Entweder in Form von Klassen, oder in Form von Prototypen.
Klassen: Die Datenstruktur eines Objekts wird durch die Attribute einer Klassendefinition festgelegt.
Prototypen: Objekte werden durch das Klonen bereits existierender Objekte erzeugt und können als Prototypen dienen.
Datenkapselung: Die eigentlichen Implementierungsdetails bleiben bei der Ausführung verborgen. Zugriff über Schnittstellen.
Feedback: Kommunikation über einen Nachrichten-Antwort-Mechanismus. Führt zu Veränderung von Objekten.
Persistenz: Objektvariablen existieren, solange die Objekte vorhanden sind und verfallen nicht automatisch nach Abarbeitung einer Methode.
Polymorphie: Unterschiedliche Datentypen können angenommen und verarbeitet werden.
Vererbung: Eine abgeleitete Klasse „erbt“ die Methoden und Attribute der Basisklasse.

Als absolute Basis objektorientierter Programmiersprachen gelten:
Vererbungsmechanismen
Datenkapselung
Polymorphie

Archivo Explosivo: OOP

FIAE – OOP – Objektorientierte Programmierung – Prototypenbasierte Programmierung

Prototypenbasierte Programmierung beschreibt klassenloses objektorientiertes Programmieren. Die Vererbung wird über das Dekorieren von Objekten erreicht – Prototypen. Dieses Modell wird als klassenlose/prototyporientierte/prototypenbasierte/instanzorientierte Programmierung bezeichnet.

Prototypenbasierte Programmierung am Beispiel Javascript

<script>

// Prototyp Auto wird erstellt  
function Auto(Marke) 
{
    this.Marke = Marke;
}

// Funktion für Prototyp wird erstellt
Auto.prototype.sagHallo = function()
{
    console.log('Hallo, ich bin ein ' + this.Marke + '!');
};

// Instanziierung des Prototypen Auto als Auto1 und Auto2
var Auto1 = new Auto('Hyundai');
var Auto2 = new Auto('Fiat');

// Funktionsaufruf durch die Instanzen
Auto1.sagHallo(); // Ausgabe: Hallo, ich bin ein Hyundai!
Auto2.sagHallo(); // Ausgabe: Hallo, ich bin ein Fiat!

// Vererbung des Prototypen Auto als neuer Prototyp Kleinwagen
function Kleinwagen(Marke)
{
    // Eigenschaften Vererbung
    Auto.call(this, Marke);
};

// Erstellung eines neuen Objekts Kleinwagen anhand des Prototypen Auto
Kleinwagen.prototype = Object.create(Auto.prototype);

// Instanziierung des Prototypen Kleinwagen
Kleinwagen.prototype.constructor = Kleinwagen;

// Ersetzen der Funktion sagHallo des Prototypen Auto
Kleinwagen.prototype.sagHallo = function(){
    console.log('Hallo, ich bin ein Kleinwagen ' + this.Marke + '!');
};

// Instanziierung des Prototypen Kleinwagen als Kleinwagen1
var Kleinwagen1 = new Kleinwagen('Fiat 500');

// Funktionsaufruf der neuen Funktion sagHallo
Kleinwagen1.sagHallo(); // Ausgabe: Hallo ich bin ein Kleinwagen Fiat 500!

// Der instanceof-Operator prüft die Anwesenheit des constructor.prototype in der Prototypenkette eines Objekts (Kleinwagen1 und Auto).
console.log(Kleinwagen1 instanceof Auto);

</script>

Eine gute Anlaufstelle für Javascript ist das Mozilla Developer Network (developer.mozilla.org/de/docs/Web/JavaScript) und die entsprechende ECMA-Script-Sprachdefinition (ecma-international.org/ecma-262/7.0/index.html

Archivo Explosivo: OOP

FIAE – OOP – Objektorientierte Programmierung – Polymorphie

Polymorphie ist ein wesentliches Verfahren der objektorientierten Programmierung. Polymorphismus bezieht sich auf die Objektmethoden. Polymorphie in der objektorientierten Programmierung ist eine Eigenschaft, die immer im Zusammenhang mit Vererbung und Schnittstellen (Interfaces) auftritt.

Im Allgemeinen gibt es drei Typen der Polymorphie:
– Der ad-hoc Polymorphismus (Überladung – overloading)
– Der parametrische Polymorphismus (Datenvorlage – template)
– Der Vererbungspolymorphismus (Neudefinition – overriding)

Ad-hoc Polymorphismus
Der ad-hoc Polymorphismus erlaubt gleichnamige Funktionen in unterschiedlichen Klassen – Beispiel: Es können zum Beispiel eine Basisklasse und eine Ableitungsklasse je eine Funktion „sagHallo()“ haben.

Parametrischer Polymorphismus
Der parametrische Polymorphismus, auch Datenvorlage genannt, erlaubt die Definition mehrere gleichnamiger Funktionen – mit unterschiedlichen Parametern (in der Anzahl und/oder im Typ). Der parametrische Polymorphismus erlaubt somit die automatische Wahl der anzuwendeden Methode gemäß der übergebenen Parameter oder Datentyps.
Beispiele:
– int addition(int, int)
– float addition(float, float)
– char addition(char, char)

Vererbungspolymorphismus
Die Möglichkeit eine Methode (Funktion) in Kind-Klassen (Child) neu zu definieren, die von einer Basisklasse (Parent) erben.

Archivo Explosivo: OOP

FIAE – OOP – Objektorientierte Programmierung – Persistenz

Persistenz (nicht unkontrolliert veränderlich) bedeutet, dass Daten auch nach Beenden eines Programms vorhanden (gespeichert) bleiben, und bei erneutem Aufruf des Programms wieder rekonstruiert und angezeigt werden können. (Im Gegensatz dazu: flüchtige Daten – transient) Persistente Objekte besitzen eine potentiell unendliche Lebensdauer und können nur durch expliziten Aufruf einer speziellen Methode (Destruktor) gelöscht werden. Sie werden in permanenten Speichersystemen z.B. objektorientierten Datenbanksystemen verwaltet.

In diesem Zusammenhang taucht oft ein Pattern auf: Data Access Object ist zum Beispiel ein Entwurfsmuster (Pattern) das den Zugriff auf unterschiedliche Datenquellen (Datenbanken, Dateisystem) so kapselt, dass die angesprochene Datenquelle ausgetauscht werden kann, ohne dass der aufrufende Code geändert werden muss. Dadurch soll die eigentliche Programmlogik von technischen Details der Datenspeicherung befreit werden und flexibler einsetzbar sein.

In PHP wäre so ein Persistenz-Layer MySQL, PDO (PHP Data Objects) oder das Doctrine Project (ORM, DBAL).

Archivo Explosivo: OOP

FIAE – Datenbanken & OOP – Objektorientierte Programmierung – Normalisierung in relationalen Datenbanken

Relationalen Datenbanken
– RDBMS – Relational Database Management System – relationales Datenbankmanagementsystem
– Abfragen (meist) mit Datenbanksprache SQL (Structured Query Language)
– Grundlage relationaler Datenbanken ist die Relation
– Relationale Algebra ist die theoretische Grundlage von SQL
– Jede Zeile in einer Tabelle (Tupel) ist ein Datensatz (record)
– Jedes Tupel besitzt Attributwerte (Spalten)

Relationale Datenbanken sind unabhängig von der objektorientierten Programmierung. Sie haben eigene Regeln, wie man die einzelnen Tabellen und Relationen (Beziehungen) gestalten sollte. Durch die Regeln der Normalisierung wird das Datenmodell in Normalformen gebracht und Redundanz und Inkonsistenz vermieden. Eine Relationale Datenbank speichert nicht nur die Daten der Tabellen sondern auch die Beziehungen zwischen den Tabellen – die Relationen.

Die wesentlichen Operationen in einem RDBMS, aus denen alle weiteren abgeleitet werden können
– Projektion – projection
– Selektion – selection
– Kreuzprodukt/Kartesisches Produkt – cross product/cross join/cartesian product
– Umbenennung – rename
– Vereinigung – union
– Differenz – set difference/minus

Schlüssel
Ein Schlüssel dient in einer relationalen Datenbank dazu, die Datensätze (Tupel) einer Relation (Tabelle) eindeutig zu identifizieren und zu nummern. Ein Schlüssel ist dann eine Gruppe von Spalten, die so ausgewählt wird, dass jede Tabellenzeile über den Werten dieser Spaltengruppe eine einmalige Wertekombination hat.
Superschlüssel – Menge von Feldern (Attributen) in einer Tabelle (Relation), die die Zeilen (Tupel) in dieser Relation eindeutig identifizieren
Schlüsselkandidaten – candidate key – Kandidatenschlüssel / Alternativschlüssel – Minimale Teilmenge der Attribute eines Superschlüssels, welche die Identifizierung der Tupel ermöglicht
Primärschlüssel – surrogate key – Der ausgewählte Schlüsselkandidat, der in Folge für die Abbildung der Relationen verwendet wird. Die Werte dieses Schlüssels werden in referenzierenden Tabellen als Fremdschlüssel verwendet
Sekundärschlüssel – Indizes/Sekundärindizes – Attributgruppen, die häufig zur Beschreibung einzelner und/oder mehrerer Zeilen (Tupel) benutzt werden (Suchbegriff(e))
Fremdschlüssel – Attribut oder eine Attributkombination einer Relation, welches auf einen Primärschlüssel (bzw. Schlüsselkandidaten) einer anderen oder der gleichen Relation verweist

Fremdschlüssel und Beziehungstypen (R Relationsschema, S Teilmenge der Attribute)
1:1-Beziehung
– Jedem Datensatz aus R ist maximal 1 Datensatz aus S zugeordnet
– Jedem Datensatz aus S ist maximal 1 Datensatz aus R zugeordnet
1:N-Beziehung
– Jedem Datensatz aus R ist/sind kein Datensatz, ein Datensatz oder mehrere Datensätze aus S zugeordnet
– Jedem Datensatz aus S ist maximal 1 Datensatz aus R zugeordnet
N:M-Beziehung
– Jedem Datensatz aus R kann/können ein Datensatz oder mehrere Datensätze aus S zugeordnet sein
– Jedem Datensatz aus S kann/können mehrere Datensätze aus R zugeordnet sein

Formale Definition eines Schlüssels (R Relationsschema, S Teilmenge der Attribute)
Eindeutigkeit: Keiner der Einträge in einer Tabelle R darf zwei verschiedene Tupel (Zeilen) enthalten, bei denen die Werte von S gleich sind
Definiertheit: Alle Einträge der Tabelle R müssen die Attribute aus S definieren, keiner der Einträge darf NULL sein
Minimalität: Keine echte Teilmenge von S erfüllt bereits die Bedingung der Eindeutigkeit

Normalisierung / Denormalisierung
Normalisierung – Redundanz vermeiden (Inkonsistenz vermeiden)
Denormalisierung – Redundanz bewusst einführen (Programmablauf beschleunigen)

Normalformen
Normalisierung bedeutet: Überführung komplexer Beziehungen in einfache Beziehungen durch Aufteilung der Attribute einer Tabelle auf mehrere Tabellen. Normalformen dienen der Qualitäts-Beurteilung eines Datenbankschemas und helfen Fehler beim Erzeugen neuer Schemata zu vermeiden.
Nullte Normalform (0NF): Eine Datenbanktabelle ist in der Nullten Normalform unnormalisiert.
Erste Normalform (1NF): Einzelne Fakten werden gespeichert -In jedem Feld einer Tabelle wird ein einzelner Wert gespeichert (atomare Attributwerte)
Zweite Normalform (2NF): Erste Normalform und alle Werte der Spalten, die nicht ein Teil des Schlüssels sind, funktional von dem gesamten Primärschlüssel abhängig (X ist von einem Attribut Y funktional abhängig, wenn es zu jedem Y genau ein X gibt)
Dritte Normalform (3NF): Zweite Normalform und keine funktionalen Abhängigkeiten unter den Spalten, die nicht zum Primärschlüssel gehören (Transitive Abhängigkeit)
Boyce-Codd-Normalform (BCNF): Dritte Normalform und die Teile der Schlüsselkandidaten nicht von Teilen anderer Schlüsselkandidaten abhängig (Ray Boyce & Edgar Codd)
Vierte Normalform (4NF): Boyce-Codd-Normalform und maximal eine nichttriviale mehrwertige, funktionale Abhängigkeit enthält (Multivalued Dependency, MVD)
Fünfte Normalform (5NF): Vierte Normalform und lässt sich nicht ohne Informationsverlust in mehrere Tabellen aufspalten (Project-Join-Normalform)

Merksätze
– Der Schlüssel, der ganze Schlüssel und nichts als der Schlüssel. So wahr mir Codd helfe!
– Ist die Relation in 1. Normalform und besteht der Primärschlüssel aus nur einem Attribut, so liegt automatisch die 2. Normalform vor
– Ist eine Relation in 2. Normalform und besitzt sie außer dem Primärschlüssel höchstens ein weiteres Attribut, so liegt die Tabelle in 3. Normalform vor
– Die 3. Normalform ist die letzte und muss die 1. und 2. Bedingungen erledigen

Archivo Explosivo: OOP

FIAE – OOP – Objektorientierte Programmierung – Entwurfsprinzipien

Beim Architekturentwurf einer Software kann man sich einiger grundlegender Entwurfsprinzipien bedienen:

  • Abstraktion: irrelevante Details werden ausgeblendet
  • Teile und Herrsche: Probleme werden in kleine, unabhängige Teilprobleme zerlegt
  • Kapselung: Zusammengehörige Bestandteile einer Abstraktion werden zu einem Ganzen zusammengefasst und von anderen abgegrenzt
  • Modularisierung: das Gesamtsystem wird in Subsysteme und Module zerlegt
  • Kopplung: eine möglichst geringe Kopplung von Komponenten
  • Zusammenhalt: das Ziel ist ein möglichst großer Zusammenhalt der Bestandteile
  • Konzeptuelle Integrität: die durchgängige Anwendung von Entwurfsentscheidungen im gesamten System
  • Trennung der Zuständigkeiten: die Aufteilung des Systems in Komponenten anhand von Zuständigkeiten
  • Trennung zwischen Verhalten und Daten: eine Komponente soll entweder für das Verhalten oder die Implementierung zuständig sein
  • Trennung zwischen Schnittstelle und Implementierung: Komponenten sollten aus einer Schnittstelle und einer Implementierung bestehen
  • Open Closed Principle: offen gegenüber Erweiterungen aber geschlossen gegenüber nachträglicher Veränderung
  • Liskov Substitution Principle: der Aufruf einer polymorphen Methode soll immer den gewünschten Effekt haben
  • Wiederholungen vermeiden: DRY – Don’t repeat yourself
Archivo Explosivo: OOP

FIAE – OOP – Objektorientierte Programmierung – Datenkapselung und Schnittstellen

Als Datenkapselung (Geheimnisprinzip – encapsulation/information hiding) bezeichnet man in der objektorientierten Programmierung das Verbergen von Informationen vor dem äußeren Zugriff. Der direkte Zugriff auf die interne Datenstruktur wird verhindert und erfolgt über Schnittstellen. Die Datenkapselung führt zu Definitionen von Betrachtungsschichten der Elemente einer Klasse. Diese Betrachtungsschichten stellen die Zugriffsrechte dar (Methodenzugriffsart).

Bleiben wir beim Auto: Die eigentlichen Eigenschaften des Motors können nur über vorgesehene Schnittstellen ermittelt werden. Der Ölstand wird über den Messstab gemessen, Motoröl lässt sich in die vorgesehene Öffnung einfüllen. Was aber im Inneren des Motors mit dem Motoröl angestellt wird, bleibt verborgen (Geheimnisprinzip).

UML (Unified Modeling Language) als De-facto-Standardnotation erlaubt die Modellierung folgender Zugriffsarten:
public – Zugreifbar für alle Objekte (auch die anderer Klassen)
private – Nur für Objekte der eigenen Klasse zugreifbar
protected – Nur für Objekte der eigenen Klasse und von Spezialisierungen derselben zugreifbar
package – Erlaubt den Zugriff für alle Elemente innerhalb des eigenen Pakets.

Anmerkung: Die Handhabung des Schlüsselwortes package ist in den verschiedenen Programmier- bzw. Skriptsprachen unterschiedlich, wenn überhaupt vorhanden.

Archivo Explosivo: OOP

FIAE – OOP – Objektorientierte Programmierung – Abstraktion in Form von Klassen

Wenn wir in einer Klasse Daten verarbeiten wollen, müssen wir reale Objekte in dieser Klasse darstellen. Diese Objekte werden für die Verarbeitung auf die nötigen Gesichtspunkte reduziert. Die Reduktion nennt man in der objektorientierten Programmierung Abstraktion.

Der Klassiker – Auto: Wollen wir ein Auto programmieren, ist es überflüssig, jeden Aspekt des Autos darzustellen. Es ist egal, ob es ein VW/Audi/Hyundai ist… – wichtig für ein Auto sind die Eigenschaften wie Beschleunigung, Geschwindigkeit, Leistung, Hubraum, … Für das Beispiel Auto sind die Eigenschaften die Variablen. Funktionen in dem Auto-Programm könnten zum Beispiel das Fahren/Lenken/Beschleunigen/Bremsen sein.

Funktionen heißen in der objektorientierten Programmierung Methoden. Ein Objekt in der objektorientierten Programmierung definiert sich aus Eigenschaften und Methoden.

class auto
{
    var $Beschleunigung = 0;
    var $Geschwindigkeit = 0;
    var $Leistung;
    var $Hubraum;
    ...

    function fahren() {
        ...
    }

    function lenken() {
        ...
    }

    function beschleunigen() {
        ...
    }

    function bremsen() {
        ...
    }
}