1. Blöcke und Iteratoren
Die meisten Sprachen setzen entweder auf traditionelle Zähl-Schleifen und Arrays oder einer Kombination aus einem Iterator-Objekt und einer Schleife. Ruby hingegen macht verstärkt Gebrauch von sogenannten Blöcken, wenn es um die Iteration von Feld-Datentypen geht. Das bedeuten im Detail, dass die Instanz eine Iterator-Methode anbietet, in die ein Codeblock hineingereicht werden kann. Im Vergleich zu Java sieht das zum Beispiel wie folgt aus:
1
2
3
4
5
6
7
8
| //Iterator in Java
List a = new ArrayList();
Iterator it = a.iterator();
Object o = null;
while(it.hasNext()){
o = it.next();
o.doStuff();
} |
1
2
3
4
5
| #Iterator in Ruby
a = []
a.each |o|
o.doStuff()
end |
Der Grund warum Blöcke funktionieren, liegt bei dem Schlüsselwort yield. Es sorgt bei jedem Aufruf dafür, dass der Codeblock einmal ausgeführt wird. Kombiniert man yield Beispielsweise mit einer Schleife, kann man so sehr einfach einen “universalen” Iterator implementieren.
1
2
3
4
5
6
| def do_the_trick
4.times do |i|
yield i+1
end
end
do_the_trick { |i| puts "#{i}. hello world!" } |
In dem obigen Beispiel führt die Methode do_the_trick fünf mal den am Aufruf nebenstehenden Block aus. Also wird “1. hello world” bis “4. hello world” ausgegeben. yield kann mit und ohne Parameter aufgerufen werden. Die Parameter stehen in entsprechender Reihenfolge im Code-Block zur Verfügung.
2. Operator Overloading
Ein Feature das ich Jahrelang nicht vermisst und dafür jetzt umso lieber gewonnen habe. Ruby hat eine ganze Reihe Standard-Operatoren, die über die üblichen Methodendefinition implementiert werden können (z.B. def ==(obj)). Folgende Operatoren stehen einem zur Verfügung: ==, >, <, >=, <=, <=>, ===, +, -, *, /, %, **, <<, >>, ~, +@, -@, [], []=, .., |, ^, &, =~
Selbstverständlich wird man viele dieser Operatoren nicht im Tagesgeschäft unterbringen können. Daher hier eine kurze Liste der vermeindlich nützlichsten Operatoren:
- def == (obj) # Gleicheit: Prüft die aktuelle Instanz auf Gleicheit mit der hineingereichten. Kann true bei Gleicheit oder false bei Unterschied liefern.
- def <=> (obj) # Wertprobe: Prüft die aktuelle Instanz gegen die hineingereichte auf Reihenfolge. Dieser Operator wird Beispielsweise von Array.sort genutzt, um die Elemente eines Arrays sortieren zu können. Ist die eigene Instanz höherwertig als die hineingereichte wird -1 zurückgeliefert. Ist die Wertigkeit beider Instanzen gleich, soll die Methode 0 wiedergeben. Ist das andere Objekt höherwertig, hat die Methode den Wert 1 zu liefern. Auf diese Art, können auch komplexe Klassen auf einfachem Wege und zentralisiert für die Sortierung vorbereitet werden.
- def << (obj) # Input: Bei Objekten des Typs Array wird der << Operator genutzt, um neue Elemente an das Ende des Arrays anzufügen.
- [] (index) # Zugriff auf Skalar: Bereits bekannt in Verbindung mit Array und/oder Hash dient dieser Operator zur Referenzierung von in der Instanz gekapselten Objekten. Passend hierzu gibt es ebenfalls den []= Operator, der allerdings zwei Argumente entgegen nimmt. Das erste als Index/Schnlüssel und den Zweiten als Wert/Objekt.
3. Sprechende Syntax
Die Syntax einer Programmiersprache ist in erster Linie vor allem eines: Geschmackssache. Vor nicht allzu langer Zeit, habe ich die C Syntax noch für die Symphatischste gehalten. Nach einiger Zeit Ruby Programmierung, vermisse ich Curly Brace und Semikolon nicht wirklich. Die Schlüsselwörter sind praktisch zu lesen und die Syntax dennoch nicht zu umgangsprachlich wie Beispielsweise in Cobol. Aussederm bricht man sich nicht ständig die Finger bei dem Versuch Alt+Gr+Any-Key mit einer Hand zu drücken.
4. YARV: Yet Another Ruby VM
Lange Zeit war Ruby eine reine Interpreter-Sprache. Mit dem neuen Ruby 2.0 wird von Haus aus eine VM mitgeliefert, die dem Ganzen einen enormen Performance-Gewinn verleiht. Antonio Cangiano hat in seinem Blog Ergebnisse seines “Ruby Implementation Shootout” Experiments veröffentlicht, und dabei festgestellt, dass Ruby mit YARV bis zu 71% schneller performed, als Ruby 1.8.5 alleine. In konkreten Zahlen bedeutet das, dort wo Ruby1.85 im Schnitt 10,59 Sekunden für die Ausführung der Testszenarien gebraucht hat, begnügt sich Ruby1.9 inklusive YARV mit 3,05 Sekunden. Damit wird dem Argumente, dass Ruby zu langsam sei allmälich der Wind aus den Segeln genommen.
5. Ruby On Rails
Das Webframework von 37Signals sorgte in den letzten Jahren für viel Furore in der Ruby Community. Über die Beliebtheit von Rails gibt es viele Meinungen. Meiner Meinung nach ist es definitiv ein großartiges Framework! Viele Leute sind von den diversen Bling-Bling Web2.0 features wie der Scriptalicious Intergration und Plugins begeistert (ungefähr genauso viele behaupten das Gegenteil). Die waren Stärken liegen meiner Meinung nach allerdings bei den Kernfunktionalitäten:
- Die strickte Model, View Controller Architektur.
- Relationelles Datenbank Mapping mit ActiveRecord. Inklusive der Model-Filter für unterschiedlichste Beziehungsmodelle.
- Datenbank unabhängige Migration Scripts und Data Fixtures.
- Unit Tests!
6. Getters and setters the easy way
In der Regel ist es in der Objektorientierung üblich, für jedes Attribut einer Klasse jeweils eine Get- und Set-Methode zu definieren. Das ist meistens ziemlich nervig, da es sich hierbei um das ewig gleiche stupiede Stück Programmcode handelt. Matz kannte teilte diese Ansicht anscheinend, und entwarf für Ruby einen sogenannten Attribute-Accessor. Es gibt diesen in drei Ausführungen:
- lesend (attr_reader)
- schreibend (attr_writer)
- lesend und schreibend (attr_accessor)
Um Attribute-Accessor zu nutzen werden diese z.B. in den Kopfbereich, kurz nach der Klassendefinition eingebunden.
1
2
3
4
5
6
7
8
| class MyClass
attr_reader :nur_lesen
attr_writer :nur_schreiben
attr_accessor :lesen_und_schreiben
@nur_lesen = 1
@nur_schreiben = 2
@lesen_und_schreiben = 3
end |