Deklarative Programmierung: Wenn das Was wichtiger ist als das Wie

Ob bei der Programmierung einer App, einer IoT-Software oder eines Computerspiels – bevor Entwickler ihre ersten Zeilen Code schreiben, müssen sie eine grundlegende Entscheidung treffen: Welche Programmiersprache wollen sie verwenden? Diverse Sprachen stehen zur Auswahl. Mit Abstand betrachtet, lassen sich alle Sprachen jedoch zwei grundlegenden Programmierparadigmen zuordnen: der deklarativen Programmierung und der imperativen Programmierung.

Was ist deklarative Programmierung?

Ganz trennscharf ist das Paradigma nicht beschrieben, doch über eines sind sich alle Definitionen einig: Kennzeichnend für die deklarativen Programmiersprachen ist, dass sie immer ein gewünschtes Endergebnis beschreiben, statt alle Arbeitsschritte aufzuzeigen. Um das Ziel zu erreichen, wird bei der deklarativen Programmierung der Lösungsweg automatisch ermittelt. Dies funktioniert so lange gut, wie die Spezifikationen des Endzustands klar definiert sind und ein passendes Ausführungsverfahren existiert. Trifft beides zu, ist die deklarative Programmierung sehr effizient.

Da die deklarative Programmierung das ‚Wie‘ nicht festschreibt, sondern auf einem sehr hohen Abstraktionsniveau arbeitet, lässt das Programmierparadigma zudem Raum für Optimierung. Wird ein besseres Ausführungsverfahren entwickelt, lässt sich dies über den integrierten Algorithmus auffinden und verwenden. Auf diese Weise ist das Paradigma sehr zukunftssicher: Beim Schreiben des Codes muss das Verfahren, wie das Ergebnis zu erreichen ist, nicht feststehen.

Die bekanntesten deklarativen Programmiersprachen:

  • Prolog
  • Lisp
  • Haskell
  • Miranda
  • Erlang
  • SQL (im weitesten Sinn)

Die verschiedenen deklarativen Programmiersprachen lassen sich wiederum einteilen in zwei Paradigmen: in Sprachen der funktionalen Programmierung und solche der logischen Programmierung.

In der Praxis verschwimmen die Grenzen jedoch häufig und es werden sowohl Elemente imperativer Programmierung mit ihren Untertypen prozeduraler, modularer und strukturierter Programmierung als auch deklarativer Programmierung zur Lösung von Problemen angewendet.

Imperative vs. deklarative Programmierung

Das imperative Programmierparadigma (befehlsorientiertes Paradigma) ist das ältere der beiden grundlegenden Paradigmen. Anders als bei der deklarativen Programmierung legt der Entwickler hier im Quellcode genau fest, was der Computer Schritt für Schritt tun soll, um zum Ergebnis zu gelangen. Das ‚Wie‘ des Lösungswegs steht im Vordergrund. Diesen Ansatz findet man zum Beispiel bei Java, Pascal oder in C. Bei der deklarativen Programmierung wird dagegen direkt das ‚Was‘ der Lösung beschrieben.

Als Beispiel eine Übertragung auf den Möbelaufbau: Während die imperative Programmierung eine Anleitung zum Aufbau liefert, bietet die deklarative Programmierung ein Bild des fertigen Möbelstücks als Vorlage.

Statt mit Funktionen das Wie der Ausführung offen zu lassen, gibt es bei der imperativen Programmierung Variablen, die zur Laufzeit verändert werden. Das macht den Code länger, aber auch leichter verständlich als die verkürzte und sehr abstrakte Form des deklarativen Stils.

Deklarative Programmierung – ein Beispiel

Eine Stärke der deklarativen Programmierung ist ihre Fähigkeit, Probleme kürzer und prägnanter zu beschreiben als die imperativen Sprachen.

Soll eine Liste mit Vornamen ausgegeben werden, lässt sich dies in PHP mit der deklarativen Programmierung – wie das Beispiel zeigt – mit nur einer Zeile Code beschreiben, während die imperative Vorgehensweise fünf Zeilen benötigt.

Imperative Programmierung

$teilnehmerListe = [1 => 'Peter', 2 => 'Hans', 3 => 'Sarah'];
$vornamen = [];
foreach ($teilnehmerListe as $id => $name) {
    $vornamen[] = $name;
}

Deklarative Programmierung

$vornamen = array_values($teilnehmerListe);

Vor- und Nachteile deklarativer Programmiersprachen

Der deklarative Programmierstil wird heute in einer Vielzahl von Fällen verwendet, wenn auch nicht in Reinform. Die Herangehensweise ist allerdings nicht für jeden Einsatz geeignet.

Der deklarative Code zeichnet sich durch ein hohes Abstraktionsniveau aus. Das erlaubt Entwicklern, komplexe Programme in komprimierter Form darzustellen. Doch je umfangreicher die Anwendung, desto größer die Gefahr, dass der Code derart verschachtelt wird, dass er nur noch für den Entwickler lesbar ist, der ihn ursprünglich geschrieben hat. Für Unternehmen, die Anwendungen personenunabhängig warten und weiterentwickeln lassen wollen, birgt diese Situation eine Gefahr. Dann müssen fremde Entwickler sich mühsam in deklarativen Code einlesen, bis sie die Struktur verstanden und Probleme gelöst haben.

Das Abstraktionsniveau der deklarativen Programmierung bietet jedoch auch Vorteile. Indem die Ausführung über einen Algorithmus klar vom System getrennt ist, lässt sich die Wartung unabhängig von der Anwendungsentwicklung durchführen. Störungen im Tagesbetrieb werden auf ein Minimum reduziert. Gleichzeitig ist die Optimierung einfacher, da der verwendete Algorithmus offen genug ist, um auf neue Methoden zuzugreifen. Der Nachteil der Algorithmus-Verwendung: Auf spezifische Charakteristika einzelner Anwendungsfälle kann eine solche formelhafte Lösung häufig nur ungenügend eingehen.

Zwar kein Nachteil, aber eine Herausforderung liegt im Denkmodell der deklarativen Programmierung. In Lösungszuständen zu denken, steht dem natürlichen menschlichen Denkverhalten entgegen. Menschen denken in Prozessen auf ein Ziel zu statt von einem Ziel ausgehend rückwärts. Hier ist von Entwicklern ein Umdenken und Einarbeiten gefordert, das zunächst Problemlösungen verlangsamen kann. Ist das neue Mindset aber einmal trainiert, kann der deklarative Ansatz seine Stärken ausspielen.

Die Entwicklung von der Problembeschreibung ausgehend hat außerdem den Vorteil, dass Teams Lösungsmodelle recht schnell skizzieren können. Schließlich kann die konkrete Programmierung der Ausführung in einem späteren Schritt erfolgen. Damit ist der deklarative Stil für Prototyping in der agilen Software-Entwicklung gut geeignet.

Vorteile Nachteile
Kurzer, effizienter Code Für Fremde zum Teil schwer verständlich
Ausführbar mit zum Zeitpunkt der Programmierung noch nicht bekannten Methoden Basiert auf für Menschen ungewohntem Denkmodell (Lösungszustand)
Einfache Optimierung, da Ausführung über Algorithmus angesteuert wird Charakteristika einzelner Anwendungsfälle können in der Programmierung nur schwer berücksichtigt werden
Wartung unabhängig von der Anwendungsentwicklung möglich  

In der Praxis kommen heute meist Mischformen der Paradigmen zum Einsatz und deklarative Programmiersprachen werden um imperative Methoden ergänzt. Das erhöht allerdings die Fehleranfälligkeit und kann die Lesbarkeit des Codes beeinträchtigen.