Open Source im professionellen Einsatz

Newsletter abonnieren
Seite durchsuchen

HEFTARCHIV | NEWS | E-BIBLIOTHEK | VIDEO | BLOGS | WHITEPAPER | EVENTS | ACADEMY | ABO | SHOP

user friendly

  Home  »  Heft & Abo  »  Heftarchiv  »  2006  »  01  »  Ruby spricht viele Sprachen  

RSS-Feed der aktuellen News von Linux-Magazin Online Folgen Sie Linux-Magazin Online auf Twitter
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark

© photocase.com

Domain Specific Languages in Ruby

Ruby spricht viele Sprachen

von Michael Raidel
Erschienen im Linux-Magazin 2006/01

Domain Specific Languages vereinfachen die textbasierte Arbeit am Computer durch eine zusätzliche Abstraktionsstufe. Statt jedes Detail in einer allgemeinen Sprache auszuprogrammieren, genügen wenige Schlüsselwörter. Ruby enthält die nötigen Ausdrucksmittel für solche Vereinfachungen.

Die Aufgabe problemspezifischer Sprachen (Domain Specific Languages, DSL) ist es, möglichst intuitiv eine recht konkrete Aufgabe zu lösen. Dazu verwenden sie ein möglichst einfaches Vokabular, das zum Problemfeld passt und den Benutzer nicht überfordert. Solche kleinen Spezialsprachen haben in Unix eine lange Tradition, wie der Kasten "DSLs in der Praxis" beweist. Eine moderne Skriptsprache wie Ruby macht durch ihre flexible Syntax das Schreiben von Domain Specific Languages einfach.

Extern und intern

Eine DSL heißt extern, wenn ihre Verarbeitung die Umwandlung in eine andere Sprache oder einen speziellen Interpreter voraussetzt. Für externe DSLs kann der Entwickler eine eigene Syntax definieren, ohne sich den Regeln einer existierenden Sprache zu unterwerfen. Eine interne DSL bedient sich im Gegensatz dazu direkt der Ausdrucksmittel einer Programmiersprache.

Interne DSLs brauchen keinen eigenen Parser, die syntaktische Richtigkeit des Code überprüft der Compiler oder Interpreter. Die Entwicklungsumgebungen kennen die Sprachsyntax, rücken also beispielsweise korrekt ein und färben Sprachkonstrukte farbig.

Ruby eignet sich wegen ihrer vielfältigen Metaprogramming-Fähigkeiten, ihrer offenen Klassen und des flexiblen Objektmodells sehr gut zum Schreiben interner DSLs. Blocks erleichtern es beispielsweise, diese um eigene Sprachelemente zu erweitern und Anweisungen in einem festgelegten Kontext auszuführen. Auch die Möglichkeit, Syntaxelemente abzukürzen oder wegzulassen, erleichtert die Formulierung sauberer DSLs. Die folgenden Abschnitte stellen anhand einiger Beispiele die wichtigsten Sprachelemente für DSLs in Ruby vor.

Die Programmiersprache bietet diverse Möglichkeiten, um die syntaktische Komplexität zu minimieren. Dazu ein Beispiel im Stil der DSL von Switchtower, einem auf die Verteilung von Webanwendungen mit Ruby on Rails [1] spezialisierten Deployment-Tool. Die Switchtower-DSL lässt den Anwender Aufgaben definieren, die auf verschiedenen Servern laufen sollen:

task("backup", { "roles" => "db" })

Die Aufgabe bekommt mit dem ersten Parameter der Methode »task« den Namen »backup« zugeteilt. Manche Aufgaben sollen auf jedem Server ausgeführt werden, andere nur auf einzelnen. Die Parameter in Form eines Hash legen fest, dass die Aufgabe »backup« nur auf Servern mit der Rolle »db« laufen soll.

Besser: Weniger Klammern

In Ruby sind runde Klammern um die Variablen eines Methodenaufrufs nur zu setzen, wenn der Code sonst für den Interpreter nicht eindeutig wäre. So lässt sich die obige Aufgabe umformulieren: »task "backup", { "roles" => "db" }«. Ruby erkennt Hashes am Ende der Parameterliste auch ohne die sonst nötigen geschweiften Klammern. Das vereinfacht den Funktionsaufruf nochmals zu »task "backup", "roles" => "db"«.

Kommt in einem Ruby-Programm eine fixe Zeichenkette vor, empfiehlt es sich meist, sie durch ein Symbol zu ersetzen. Kommt das gleiche Symbol im Programm mehrfach vor, belegt es nur einmal Speicher und ist einfacher zu schreiben als eine normale Zeichenkette.

Statt der Anführungszeichen am Anfang und Ende des Strings ist nur ein führender Doppelpunkt notwendig. Das obige Beispiel reduziert sich damit auf »task :backup, :roles => :db«. Natürlich sind diese Änderungen kosmetischer Natur. Bei DSLs ist aber einfache Handhabung besonders wichtig, wozu auch ein klares Erscheinungsbild gehört.

Zu den wichtigsten Elementen von Ruby gehören Blocks, abgeschlossene Codebereiche, die eine Methode bei ihrem Aufruf übergeben bekommt. Im Normalfall folgt der Block nach der schließenden runden Klammer. Anfang und Ende des Blocks markieren entweder »do« und »end« oder geschweifte Klammern. Der Block läuft immer in dem Kontext ab, in dem er definiert wurde. In der Methode ruft die Anweisung »yield« den Block auf. Die Variablenzuweisung im Block findet zwischen Pipezeichen statt.

DSLs in der Praxis

Populäre Beispiele für Domain Specific Languages sind Regular Expressions, die SVG-Definition für Vektorgrafiken, der Pattern-Scanner Awk oder Konfigurationssprachen wie bei Sendmail. Allen ist gemeinsam, dass sie für einen speziellen Einsatzzweck optimiert sind. Im Unix-Bereich sind seit langem die beiden Tools Lex und Yacc auf das Erstellen und die Verarbeitung von Domain Specific Languages spezialisiert.

In der Ruby-Welt gibt es viele Beispiele für interne DSLs: Das Make-ähnliche Build-Tool Rake [2] verwendet eine DSL für die Konfiguration abhängiger Aufgaben. Das ORM-Paket Active Record [3] benutzt eine sehr einfache DSL zur Beschreibung der Beziehungen zwischen Datenbanktabellen.

Das Deployment-Werkzeug Switchtower [4] wiederum setzt eine DSL dazu ein, um notwendige Aktionen für die Verteilung einer Webanwendung zu definieren. Builder [5] schließlich ist ein Werkzeug für die Erzeugung von XML-Files und ein Stellvertreter für besonders dynamische DSLs: Das Tool fängt alle Aufruf einer Methode ab und wandelt sie in entsprechende XML-Tags um.

Blocks der Art »do |var| puts var end« lassen sich in einer DSL sehr gut verwenden, um in beschreibender Form Einstellungen vorzunehmen:

task :backup, :roles => :db do
  run "backup_command"
end

Eines der mächtigsten Features von Ruby sind die offenen Klassen. Damit ist es jederzeit möglich, Klassen und deren Methoden auch nach ihrer ursprünglichen Definition zu verändern. Das gilt sogar für die Ruby-Basisklassen. Ein gutes Beispiel für eine entsprechende Veränderung der Basisklassen findet sich im Active-Support-Modul [6]. Es überlädt unter anderem die Numeric-Klasse, um den Umgang mit Zeitangaben intuitiver zu gestalten:

class Numeric
  def minutes
    self * 60
  end
  def hours
    minutes * 60
  end
end

Als Beispiel wäre eine Anweisung der Form »5.minutes + 1.hours« denkbar. Eine kleine Änderung erhöht die Lesbarkeit der DSL noch einmal. Während »5.minutes« bereits sehr gut lesbar ist, trifft das auf »1.hours« nicht zu. Stattdessen wäre es passender, »1.hour« schreiben zu können. Da die bestehende Version programmtechnisch richtig funktioniert, fehlt nur eine Kopie der Methode. Das ist leicht mit der Ruby-Methode »alias« zu erreichen:

class Numeric
  def hours
    minutes * 60
  end
  alias :hour :hours
end
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark
Ähnliche Artikel
Vom Thron gestürzt Die besten Lesereinsendungen des Programmierwettbewerbs
Objekte statt Tabellen Datenbankanwendungen mit SQL Object
Bank 24 Vorgestellt: Die Informix-Version 11 mit neuen Konzepten für Hochverfügbarkeit
Ready, Set, Go! Google erfindet neue Programmiersprache
ÜbersetzO-matik Vims Skriptsprache praktisch erklärt
Babylon zu fünft Populäre Programmiersprachen treten gegeneinander an
Whitepaper
Usage Landscape Enterprise Open Source Data Integration

Die Nachfrage nach Datenintegrationslösungen für Unternehmen ist zunehmend gestiegen und vor allem das Interesse an Open Source Technologien wird immer größer. Doch wie und von wem werden Open Source Datenintegrationslösungen genutzt und welches Nutzungsverhalten lässt sich daraus ableiten? Das vorliegende White Paper präsentiert die Erfahrungswerte von über 1000 Open Source Nutzern und liefert fundierte Antworten auf diese Fragen.

Download PDF (Registrierung erforderlich)
Daten Migration - Eine Publikation von Bloor Research

Datenmigrationsprojekte überschreiten häufig das Budget, neigen zu Verzögerung und werden unter Umständen komplett abgebrochen. Bloor Research ist eines der weltweit führenden IT-Forschungs-, Analyse- und Beratungsunternehmen und wird in dem vorliegenden White Paper die wichtigsten Aspekte dieser Problematik näher beleuchten. Ferner werden praktische Empfehlungen für erfolgreiche Migrationsprojekte gegeben, die Sie auf Ihr nächstes Projekt übertragen können.

Download PDF (Registrierung erforderlich)
Kommentare (0)