Clojure – in der Praxis?

Eine neue Programmiersprache? Bitte nicht schon wieder…

Stefan Tilkov

Wer braucht schon eine neue Programmierprache? Schließlich lässt sich alles in jeder Sprache erledigen, die Turing-complete ist; ob es nun C++, C# oder Java ist – irgendwie ist doch alles das Gleiche. Die wirklich spannenden Themen liegen ganz woanders, in der Gesamtarchitektur, der Entwicklungsmethodik, sozialen Faktoren, der Firmenpolitik usw. Oder nicht? Spielen Programmiersprachen wirklich eine Rolle, oder sind sie vergleichsweise egal? Wie kann der Aufwand für das Erlernen und – viel wichtiger – das Einführen einer neuen Sprache gerechtfertigt werden? Am Beispiel Clojure diskutieren wir in diesem Artikel die wichtigsten Argumente.

Von Andy Hunt und Dave Thomas stammt der Rat, jedes Jahr eine neue Programmiersprache zu lernen, um nicht einzurosten. Und die Anhänger dieser Philosophie können sich zurzeit glücklich schätzen: An neuen oder wieder entdeckten Programmiersprachen herrscht wirklich kein Mangel. Die große Mehrheit der Entwickler jedoch steht dem Thema deutlich skeptischer gegenüber. In diesem Artikel wollen wir am Beispiel von Clojure näher beleuchten, welche Gründe es gibt, sich mit neuen Programmiersprachen auseinander zu setzen. Viele der Argumente sind Clojure-spezifisch, andere lassen sich auch auf andere Sprachen übertragen, insbesondere wenn diese – wie JRuby, Scala oder Groovy – auch auf der JVM lauffähig sind. Vorab: Natürlich gibt es diverse Nachteile, die ganz allgemein mit der Einführung einer neuen Sprache zusammenhängen, und jede Sprache hat auch ihre eigenen spezifischen Schwächen. Diese blenden wir in den nächsten Absätzen einfach einmal aus. Denn erstens kennen Sie diese Nachteile wahrscheinlich schon, und zweitens ist unsere Motivation natürlich völlig klar: Wir sollen Sie motivieren, neue Sprachen ernst zu nehmen und nicht zu ignorieren. Nachdem die „hidden agenda“ nun nicht mehr so versteckt ist, auf ans Werk!

Interoperabilität und Integration

Das erste Argument ist eigentlich ein Gegenargument gegen die häufigste Kritik am Einsatz alternativer Programmiersprachen: Mittlerweile bedeutet ein Wechsel der Sprache keineswegs zwingend, dass man bestehende Bibliotheken und Frameworks nicht mehr nutzen kann und Änderungen an der Laufzeitumgebung vornehmen muss. Sprachen wie Clojure, die die JVM als Ablaufumgebung nutzen, integrieren sich nahtlos in ein Java-Ökosystem. Aus Clojure heraus kann jede Java-Bibliothek verwendet werden; neben der Instanziierung von Objekten und dem Aufruf von Klassen- und Instanzmethoden lassen sich Klassen auch erzeugen und Interfaces implementieren. Collection-Datenstrukturen in Clojure und java.util.Collection und Co. sind interoperabel, die Unterstützung für Parallelprogrammierung nutzt intern die Mechanismen aus java.util.concurrent. Clojure-Code kann in JVM-Bytecode vorkompiliert werden (sonst geschieht das on-the-fly), mit Clojure implementierte Webanwendungen lassen sich als .war-Datei in eine bestehende Infrastruktur integrieren. Ähnliches gilt für andere Sprachen wie JRuby, Scala oder Groovy – die Integration und Interoperabilität in die JVM ist ein wesentliches Verkaufsargument. Sie können daher eine neue Sprache einführen, ohne dass die Auswirkungen unüberschaubar werden, eine „Big Bang“-Ablösung in Form einer Reimplementierung von Bestehendem ist nicht notwendig.

„Wachsende Sprachen“ und Domänenorientierung

Clojure als Lisp-Dialekt unterstützt mehr als alle anderen JVM-Sprachen den Ansatz, dem Entwickler Abstraktionen zur Verfügung zu stellen, über die er die Sprache selbst erweitern kann. Für Java-Entwickler ist dies ein ungewohntes Konzept: Wir sind damit vertraut, neue Konzepte mit Typen, Interfaces, Klassen und Methoden umzusetzen. Clojure erlaubt es jedoch, durch die minimalistische Syntax in Verbindung mit den Sprachmitteln Funktion und Makro neue Konzepte einzuführen, die in anderen Sprachen einen Eingriff durch den Compiler-Autor erlauben würden. So ist es mithilfe von Makros möglich, Clojure-Code zu programmieren, der nicht zur Laufzeit, sondern zur Compile-Zeit ausgeführt wird und neuen Code erzeugt (und zwar nicht textuell wie bei einem C-/C++-Preprozessor, sondern auf Ebene des ASTs der Sprache). Was esoterisch klingen mag, führt in der Praxis dazu, dass man bei der Entwicklung mit Lisp die Sprache Stück für Stück erweitert und sie immer mehr der Problem- bzw. Lösungsdomäne annähert. Wenn Sie sich an Domain-driven Design (DDD) und die darin propagierte „ubiquitous language“ oder an domänenspezifische Sprachen (DSLs) erinnert fühlen, liegen Sie richtig – man könnte mit einiger Berechtigung behaupten, dass beides in der Lisp-Welt schon immer zum normalen Programmiermodell gehört.

Geschrieben von
Stefan Tilkov
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.