Funktionale Programmierung baut Software aus Funktionen auf, die wie mathematische Funktionen arbeiten: Dieselbe Eingabe liefert immer dieselbe Ausgabe, und die Funktion verändert dabei keine Daten außerhalb von sich selbst. Das unterscheidet sie von der objektorientierten Programmierung, bei der Programme aus Objekten mit einem eigenen, veränderbaren Zustand bestehen. Rein funktional geschriebene Programme sind in der Praxis selten, ihre Grundideen prägen inzwischen aber auch Sprachen, die eigentlich anders aufgebaut sind.
Unveränderliche Daten statt geänderter Variablen
Das zentrale Prinzip heißt Unveränderlichkeit, auf Englisch Immutability. Statt eine bestehende Variable zu überschreiben, erzeugt eine funktionale Codezeile bei Bedarf einen neuen Wert und lässt den alten unangetastet. Das verhindert eine ganze Fehlerklasse: Wenn keine Funktion heimlich Daten verändert, die eine andere Funktion gerade benutzt, lassen sich Programme leichter parallel auf mehreren Prozessorkernen ausführen, ohne dass sich zwei Programmteile gegenseitig ins Gehege kommen.
Funktionen höherer Ordnung und Rekursion
Funktionale Sprachen behandeln Funktionen als gewöhnliche Werte: Eine Funktion kann als Parameter an eine andere Funktion übergeben oder als Ergebnis zurückgegeben werden. Man nennt das eine Funktion höherer Ordnung. Statt einer Schleife, die einen Zähler Schritt für Schritt hochzählt, arbeiten funktionale Programme häufig mit Rekursion, einer Funktion, die sich selbst erneut aufruft, bis eine Abbruchbedingung erreicht ist. Wer schon einmal in JavaScript die Methoden map, filter oder reduce auf eine Liste angewendet hat, hat damit bereits funktionale Programmierung benutzt, auch wenn JavaScript selbst keine rein funktionale Sprache ist.
WhatsApp, Discord und Nubank setzen auf funktionale Sprachen
Die Programmiersprache Erlang wurde in den 1980er-Jahren beim schwedischen Telekommunikationsunternehmen Ericsson für Systeme entwickelt, die niemals ausfallen dürfen. WhatsApp baute seine Chat-Infrastruktur auf Erlang auf und konnte damit lange Zeit Milliarden Nachrichten mit einem vergleichsweise kleinen Entwicklerteam verarbeiten. Elixir, eine 2012 veröffentlichte Sprache, die auf derselben Erlang-Laufzeitumgebung aufsetzt, aber eine modernere Syntax bietet, wird unter anderem vom Chatdienst Discord für Teile seiner Echtzeitkommunikation eingesetzt. Die brasilianische Digitalbank Nubank, eine der größten Banken Lateinamerikas, verarbeitet einen Großteil ihrer Finanzlogik in der Sprache Clojure, einem Lisp-Dialekt, der ebenfalls auf Unveränderlichkeit setzt.
Haskell als strengste verbreitete Vertreterin
Haskell gilt unter den verbreiteten Sprachen als die konsequenteste Umsetzung des funktionalen Ansatzes. Die Sprache erzwingt über ihr Typsystem, dass eine Funktion, die Daten verändert oder eine Datei liest, ein sogenannter Seiteneffekt, das im Code sichtbar kennzeichnen muss. Dadurch lässt sich beim Lesen eines Programms oft schon am Funktionstyp erkennen, ob eine Funktion ausschließlich rechnet oder auch mit der Außenwelt interagiert, ein Vorteil bei der Fehlersuche in großen Codebasen.
Zuverlässigkeit unter hoher Last treibt die Wahl
Der Grund, warum gerade Messenger, Banken und andere Dienste mit sehr vielen gleichzeitigen Nutzern zu funktionalen Sprachen greifen, liegt selten in der reinen Eleganz des Ansatzes. Unveränderliche Daten lassen sich ohne komplizierte Sperrmechanismen auf viele Prozessorkerne und Server verteilen, weil kein Programmteil dem anderen versehentlich Daten unter der Hand verändert. Das senkt eine bestimmte Klasse von Fehlern, die in klassischen, zustandsbehafteten Systemen bei hoher Parallelität besonders häufig auftritt: Race Conditions, bei denen das Ergebnis eines Programms vom zeitlichen Zufall abhängt, in welcher Reihenfolge zwei Prozesse dieselben Daten anfassen.
Für die meisten Entwicklerteams bedeutet das nicht, komplett auf eine funktionale Sprache umzusteigen. Häufiger übernehmen sie einzelne Konzepte wie Unveränderlichkeit oder Funktionen höherer Ordnung in Sprachen, die sie ohnehin schon einsetzen, und wählen eine rein funktionale Sprache gezielt für die Teile eines Systems, in denen Zuverlässigkeit unter hoher Last den Ausschlag gibt.
Häufig gestellte Fragen
Was bedeutet Unveränderlichkeit in der funktionalen Programmierung?
Unveränderlichkeit, auf Englisch Immutability, bedeutet, dass eine funktionale Codezeile bei Bedarf einen neuen Wert erzeugt, statt eine bestehende Variable zu überschreiben, und den alten Wert unangetastet lässt. Das verhindert, dass eine Funktion heimlich Daten verändert, die eine andere Funktion gerade benutzt, wodurch sich Programme leichter parallel auf mehreren Prozessorkernen ausführen lassen.
Warum setzen Unternehmen wie WhatsApp und Discord auf funktionale Sprachen wie Erlang und Elixir?
Unveränderliche Daten lassen sich ohne komplizierte Sperrmechanismen auf viele Prozessorkerne und Server verteilen, weil kein Programmteil dem anderen versehentlich Daten unter der Hand verändert. Das senkt die Zahl der Race Conditions, bei denen das Ergebnis eines Programms vom zeitlichen Zufall abhängt, weshalb WhatsApp seine Chat-Infrastruktur auf Erlang aufbaute und Discord Elixir für Teile seiner Echtzeitkommunikation einsetzt.
Was unterscheidet Haskell von anderen funktionalen Sprachen?
Haskell gilt unter den verbreiteten Sprachen als konsequenteste Umsetzung des funktionalen Ansatzes, weil ihr Typsystem erzwingt, dass eine Funktion mit einem Seiteneffekt, etwa das Verändern von Daten oder das Lesen einer Datei, das im Code sichtbar kennzeichnen muss. Dadurch lässt sich beim Lesen eines Programms oft schon am Funktionstyp erkennen, ob eine Funktion nur rechnet oder auch mit der Außenwelt interagiert.
Muss ein Team komplett auf eine funktionale Sprache umsteigen, um von diesem Ansatz zu profitieren?
Nein, die meisten Entwicklerteams übernehmen stattdessen einzelne Konzepte wie Unveränderlichkeit oder Funktionen höherer Ordnung in Sprachen, die sie ohnehin schon einsetzen. Eine rein funktionale Sprache wählen sie gezielt für die Teile eines Systems, in denen Zuverlässigkeit unter hoher Last den Ausschlag gibt, etwa bei Nubank, das seine Finanzlogik in Clojure verarbeitet.
