Einführung

Dynamische Programmiersprachen sind Programmiersprachen die oftmals eher den LessCode-Prinzipien entpsrechen als „undynamische“ Sprachen. Deshalb werden sie vom LessCoder auch bevorzugt eingesetzt.
Dies wird im folgenden sicherlich deutlich, aber erst einmal zur Einführung: Die populärsten Wegbereiter von dynamische Programmiersprachen waren Lisp und SmallTalk.
Heute sind als die populärsten Sprachen dieses Genres wohl PHP, Python, Perl, JavaScript, Ruby und Groovy zu bezeichnen.

Typische Merkmale dieser Art von Sprachen sind:

  • Dynamische Typisierung: Hierunter ist das Zuteilen des Typs einer Variablen erst während der Laufzeit gemeint. In diesem Zusammenhang komtm oft der Begriff Duck Typing“ vor: Wenn es aussieht wie eine Ente, quakt wie eine Ente, dann ist es eine Ente (auch wenn nirgends deklariert wure, dass es eine Ente sei. Konkret heisst das zum Beispiel: Wenn sich eine Methode auf einem Objekt aufrufen lässt, dann spricht nichts dagegen, dies zu tun. Es gibt auch noch eine spezielle Klasse von Sprachen, bei denen Typisierung optional ist und eine, bei der der Compiler druch Inferenz auf Typen schließen kann (in etwa: „ah, da kommt eine Variable, deren typ ich nicht kenne, aber hier nachher wird es eine Liste gesteckt, die nur Strings annimmt, dann muss es sichh hierbei um einen String handeln“)
  • Closures: Dies ist eine Funktion, die nur im Kontext einer anderen funktioniert. Dafür hat sie auch Zugriff auf die Variablen in diesem Kontext. Sie kann meist auch als anonyme Funktion hin und hergereicht werden – in etwa wie eine anonymce Klasse die das Runnable-Interfaces in Java implementiert oder ein Function-Pointer in C. Im Zusammenhang mit Duck-Typing lässt sich damit mit sehr wenig Code-Tokens sehr viel ausdrücken.
  • Reflexion: Das System kann zur Laufzeit seine Objekte und Klassen untersuchen und entsprechend darauf reagieren und teilweise sogar manipulieren. Zum Beispiel können in manchen Sprachen dynamische weitere Methoden zu Klassen hinzugefügt werden. Dies ist eine gute Vorraussetzung zur Umsetzung von internen DSLs (Domänen-Spezifischen-Sprachen)
  • Dynamische Generierung und Ausführung von Code: Viele dyn. Sprachen lassen es zu, meist mit einer „eval“-Methode, zur Programmlaufzeit Code als Zeichenfolge zusammenzusetzen und dann direkt ohne Compilierung zur Ausführung zu bringen. Insb. im Zusammenhang mit Reflexion sind so Klassen/Objekte zur Laufzeit erweiterbar.

Der Begriff „dynamische Programmiersprache“ ist nicht eindeutig definiert, aber man kann sagen, dass je mehr dieser Merkmale eine Sprache unterstützt, umso eher ist sie als dynamische Sprache zu bezeichnen.

Warum gerade jetzt?

Vor 30 Jahren war es C, danach C++, vor guten 10 Jahren Java und kurz danach C#. Sprachen, die die Software-Industrie dermaßen dominiert haben, dass andere Sprachen kaum eine Chance hatten. Diese Sprachen waren zu Ihrer Zeit auch eine gute Wahl: Hohe Sicherheit durch den Compiler, reich an Features wie Speichermanagement und mächtigen IDEs und langfristig gesichert durch viele Millarden Dollar aus der Industrie.
Vorher gab es kaum Sprachen, mit dermaßen kommerziellen Hintergrund.

Allerdings scheint die Entwicklung dieser Mainstream-Sprachen immer mehr still zu stehen bzw. sich in einer Richtung zu entwickeln, die sich sich nicht mehr sehr an der Praxis der guten Softwareentwicklung orientiert. Es dauert lange, bis neue Sprachkonstrukte entstehen, danach sind sie oft eher unpraktisch. Java mit seinem teilweise jahrelang dauerndem JSR-Prozess oder die Java-Generics, die die ganze Typisierung noch mehr verkomplizieren als Nutzen. Theoretisch korrekt, praktisch kaum genießbar.
Und was der kommerzielle Hintergrund von Sprachen angeht, zeigt Oracle aktuell (August 2009) mit seiner Geldgier wo der Tend hingehen könnte. Vielleicht muss irgendwann jeder einen Obulus für die Nutzung der Next-Generation-Java-VM zahlen, so wie es Apple mit den Apps im AppStore vormacht?

Mit aus diesem Grund sprießen in den letzten Jahren viele neue Sprachen aus dem Boden wie Pilze.
Aber warum es oftmals die dynamischen Sprachen sind, dafür gibt es einen anderen Grund: Zu der Zeit, als das Test-Driven-Development aufkam, erkannten viele Entwickler das, was LessCode unter Overengineering meint: Warum bloß muss man dem Compiler noch Typen mitteilen und dieser die Typen auch noch überprüfen, wenn man durch ständig laufende Tests sowieso implizit eine Typüberprüfung durchführt? Durch das Weglassen von Typdeklarationen wird nur wenig verloren, aber viel gewonnen.

Warum weniger Code?

Die Frage ist nun, warum dynamische Sprachen insb. im LessCode-Umfeld so beliebt sind. Generell ist es so, dass dass mit dynamischen Sprachen weniger Codezeilen zu schreiben sind, um ein Sachverhalt auszudrücken.
Um die Sache zu konkretisieren soll dies am Beispiel Ruby im Vergleich zu Java beschrieben werden:

  • Dank der dynamischen Typisierung und Duck-Typing fällt die Deklaration von Typen komplett weg. In der Praxis zeigt sich, dass falsche Typen eine recht seltene Art von Fehlerquellen ist (viel seltener als z.B. NoMethodError (bei nil) oder NullPointerExceptions). Dank sowieso notwendigen automatisierten Tests werden diese sowieso in einer frühen Phase schon gefunden und eliminiert. Dank Typeninferenz (nicht unbedingt in der Sprache selbst, aber im Typensystem) sind auch die IDEs inzwischen so gut, dass Funktionen wie Code-Completion und Refactoring brauchbar funktionieren.
  • Durch Nutzung von Closures (auch Lambdas oder in Ruby Blöcke genannt) ist es möglich, einfache Sachverhalte auch sehr einfach auszudrücken.
  • Durch Reflexion ist es nicht nötig, dem Compiler bestimmte Sachverhalte (meist Variablentypen) deklarativ mitzuteilen, sondern man setzt einfach das um, was in einem bestimmten Kontext notwendig ist.
  • Insbesondere DSLs sind oft ein elegantes Mittel, um mit sehr wenig Zeilen ein bestimmtes Verhalten zu deklarieren. Deklariert wird im Java-Umfeld oftmals noch mit externen DSLs (in Form von teilweise riesigen XML-Dateien). Dies hat sich in Java durch Annotations verbessert, dadurch wurde auch Java ein Stück dynamischer. Im Ruby-Umfeld und insb. in Ruby-on-Rails wird oft mit internen DSLs gearbeitet, d.h. die Umgebung selbst wird so erweitert, dass sie gar nicht mehr so sehr nach Ruby aussieht, sondern wie geschaffen zur Problemlösung in einer spezifischen Fachdomäne – bei Ruby on Rails der Fachdomäne von datenbankbasierten Webapplikationen. Dies wird insb. dann interessant, wenn es sich um eine Nicht-IT-Fachdomäne handelt (Versicherung, Controlling, Eissengießerei)
  • Die Charakteristika von Programmiersprachen prägen natürlich in gewissem Umfang die Menschen, die sie einsetzen, aber auch umgekehrt fühlt sich ein bestimmter Typ von Mensch von bestimmten Programmiersprachen eher angezogen als von anderen. So kommt es, dass sich quasi Menschengruppen/Communities um einzelne Programmiersprachen herum bilden, die alle ähnlich denken:
    Im Java-Umfeld könnte man sie eher als seriös, „enterprisey“, mit Hang zur Verkomplizierung bezeichnen, im Ruby-Umfeld als pragmatisch, agil und Task-erledigt-auf-zum-nächsten. Dies wirkt sich natürlich auch auf die Art der von dieser Community entstehenden Frameworks und Bibliotheken aus.
    Generell kann man sagen, dass die Bibliotheken im Ruby-Umfeld oftmals eher konkret und lösungsorientiert sind, und im Java-Umfeld eher generell, komplex und mächtig. Dies wirkt sich wiederum auf Art der Nutzung der Bibliotheken aus und damit den Code, den man schreibt, um die API der Bibliothek aufzurufen.

Ein einfaches Beispiel, das einige dieser Prinzipien im Vergleich Ruby und Java zeigt, findet sich in diesem Blogpost.

Tests sind das A und O

Als gravierender Nachteil von dynamischen Programmiersprachen wird immer wieder genannt, dass man mit ihnen keine Großprojekte durchführen kann, da vor allem durch die die fehlende Typisierung kein Sicherheit gebender Compiler/Tool-Suppport zum Einsatz kommen kann.
Nun, für diejenigen, die getreu dem Motto „Ich brauche keine Tests. Wenn es compiliert, und ich es zweimal druchklicke, dann funktioniert es auch.“ vorgehen, ist dieser Eindruck sicherlich richtig.

Man kann sagen, dass in dynamischen Programmiersprachen das Entwicklen und regelmäßige Starten von automatischen Tests einen Compilerlauf ersetzt. Der charmante Vorteil dabei ist, dass damit nicht nur das getestet wird, was der Compiler in typisierten Srpachen prüfen würde, sondern eben auch die fachspezifische Korrektheit des Codes. Und diese Art der Prüfung bekommt man auch in nicht-dynamischen Programmiersprachen nur durch das Schreiben von automatischen Tests.

Wie oben schon beschrieben, bringt die Typinferenz moderner IDEs auch bei dynamischen Sprachen den bekannten Komfort von Code-Completion und Refactoring-Support. Wobei zu sagen ist, dass Refactoring bei dynamischen Sprachen ein deutlich untergeordneteres Thema spielt. Dies liegt daran, dass die Anzahl der bei der Anwendung eines Refactoring betroffenen Codestellen viel geringer ist.
Beispiel: Das Umbenennen einer Klasse. Dadurch, dass keine Typisierung verwendet wird, ist die Anzahl der Vorkommnisse des Namens dieser umzubenennenden Klasse beschränkt auf sehr wenige Stellen, typischerweise nur dort, wo sie instanziiert wird.

Es liegt in der Natur vieler dynamischen Sprachen, dass sie meist einfacher zu lernen sind als die üblichen verdächtigen compilierten Sprachen – insb. weil hier nicht nur die Anzahl der LOC (Lines Of Code) deutlcih geringer ist, sondern auch die Anzahl und Komplexität der Tools.
Wie lange dauert es in Java, ein Projekt mit Maven, Ant, Spring, Hibernate etc. aufzusetzen um ein erstes „Hello Word“ auf einer Webseite ausgeben zu können?
Allein durch die Wahl des richtigen Frameworks wie z.B. Grails oder Ruby on Rails, wird hier schon eine Menge an Knowhow gar nicht erst benötigt.

Strategie zur Einführung

Wie nicht anders anzunehmen, wird durch die Wahl der Programmiersprache eine wichtige Weiche in einer frühen Phase des Projektes gestellt.

Sollte der geneigte Leser nun, nachdem er jahrelang z.B. in Java entwickelt hat, eine neue, dynamische Programmiersprache einsetzen, nur weil hier so viele tolle Vorteile beschrieben werden?

Die Antwort ist gar nicht so schwierig. Grundsätzlich wird der LessCoder die Frage ganz klar bejahen, denn die altbekannte Java-Syntax ist das Gegenteil von dem, was man sich unter LessCode vorstellt.
Aber es kommt natürlich auf das Umfeld an: Sind auch die Kollegen und die Entscheider so „open-minded„, dass sie einen Umstieg potenziell mitmachen würden, wenn ihnen die Vorteile gezeigt werden? Wie groß ist der Leidensdruck und die Entwicklerunzufriedenheit, die momentan durch den Einsatz von Java vorhanden ist?
Oft ist es – genügend Penetration der Entscheider vorrausgesetzt – möglich, in einem Pilotprojekt etwas Neues auszuprobieren.
Es erfordert nicht selten eine ganze Menge Ausdauer und auch Mut, über diesen Schatten zu springen, aber es wird sich lohnen, wenn dieses Pilotprojekt erfolgreich ist.
Um den Erfolg dieses Pilotprojektes zu steigern, macht es Sinn, sich von einer erfahrenen Person helfen zu lassen. Denn insbesondere dann sind schnelle Erfolge möglich – und dem Projekt ist nichts mehr zuträglich als schnelle Erfolge vorweisen zu können. Ein zusätzlicher Nebeneffekt ist, dass die Teammitglieder dabei durch die Zusammenarbeit mit einer erfahrenen Person in kurzer Zeit sehr viel Neues lernen können und stehen nach wenigen Monaten auf eigenen Beinen.

4 Kommentare

Schreibe einen Kommentar