Hallo,
Ich beschaeftige mich seit Jahren mit beiden Sprachen und ich glaube
auch, das die Differenzen in Punkto Produktivitaet nicht so gewaltig
sind. Sowohl Ruby als auch Python sind dynamische Sprachen die fuer
objektorientierte Programmierung ausgelegt sind und mit elementen aus
der funktionallen Programmierung angereichert wurden. Bei Ruby ist
dieses OOP Design etwas sauberer implementiert als bei Python, das
macht in der Praxis aber jetzt nicht so den riesen Unterschied.
Beide Sprachen verfuegen ueber umfangreiche Bibliotheken und eine sehr
aktive Community.
Wenn man die Sprachen aus der Sicht eines Java/C#/C++ Programmierers
betrachtet, ist es vermutlich nicht so relevant, mit welcher man
programmiert. Die groessten Umstellungen/Vorteile/Nachteile aus dieser
Sicht sind sich sehr aehnlich.
Fuer sich betrachtet gibt es aber schon einige Unterschiede. Ich versuch mal
ein paar wesentliche aufzulisten, die fuer mich besonders
hervorstechen:
1. Message Passing vs. Strukturelles Objektdesign
Der Begriff Objektorientierte Programmierung wurde in seiner
Entstehung (Simula,Smalltalk) eigentlich sehr einfach definiert: Man
unterteilt sein System in Objekte, die einen Zustand
haben. Moechte man den Zustand eines Objektes veraendern oder
abfragen, sendet man Nachrichten an das Objekt.
In Smalltalk (und damit auch in Ruby, denn Ruby ist nichts weiter als
eine neue Version von Smalltalk) wurde das Konzept auch genau so
umgesetzt.
die Zeile
lamp.lightswitch.press_button
bedeutet hier tatsaechlich: sende an die objektinstanz 'lamp' die
nachricht 'lightswitch'. Die antwort aus diese Nachricht ist wieder
ein objekt (hier ein lichtsschalter), an das eine weitere Nachricht gesendet wird.
Rechts vom '.' steht also immer eine Nachricht. Tatsaechlich ist die
schreibweise oben nur sythaktischer Zucker fuer das hier, was
ebenfalls korrektes Ruby ist:
lamp.send("lightswitch").send("press_button")
In Python betrachtet man das etwas anders, naemlich so wie in C++,C# oder Java:
Objekte werden hier wie Behaelter behandelt, die wiederum weitere
objekte enthalten koennen. Diese sichtweise kommt, so vermute ich, aus
dem Umstand, das die C++ Objekte von den Strukturen aus C inspiriert
wurden.
lamp.lightswitch.press_button()
bedeutet also in python: "greife in die objektinstanz 'lamp' hinein
und suche das element 'lightswitch' (bzw. die referenz auf dieses
objekt)." Der Punkt bedeutet hier also "gehe in". Aus dem lightswitch
Behaelter holen wir uns das MethodenObjekt "press_button" und fuehren
es aus.
Fuer den Programmierer ist das erstmal nicht so der riesen
Unterschied. Python programmierer koennen in den meisten Faellen auch
in "nachrichten an objekte" denken.
Wenn man sich laenger mit den Sprachen beschaeftigt, wird dieser
Unterschied aber immer deutlicher. Z.b. kann es in Ruby natuerlich
keine oeffentlichen Instanzattribute geben. Man kann ja ueberhaupt
nicht auf Attribute zugreifen, sondern eben nur Nachrichten senden.
Weil eine Methode in Python nichts als eine objectinstanz ist, die
teil eines "Behaelters" ist, kann man z.B. so etwas hier schreiben:
amethod = object.methode
amethod()
Moechte man in Ruby eine Methode als Objektreferenz bekommen,
muss man, wie immer in Ruby, das zugehoerige objekt danach fragen:
amethod = object.method(:methode)
amethod.call
Es gibt noch zahlreiche weitere Unterschiede zwischen Ruby und Python,
die sich auf eben diese unterschiedliche Sichtweise zurueckfuehren lassen.
Aber jetzt zu einem anderen Punkt im Sprachdesign, der fast noch wichtiger ist:
2. The one obvicious way vs. The Principle of least surprise
Ein Grundprinzip bei der entwicklung von Python: Es darf zwar immer
viele Wege geben, ein Problem zu loesen, aber es sollte nicht 2
verschiedene Konstrukte geben, die im Prinzip das selbe machen. Wenn
man z.B. alle Programmierer dazu zwingt, eine abfrage mit einem "if"
zu machen, anstatt ihnen noch switch anwesungen oder was auch immer
anzubieten, dann koennen diese Programmierer untereinander ihren code
leichter lesen (Denn sie haetten es ja genauso gemacht).
Darum gibt es in python keine switch anweisungen oder do...while
schleifen oder zaehlschleifen.
Die Ruby designer (und mittlerweile auch ich) sehen das etwas anders:
Was Chaos verursacht, ist wenn das grundlegende Sprachdesign komplex
oder undurchsichtig ist, nicht wenn es verschiedene Arten gibt eine
Schleife zu implementieren. Ob eine if oder eine case anweisung den
Code besser beschreibt, ist abhaengig von der jeweiligen Situation,
und Programmierer haben eigentlich in der Praxis nie sorgen, weil sie
ueberall Konstrukte sehen die sie anders implementiert haetten.
Vielmehr kommt man dem Programmierer entgegen wo man nur
kann. D.h. wenn man bei der Arbeit immer wieder auf Regular
Expressions stoesst, dann baut man die halt direkt in die Sprache ein.
Viele sehen solche Konstrukte dann und erinnnern sich schmerzvoll an
ihre Erlebnisse mit Perl. Das ist aber unbegruended, denn waehren man
fuer die ruby Syntax einiges von Perl uebernommen hat, ist in ruby das
sprachdesign selbst voellig konsistent. So eine "built-in" Regular
expression ist dann halt auch nichts anderes als eine objektinstanz,
an die man Nachrichten schicken kann.
3. Domain Specific Languages
Das ist der Grund warum ich jetzt mehr mit Ruby mache: Es ist, weil
flexibler, besser fuer das erstellen von internen DSLs.
Aber das hat Martin Fowler hier schon sehr gut beschrieben:
http://martinfowler.com/articles/languageWorkbench.html