Werkzeugkasten

>>Ich analysiere die Beitragsstatistik der Riesenmaschine mit einer Software zur Auswertung astronomischer Daten, die MIDAS heißt (Munich Image and Data Analysis System).

Mit dieser Software mache ich im übrigen auch ALLES andere. Abgesehen von den Dingen, die man mit einem Tastaturmakro im Texteditor erledigen kann, zum Beispiel der Auswertung von astronomischen Daten.«

Aleks Scholz, Riesenmaschine

Wenn man von einem Thema keine Ahnung hat, fällt es einem schwer, die richtigen Werkzeuge zu wählen. Das ist bei Softwareentwicklung eher noch schlimmer als in anderen Lebensbereichen, Kapital-Lebensversicherungen vielleicht einmal ausgenommen. Gleichzeitig ist es jedoch für den Spaß an der Programmierung und - bei Fortgeschrittenen - für die Arbeitsproduktivität entscheidend, mit welchen Mitteln man arbeitet.

Viele erfahrene Programmierer stehen den Mudschaheddin in Fundamentalismus und Religionstreue nicht nach. Sie verteidigen ihre Lieblingssprachen, Texteditoren und Build-systeme mit Inbrunst. Bringt man mehrere von ihnen zusammen und reicht etwas Alkohol, kann man das spontane Keimen von Religionskriegen beobachten.

Das liegt - neben Wichtigtuerei - daran, dass es für die allermeisten Fragen der Programmierung nicht die eine Sprache oder den einen Editor gibt, die bzw. der besser als alle anderen ist. Jedes Werkzeug hat Stärken, aber auch Schwächen. Bei einem sehr mächtigen Editor ist vielleicht die Einarbeitungszeit sehr lang, einem schnell zu erlernenden fehlen dafür viele Features. Da man sich aber im Laufe der Zeit an seine Werkzeuge anpasst, umgeht oder ignoriert man ihre schwachen Punkte und erkennt ihre Stärken umso besser.

Für den Einzeller unter den Programmierern lässt sich daraus die beruhigende Gewissheit schöpfen, dass man ruhig auf den Mainstream in einem bestimmten Bereich setzen kann - man wird damit schon irgendetwas erreichen. Viel genutzte Werkzeuge haben meist ein paar echte Vorteile, sonst wären sie nicht so weit verbreitet. Und ihre weite Verbreitung macht es leichter, zu Fragen und Problemen schnell eine Antwort zu finden.

Editoren

Auch wenn man größere Programme prinzipiell mit Notepad und einem Kommandozei-len-SFTP-Tool schreiben kann, ist das keine Lösung. Es ist streng genommen noch nicht einmal ein Provisorium, sondern eine schmerzhafte Wunde.

Obwohl Softwareentwicklung eine relativ komplexe High-Tech-Aufgabe ist, bei der etwas technische Unterstützung nicht schadet, kann man häufiger die Ansicht lesen, dass alles über einen Editor und Compiler Hinausgehende überflüssiger Schnickschnack sei. Das mag für Programmierer mit 20 Jahren Erfahrung tatsächlich so , ein, aber als Einsteiger sollte man sich davon nicht verwirren lassen.

Es ist wirklich absolut, vollkommen unumgänglich, dass man einen Editor einsetzt, der ...

•    UTF-8- und ISO-8859-Dateien lesen und imjeweils anderen Format speichern kann. Außerdem muss er Unix-Zeilenenden und Windows-Zeilenenden akzeptieren.

•    ein Syntaxmodul für die Sprache besitzt, in der man zu programmieren gedenkt. Dieses Syntaxmodul färbt Text unterschiedlich ein, je nachdem, ob es sich um einen Kommentar, eine Funktion oder einen Syntaxfehler handelt.

•    in mehreren Dateien gleichzeitig suchen und ersetzen kann. Editoren, die das nicht können, gibt es vermutlich außer Notepad gar nicht, deshalb muss der Ratschlag eigentlich lauten: Finden Sie heraus, wie man mit dem Editor Ihrer Wahl in mehreren Dateien gleichzeitig suchen und ersetzen kann. Beherzigen Sie allerdings auch die Warnungen vor globalem Suchen-und-Ersetzen im Abschnitt »Entwicklungsumgebungen« (Kapitel 20) und Kapitel 5.

Auch der bescheidenste Texteditor kann vermutlich mehr, als Sie in diesem Moment nutzen. Es schadet nicht, hin und wieder ein bisschen darüber herauszufinden. Zum Beispiel Folgendes:

•    Wie kann man sich Makros für häufig wiederkehrende Aufgaben basteln?

- Gibt es multiple Zwischenablagen, die es einem ersparen, ständig zwischen zwei Dokumenten hin- und herzuspringen? Oder kann man vielleicht an die Daten, die sich bereits in der Zwischenablage befinden, hinten weitere kopierte Daten anhängen?

•    Wie bringt man den Editor dazu, die Funktionen der verwendeten Programmiersprache anzuzeigen? Manchmal sind dafür Plugins erforderlich.

•    Wie kann man Regular Expressions beim Suchen und Ersetzen einschalten?

•    Wie motiviert man den Editor dazu, schlecht formatierten Code aufzuräumen? Insbesondere beim Schreiben von XML und HTML geht erfahrungsgemäß die Formatierung schnell kaputt.

Selbst wenn Sie jetzt nicht gleich herausfinden, wie das alles geht, ist es nützlich, zu wissen, ob der Editor überhaupt über diese Fähigkeiten verfügt. Irgendwann werden Sie dann verzweifelt oder motiviert genug sein, auch die Details näher zu erforschen. Die

>>Rule of Three<< (siehe Kapitel 14) leistet auch hier gute Dienste: Erledigt man zum dritten Mal etwas von Hand oder auf eine verdächtig umständliche Weise, dann sollte man vielleicht doch die paar Minuten Recherchezeit investieren und die Fähigkeiten erkunden, die der Editor wahrscheinlich für genau diese Aufgabe mitbringt.

Im englischsprachigen Wikipedia-Eintrag >>Comparison of text editors<< gibt es diverse Übersichtstabellen dazu, welche Editoren welche häufig gesuchten Fähigkeiten mitbringen. Dasselbe speziell für HTML und Webentwicklung findet sich im Eintrag >>Compari-son of HTML editors«.

Vorteile der Inkompetenz

Bis vor zehn Jahren hatte ich einen Editor, mit dessen Makros ich alles machen konnte, NoteTab unter Windows. Mit dem Kauf meines ersten Mac brauchte ich einen neuen Editor, und weder mit TextMate noch mit SublimeText habe ich je auch nur annähernd die Fähigkeiten von damals erworben. Das ist einerseits unpraktisch, und ich ärgere mich manchmal darüber. Andererseits hat mich meine Kompetenz im Umgang mit der wirklich sehr schlichten Makrosprache von NoteTab damals oft davon abgehalten, Probleme stattdessen wenigstens in, sagen wir, Perl zu lösen. Inzwischen zwingt mich meine Ahnungslosigkeit im Umgang mit meinem Editor oft dazu, eine erwachsenere Lösung zu finden, also zum Beispiel was mit Regular Expressions. Das hat unter anderem den Vorteil, dass es schneller geht und auch dann noch funktioniert, wenn ich das nächste Mal meinen Editor oder mein Betriebssystem wechsle.

Kathrin

Welche Programmiersprache ist die richtige?

»Ein Drittel aller Softwaredeveloper können mindestens eine Programmiersprache.«

Bernd Eckenfels / (geckes, Twitter, 26. September 2012

Wir gehen davon aus, dass Sie mindestens eine Programmiersprache rudimentär beherrschen, denn sonst würden Sie nicht dieses Buch lesen, sondern eines mit dem Titel »Überhaupt erst mal programmieren«. Aber vielleicht tragen Sie sich schon seit Jahren mit dem vagen Plan, eines Tages eine Zweit- oder sogar Drittsprache zu erlernen. Selbst wenn Sie sich bereits in fünf Sprachen ausdrücken könnten, wäre es kein Fehler, sich mit einer sechsten zu befassen.

Viele Menschen setzen sich in ihrer ersten oder zweiten Programmiersprache zur Ruhe und erklären, die jeweilige Sprache sei »gut genug« für ihre Pläne. Diese Trägheit hängt unter anderem mit einem Phänomen zusammen, das der Essayist und Programmierer Paul Graham am Beispiel eines Anhängers der fiktiven Sprache »Blub« beschrieben hat: »Wenn unser hypothetischer Blub-Programmierer weniger mächtige Sprachen betrach-

tet, dann weiß er, dass er nach unten schaut. Sprachen, die weniger mächtig sind als Blub, können offensichtlich weniger, ihnen fehlen Features, an die er gewöhnt ist. Aber wenn unser hypothetischer Blub-Programmierer in die andere Richtung schaut, zu den mächtigeren Sprachen, dann merkt er nicht, dass er den Blick nach oben richtet. Er sieht nur seltsame Sprachen. Vermutlich hält er sie für ungefähr so mächtig wie Blub, zusätzlich angereichert mit irgendwelchem haarigen Zeug.«1

Interview mit Lukas und Matthias

Lukas: Was mir viel gebracht hat, war, neue Sprachen zu lernen.

Matthias: Wenn man genug gelernt hat, wird es auch ganz leicht, noch mehr Sprachen zu lernen. Wenn man die grundsätzlichen Konzepte mal verstanden hat, ist das alles gar nicht mehr schwer. Der Rest ist dann nur Syntax, und die ist schnell gelernt. Das räumt auch das Hirn noch mal auf, wenn man dieselben Probleme in ganz vielen Sprachen mal gelöst hat. Einfach dadurch, dass eine Sprache ein bisschen anders aufgebaut ist, bevorzugt sie Lösungswege, die du dann auch in deiner ersten Sprache wieder verwenden kannst.

Lukas: Und es kann ja auch sein, dass du eine Sprache findest, die noch viel besser zu dir passt. Wenn man sehr mikromanagementmäßig unterwegs ist, sollte man vielleicht Assembler lernen.

Matthias: Wenn man in einer Sprache schon länger programmiert, hat man sich schon bestimmte Idiome angewöhnt, wie man Sachen macht, zum Beispiel einen String parsen oder so was. Und dann geht das in der neuen Sprache nicht mehr. Dann muss man sich neu überlegen, wie man das macht ...

Lukas: ... und merkt dabei vielleicht, oh, man hat das total umständlich gemacht oder einen veralteten Weg gewählt, oder man kommt überhaupt mal drauf, darüber was zu lesen.

Matthias: Andererseits übertragt man natürlich die in der ersten Sprache gelernten Konzepte immer auch auf andere Sprachen. Und man verlernt ja deshalb das alte Idiom nicht. Man hat dann einfach mehr im Werkzeugkasten.

Kathrin: Ich verlerne ja schon während derArbeit mit einer einzigen Sprache ständig alles wieder.

Matthias: Aber du würdest dann mehr grundsätzliche Arbeitsweisen lernen und weniger >>wie mach ich's konkret«. Das konkrete Machen kann ich mir dann für die jeweilige Sprache immer schnell wieder raussuchen. Mir so was zu merken, das lohnt sich für mich gar nicht, da müsste ich's mir in zu vielen Sprachen merken.

Lukas Hartmann und Matthias Rampke, Softwareentwickler

1

www.paulgraham.com/avg.html.

Das Netz ist voll mit mal mehr, mal weniger ernst gemeinten Aufzählungen der konkreten Vor- und Nachteile einzelner Programmiersprachen. Es ist zwar verlockend, diesen Listen eine weitere hinzuzufügen und dabei unsubtil die eigenen Vorlieben und Abneigungen einfließen zu lassen. Aber die Details solcher konkreten Empfehlungen ändern sich alle paar Jahre, und Sie lernen nicht viel dazu, wenn wir Ihnen einfach raten, »Nehmen Sie einfach Python, damit machen Sie nichts falsch!« (Obwohl Sie damit sicher wirklich nichts falsch machen.)

Der IT-Berater und Autor Geoffrey Moore teilt Technologienutzer in fünf Gruppen ein:

•    Innovators, das sind diejenigen, die die Technologien erfinden oder ganz nahe an den Erfindern dran sind.

•    Early Adapters, Technologieexperten, die gute Antennen für kommende Strömungen haben und sie sehr frühzeitig aufgreifen.

•    Early Majority und Late Majority, das sind die Nutzergruppen, die den Mainstream ausmachen. Eine Technologie, die von diesen Gruppen aufgegriffen wird, hat sich etabliert.

•    Laggards. Der unflexible Rest, der an den Tedmologien von vorgestern festhält.

Auch Programmiersprachen verbreiten sich nach einem ähnlichen Schema über mehrere, unterschiedlich risikoorientierte Nutzergruppen, und je erfahrener und technisch interessierter ein Programmierer ist, desto eher wird er zu den Early Adapters einer Sprache gehören. Das ist toll, wenn sich diese Sprache später durchsetzt, denn jetzt genießt man einen großen Startvorteil. Kann die Sprache sich jedoch nicht etablieren, hat man Pech gehabt. Jemanden, der sowieso schon mehrere Sprachen beherrscht, schmerzt das weniger, als wenn ein Ungeübterer erkennen muss, dass seine Lieblingssprache inzwischen als altbacken gilt.

Als weniger erfahrener Programmierer sollten Sie sich daher eher in der Early Majority tummeln: Sie haben einerseits keine eigenen Bibliotheken oder größeren Projekte in einer Sprache geschrieben und sind daher nicht an sie gebunden, wie es bei großen Firmen häufiger der Fall ist. Andererseits brauchen Sie länger als ein Experte, um sich in eine Sprache einzuarbeiten, und haben vermutlich auch nicht den Überblick darüber, was besonders vielversprechende neue Ansätze sein könnten.

Deshalb hier einige länger haltbare Ratschläge für die Suche nach der passenden Zweit-bis Fünftsprache:

Was eine Sprache kann, wird nicht nur durch ihre Fähigkeiten bestimmt, sondern -gerade für Anfänger - noch viel wesentlicher durch Dokumentation und Umfeld. Suchen Sie im Netz nach dem Namen der Sprache in Kombination mit documentation. Sehen Sie nach, wie gut Sie mit dem Ergebnis zurechtkommen. Manche Sprachen sind sehr ausführlich und vor allem einsteigerfreundlich dokumentiert, bei anderen ist zwar im Prinzip alles vorhanden, die Verständnishürde aber hoch, und gerade bei neueren Sprachen gibt es manchmal schlicht noch gar keine vollständige Dokumentation.

Suchen Sie nach dem Namen der Sprache plus tutorial. Testen Sie die ersten Schritte des Tutorials. Ignorieren Sie dabei die innere Stimme, die Ihnen erst mal bei jedem solchen Versuch mitteilt: »Das ist anders als bisher! Das will ich nicht!«

Finden Sie heraus, seit wann es die Sprache gibt. Ist sie jünger als fünf Jahre, dann gibt es für Ihre Bedürfnisse wahrscheinlich noch zu wenige einsteigerfreundliche Tools, zu wenig Dokumentation, zu wenige fertige Lösungen im Netz und zu viele Bugs. Die Nutzercommunity besteht aus ehrgeizigen, experimentierfreudigen Programmierern, die nicht immer die nötige Geduld für Ihre Probleme aufbringen werden. Die Antwort auf die Frage, »Bin ich denn wirklich der Einzige, der dieses Problem hat?«, ist relativ oft Ja. Ist die Sprache älter als 30 Jahre, steht man unter Umständen auch wieder allein mit seinen Problemen da, und durch die Nutzerforen rollt Tumbleweed.

Sie haben programmierende Freunde, Mitbewohner, Büronachbarn? Entscheiden Sie sich für die Sprache, in der auch die anderen arbeiten. Auch wenn die Sprache für sich genommen nicht ganz ideal für Ihre Zwecke erscheinen mag, werden viele Nachteile dadurch wettgemacht, dass Sie bei Problemen einfach jemanden fragen können. Falls die Freunde ehrgeizige Programmierer sind, die Ihnen viele Jahre Erfahrung voraus haben und sich nicht mit einer Programmiersprache aus dem Vorjahr in der Öffentlichkeit blicken lassen würden: Fragen Sie, mit welcher Sprache sie vor fünf Jahren gearbeitet haben, und nehmen Sie die.

Manchmal bestimmt die Idee, die man umsetzen möchte, die Programmiersprache: Wer für Android entwickeln will, nimmt am besten Java, für iOS-Geräte (iPad, iPhone) ist Objective-C die gängigste Sprache. Häufig ist das weitere technologische Umfeld entscheidend, wie im Fall des Web, das seit 20 Jahren einen prägenden Einfluss ausübt und HTML und JavaScript etabliert hat. Zu beidem gab es konkurrierende Ideen, aber weil das Web insgesamt so einen großen Erfolg hatte, konnten sie sich nicht durchsetzen.

Manchmal gibt es ein spezielles Tool, das Ihr Projekt entscheidend voranbringen kann, nur für ein oder zwei Sprachen. Wenn Sie sich dabei ertappen, die Zugriffsstatistiken eines Blogs mit Astronomiesoftware auszuwerten, sollten Sie vermutlich den Schritt zu einer mathematisch-statistischen Sprache wie R machen, die viele statistische Funktionen einfach eingebaut hat.

Recherchieren Sie, in welcher Sprache andere Programmierer ähnliche Probleme gelöst haben. (Und überlegen Sie dann, ob Sie nicht einfach deren fertige Lösung übernehmen können - siehe Kapitel 19.)

Vielleicht suchen Sie die richtige Sprache für ein gemeinsames Projekt mit anderen. Sind Sie der schlechtere Programmierer im Team, dann folgen Sie einfach den Vorschlägen Ihrer Kollegen und klagen Sie nicht darüber, dass Sie umlernen müssen. Betrachten Sie die Situation nicht als Zumutung, sondern als günstige Gelegenheit, eine neue Sprache in der Gesellschaft von Menschen zu lernen, die sich damit bereits auskennen. Protestieren Sie nicht auf der Basis von Viertelwissen über die vorgeschlagene Sprache (»AberJava ist doch so langat-mig!<<), wenn Sie eigentlich nur »Das ist mir zu mühsam, muss ich wirklich?«« meinen.

Wenn Sie gar kein konkretes Projekt haben, sondern nur zum Spaß ein bisschen besser programmieren lernen wollen, sollten Sie sich diejenigen Sprachen näher ansehen, die eine ganz bestimmte Denkweise gut vermitteln: Ruby, weil es eine angenehm flexible Sprache ist, Smalltalk, weil es objektorientierte Programmierung besonders elegant vermittelt, Scheme oder ein Lisp-Dialekt als Beispiele funktionaler Sprachen. Oder C bzw. sogar Assembler, weil Sie dann gezwungen werden, sich mit Grundlagen wie Pointern und Speichervervaltung auseinanderzusetzen.

Die Verlockung mag groß sein, eine Zweitsprache zu wählen, die Ihrer vertrauten Erstsprache einigermaßen ähnlich sieht. Geht es Ihnen aber nicht so sehr um schnelle Ergebnisse, sondern eher darum, ein besserer Programmierer zu werden, dann kommen Sie mit einer möglichst unähnlichen Zweitsprache schneller voran. Wenn Sie bisher mit PHP oder Ruby gearbeitet haben, sollten Sie sich C, C++ oder Java anschauen. Wenn Sie auf objektorientierte Programmierung schwören, ist Lua oder R ein interessanter Kontrast. Und wenn Sie eher traditionsreiche Sprachen wie Python oder Perl kennen, sollten Sie sich vielleicht einmal eine ganz aktuelle wie Go oder Rust anschauen.

Manchmal zählt Coolness. Wenn es Ihnen (und sei es nur heimlich) wichtig ist, in Gesprächen mit anderen Programmierern für die Wahl Ihrer Programmiersprache (und sei es nur heimlich) bewundert zu werden, und wenn diese Bewunderung Ihre Motivation steigert, dann kann eine ganz frisch erfundene Programmiersprache trotz der oben genannten Nachteile das Mittel der Wahl sein. Auch alte Programmiersprachen haben manchmal einen gewissen Coolnessfaktor, Assembler oder Lisp zum Beispiel. Sie entfalten ihre lebenslaufschmückende Wirkung allerdings eher dann, wenn Sie selbst noch sehr jung sind. Sonst kommt leicht der Verdacht auf, Sie hätten die Sprache damals auf der Höheren Töchterschule gelernt und sich seitdem nicht weiterentwickelt.

Ignorieren Sie Tabellen dazu, wie viele Zeilen man in unterschiedlichen Sprachen für ein und dasselbe braucht. Als Anfänger können Sie froh sein, wenn Sie irgendetwas irgendwie hinkriegen, da ist Kürze nicht unbedingt ein Vorteil, möglicherweise sogar von Übel.

REPL

REPL ist ein Akronym für »Read-Evaluate-Print Loop«. Das klingt jetzt angenehm nach »Oh, das ist zu komplex, kann ich zum Glück überspringen«, aber das wäre schade, denn REPLs helfen ungemein, eine Sprache zu lernen.

Ein REPL (teilweise auch Interactive Shell genannt) nimmt die Eingabe von kurzen Programmschnipseln entgegen, lässt sie laufen und gibt das Ergebnis aus. Es ist für eine Programmiersprache das, was die Shell (oder bei Windows die DOS-Box) für das Betriebssystem ist: eine interaktive Umgebung, in die Sie Anweisungen eintippen, die dann sofort ausgeführt werden - kein Kompilieren und kein Hochladen irgendwohin nötig. Das Ergebnis wird in dasselbe Fenster ausgegeben. Alle Anweisungen, die Sie eingeben, werden in einer History protokolliert, so dass Sie später wieder darauf zurückgreifen können.

Weil man in einem REPL direkte Resultate seiner Kommandos sieht, anstatt dass Zeit mit Hochladen und/oder Kompilieren vergeht, eignen sie sich besonders für explorative Programmierung: Man spielt mit der Sprache herum und probiert Dinge aus. Wenn Sie Fehler machen, sehen Sie sie sofort.

Der Ausdruck »Read-Evaluate-Print Loop« wurde für eine interaktive Lisp-Umgebung eingeführt, weil sich diese Sprache in ihrer Formbarkeit besonders gut dazu eignet. Es gibt solche interaktiven Sprachshells inzwischen aber für sehr viele Sprachen, möglicherweise haben Sie sogar schon einmal damit gearbeitet:

•    Relationale Datenbanken wie MySQL, msSQL oder PostgreSQL werden schon seit Jahrzehnten mit Kommandozeilen- oder GUI-Clients programmiert, die das interaktive Erstellen von Tabellen sowie Eingeben und Abfragen von Daten ermöglichen. Man tippt seine SELECT-Statements ein und bekommt sofort ein Ergebnis.

•    Python bringt mit iPython ein recht bekanntes REPL mit.

•    Für PHP kann man eines installieren (www.phpsh.org/).

   Ruby bringt mit irb (Interactive RuBy) ein REPL bei jeder Ruby-lnstallation mit.

•    ln Gestalt der JavaScript-Konsole ist ein REPL für JavaScript in die meisten Browser integriert. Öffnen Sie die JavaScript-Konsole, und schon können Sie JavaScriptKommandos eingeben.2

•    Mathematisch-statistische Sprachen wie R sind stark REPL-basiert, weil bei ihnen ein Großteil der Softwareentwicklung in der Modellierung von Datenauswertungsalgorithmen liegt. Eine solche Modellierung erfordert das Testen verschiedener Hypothesen, was mit dem explorativen Modell eines REPL besonders einfach und schnell geht.

lm Gegensatz dazu sind REPLs für Sprachen wie C++ seltener, deren Quellcode erst vollständig kompiliert wird und die eher für Systemprogrammierung und GUis verwendet werden. Der Grund dafür ist, dass man solche Aufgaben nicht gut in kleine Codeschnipsel zerlegen und interaktiv entwickeln kann. Und zumindest früher dauerte es einfach zu lange, bis ein Programm kompiliert war.

Als Benutzer einer derartigen interaktiven Umgebung können Sie Variablen setzen, die für die Dauer der Session erhalten bleiben. Analog dazu können Sie Funktionen definieren und ein paar Zeilen später aufrufen. Das funktioniert wie ein Taschenrechner, nur für Programmiersprachen und viel großartiger.

Hier ein Beispiel in Ruby mit dem REPL irb:

C:\scripts>irb

irb(main):OOl:O> puts "hello"

hello

=> nil

Hier passiert Folgendes: In der ersten Zeile starten wir mit dem Befehl irb das Interactive RuBy, kurz irb. Dann geben wir die Anweisung puts "hello" ein, was nichts anderes als

2

Falls Sie den Menüeintrag nicht finden, benutzen Sie Firefox und installieren Sie die Erweiterung Firebug. Dort finden Sie die JavaScript-Console unter »Console«.

eine Prim-Anweisung ist. In dem Moment, in dem wir die Returntaste drücken, wird sie ausgeführt und die Ausgabe hello erscheint auf dem Schirm. Zum Schluss gibt irb noch den Ausdruck = > nil aus. Alles hinter = > ist der Rückgabewert der Ruby-Anweisung. puts gibt zwar einen String auf dem Bildschirm aus, würde aber als Funktion keinen Rückgabewert liefern, daher erscheint hier nil.

Ganz anders sieht es aus, wenn Sie in irb Zahlen addieren:

irb(main):002:0> 1+1 = > 2

Man kann in REPLs auch Variablen setzen, die für die Laufzeit der REPL-Sitzung erhalten bleiben:

irb(main):003:0> pinkie_count = 3 => 3

irb(main):004:0> pinkie_count -= 1 => 2

irb(main):005:0> puts "Zahl der kleinen Finger: #{pinkie_count}"

Zahl der kleinen Finger: 2 => nil

Hier definieren wir zunächst die Variable pinkie_count und weisen ihr den Wert 3 zu. Dieser wird von irb auch gleich ausgegeben. In der nächsten Zeile korrigieren wir den Variablenwert, indem wir 1 abziehen. Der Wert 2 wird ausgegeben, was zeigt, dass die Variable pinkie_count weiterhin definiert ist und ihren Wert hält. Und in der letzten Zeile geben wir ihren Wert in einer Prim-Anweisung aus (siehe Abbildung 20-1).

Haben Sie nur eine ungefähre Vorstellung davon, wie Sie ein Problem lösen wollen, dann ist ein REPL ideal: Sie können experimentieren, Ideen ausprobieren und die Ergebnisse direkt betrachten, ohne die Datei erst abspeichern und als Programm laufen lassen zu müssen. Diese Interaktivität lädt dazu ein, wie auf einem Skizzenblock kürzere Codeblöcke zu entwickeln. Wenn Sie dann davon überzeugt sind, den richtigen Weg gefunden zu haben, können Sie den Code aus der History herauskopieren und in Ihr Programm integrieren. Wenn Sie sich verrannt haben, löschen Sie alles und fangen von Neuern an.

Auch um eine Sprache nur einmal kennenzulernen und ein Gefühl für sie zu bekommen, ist ein REPL eine feine Sache. Nur wenige Menschen lernen eine Sprache dadurch, dass sie ein Buch oder die Onlinedokumentation lesen - solange man nicht ein paar kleinere Probleme in der Sprache gelöst hat, hat man keine richtige Vorstellung davon, wie gut man mit ihr auskommt. Erst durch spielerisches Ausprobieren lernt man eine Sprache kennen.

Diff und Patch

Falls Sie einen neuen, schwer zu findenden Fehler im Code haben und irgendeine Form von Versionskontrolle oder zumindest ein Backup benutzen, hilft es, ein Diff-Tool einzusetzen. Diff steht für difference, zu Deutsch »Abweichung«. Es ist ein Werkzeug, das zwei Textdateien vergleichen und die Unterschiede markieren kann. Diff-Tools gibt es sowohl mit grafischer Benutzeroberfläche als auch für die Kommandozeile. Über Letzteres ist weiter unten im Zusammenhang mit Patch-Files noch die Rede.

Meist haben GUI-basierte Diff-Tools ein senkrecht geteiltes Fenster. Auf der einen Seite wird die eine Version angezeigt, auf der anderen die andere. Links von den Codeansichten findet sich ein vertikaler Balken, der eine kondensierte Ansicht der Unterschiede vermittelt. Mit dem vertikalen Scrollbalken auf der rechten Seite kann man synchron beide Dateien durchgehen.

Diff gibt es in der einfachsten Version als Option in vielen Editoren oder als eigenes Programm, zum Beispiel WinMerge oder Diffmerge (siehe Abbildung 20-2).

Starten Sie das Programm, dann werden Sie aufgefordert, zwei zu vergleichende Dateien zu öffnen. Diff kann Code einigermaßen intelligent vergleichen. je nachdem, wie man die Programmsettings einstellt, ignoriert es zum Beispiel Unterschiede in Whitespace-Zei-chen komplett - das ist ungemein praktisch, wenn mehr als ein Programmierer mit dem Code gearbeitet hat und dadurch Tabstops zu Leerzeichen umformatiert wurden. Ein naiver Vergleich würde in dieser Situation den gesamten Text markieren, während Diff nur die inhaltlich unterschiedlichen Blöcke hervorhebt.

Häufig haben Sie bei Diff auch die Möglichkeit, ein Merge durchzuführen. Merge heißt in diesem Fall, dass die Software Änderungen auf Knopfdruck von einer Version in die andere kopiert, um etwa Konflikte aus einem Versionskontrollsystem auszubügeln. Man muss sich nur beim Öffnen der beiden Dateien ganz fest vornehmen, immer von rechts nach links oder umgekehrt zu kopieren - und an diesen Vorsatz muss man sich strikt halten, denn wenn man einmal in die falsche Richtung kopiert, verliert man die Übersicht und vergrößert das Chaos nur.

Wenn Sie lose mit anderen Entwicklern zusammenarbeiten wollen, etwa, indem Sie zu einem Open Source-Projekt ein paar kleine Änderungen beitragen, dann sollten Sie sich auch die Programme diff und patch anschauen. Häufig werden Sie nicht gleich schreibenden Zugang zum Versionskontrollsystem des Projekts bekommen, um ein paar Verbesserungen einzuspeisen, sondern die Projekteigner werden Sie bitten, einfach Patch-Files zu schicken.

Patch-Files sind Textdateien, die zeilenweise Änderungen zwischen zwei Versionen eines Textes enthalten. Das sieht dann beispielsweise so aus:

145C149

<    * Nutzer können sich selbstständig neue Accounts anlegen und vergessene Passwörter

zuschicken lassen.

>    * Nutzer können sich selbstständig neue Accounts anlegen und vergessene Passwörter

zurücksetzen lassen.

Das 145C149 in der ersten Zeile ist eine Nachricht des diff-Programms, die bedeutet: »In der einen Version des Textes fand ich folgende Stelle in Zeile 145, in der zweiten Version fand ich sie in Zeile 149.«

In der nächsten Zeile sagt das <, »diese Zeile muss raus«, und das > ein paar Zeilen später sagt, »dafür muss jene Zeile rein.« Zwischen diesen Patch-Anweisungen steht noch das ---, das die beiden trennt.

Gibt es zwischen den beiden Versionen des Textes Unterschiede an mehr als einer Stelle, dann sind im Patch-File alle Änderungen in dieser Syntax hintereinandergeschrieben.

Patch-Files werden vom Programm patch verarbeitet und von diff erzeugt. Mit dem Aufruf diff code-versionl.txt code-version2.txt > code.patch

erzeugen Sie eine Patch-Datei mit dem Namen code.patch, die Sie an jemand anderen schicken können. Dieser kann dann patch aufrufen

patch code-versionl.txt < code.patch und erhält dadurch eine Textdatei, die genau der Ihren entspricht.

Patch-Files statt der kompletten Dateien zu verschicken, bringt zwei Vorteile mit sich:

•    Der Empfänger kann in die Patch-Datei hineinschauen (es ist ja ein einfaches Textformat) und einen schnellen Überblick darüber gewinnen, was genau Sie geändert haben.

•    patch prüft den Stand der Datei, den es patchen soll. Das ist zwar keine sehr tiefgehende Prüfung, aber wenn sich beim Empfänger die Datei bereits verändert hat, warnt patch davor.

Patches können durch die Patch-Files auch rückstandslos entfernt werden: patch -R code-versionl.txt < code.patch Und schon sind alle Ihre Änderungen beim Empfänger wieder ausgebaut.

Das Tandem diff und patch ist nicht nur für Programmierer interessant, man kann damit beispielsweise auch hervorragend gemeinsam Bücher schreiben, wenn man sich nicht monatelang über die richtigen Werkzeuge und Formate streitet.1

Paketmanager

Linux-Benutzer haben hier einen Vorteil, weil sie mit großer Wahrscheinlichkeit schon für die Installation von Programmiersprachen oder Webservern mit dem Paketmanager des Systems in Berührung gekommen sind - je nach Linux-Distribution sind das beispielsweise dpkg/apt oder rpm. Für Mac OS gibt es Mac Ports und Homebrew, allerdings muss man sie erst einmal nachrüsten. Hat man das erledigt, dann kann man sich die ganze Welt der Open Source-Software nach Belieben zusammenstellen und installieren. Windows-Nutzer können zu Cygwin oder Npackd greifen.

Zwar kann man Open Source-Software wie Programmiersprachen, Datenbankserver oder Webserver auch selbst kompilieren, weil man den Quellcode ja einfach herunterladen kann und darf. Das kann aber zu einer abendfüllenden Beschäftigung werden, weil viele kleine Kommandozeilentools und Bibliotheken nötig sind, um ein größeres Open Source-Paket zu kompilieren. Wenn Sie eine veraltete Version einer Bibliothek auf Ihrem System haben, wird der Compilerlauf fehlschlagen und Sie müssen erst einmal eine neue Version installieren, bevor Sie mit der von Ihnen eigentlich gewünschten Software weitermachen können. Und beim Kompilieren der Bibliothek passiert natürlich genau das Gleiche, weil irgendeine weitere Bibliothek auf Ihrem System fehlt.

Moderne Software bringt eine Menge Abhängigkeiten zu Bibliotheken mit, zu bestimmten Compilerversionen oder sogenannten Build-Tools, also Software, die beim Kompilieren hilft. Diese Abhängigkeiten von Hand aufzulösen, ist eine undankbare Aufgabe, und genau deshalb wurden Paketmanager erfunden.

Paketmanager sorgen für einen standardisierten Installationskanal für (Open Source-)Soft-ware, indem sie nur Software in ihren Verzeichnissen (den sogenannten Repositories) zulassen, die nach den Regeln des Paketmanagers konfiguriert und strukturiert wurde. Die Paketmaimainer, also freundliche Zeitgenossen, die dafür sorgen, dass der Code mit einem bestimmten Paketmanager vertrieben werden kann, machen die ganze Arbeit. Da Sie sich Ihrerseits darauf verlassen können, dass der Paketmanager eine feste Oftwareumgebung bereitstellt, haben Sie es leichter, als wenn Sie Ihre Software für alle möglichen Plattformen in allen Versionen kompilieren müssten.

Ein weiterer Voneil beim Einsatz eines Paketmanagers ist, dass er Abhängigkeiten bändigt. Der Paketmaimainer muss nur angeben, welche Bibliotheken und Build-Tools er in welcher Version voraussetzt, und der Paketmanager kann diese bei der Installation nachladen. Für Sie als Benutzer kann es etwas erschreckend sein, wenn Sie nur einen Webserver installieren wollten und der Paketmanager zusätzlich 50 andere Pakete von Programmiersprachen bis hin zu SSL installiert, aber das sollte Sie nicht abschrecken, denn Festplatten sind heutzutage ja groß.

Wenn Sie direkt Sourcecode herunterladen und kompilieren, müssen Sie bei jeder neuen Version neu herunterladen, die Abhängigkeiten beachten, herausfinden, ob es neue Schwierigkeiten beim Kompilieren gibt und prüfen, ob die neue Version auf Ihrem System läuft. Das alles kann ein Paketmanager übernehmen und Sie müssen nur apt-get Upgrade (oder ähnlich für andere Paketmanager) eintippen, um die jeweils aktuellen Versionen zu installieren. Wollen Sie aus bestimmten Gründen (Inkompatibilitäten mit anderer Software, die nicht mit dem Paketmanager klarkommt) ein bestimmtes Paket nicht auf die neueste Version updaten, dann ist das auch kein Problem, denn der Paketmanager kann auch Updates zurückhalten.

Häufig bieten Paketmanager eine Suchfunktion im Repository an, mit der Sie gezielt nach Paketen suchen können. Auf Eingabe eines Stichworts wie »SSL<< hin gibt der Paketmanager dann eine Liste von Paketen aus, die vom SSL-Server über SFTP-Clients bis hin zu Webservern mit SSL-Umerstützung reicht.

Die Grundfunktionen der meisten Paketmanager sind ähnlich:

•    update: Der Paketmanager zieht sich aus dem Netz die Liste der neuesten Versionen der Pakete.

•    Upgrade: Mit diesem Befehl installieren Sie für ein Paket die aktuelle Version. In der Regel gibt es auch ein Upgrade, mit dem Sie alle Pakete upgraden können.

•    install: Installiert ein Paket neu, dafür müssen Sie den Paketnamen angeben.

•    remove (oder delete): Löscht ein installiertes Paket.

•    list: Gibt die Liste der aktuell installierten Pakete und häufig auch deren Versionsnummern aus.

•    find: Suche im Repository nach einem Paket.

Neben den großen Paketmanagern wie apt besitzen viele Programmiersprachen noch eigene, die sich speziell an Entwickler richten. Darin finden Sie keine Webserver, sondern Frameworks und Bibliotheken, die Sie für die eigene Programmierung einsetzen können und die Lösungen bieten, die in der Sprache selbst nicht abgedeckt sind. Diese oft »Package« genannten Module beinhalten nicht nur alle Dateien, die die Bibliothek ausmachen, sondern darüber hinaus auch Metainformationen, die unter anderem Namen und Mailadresse der Autoren, die URL der Homepage und eben auch die Abhängigkeiten auflisten. Weil diese Metainformationen maschinenlesbar sind, kann der Prozess der Paketinstallation samt dem automatischen Download und der Installation aller zusätzlich benötigten Pakete automatisiert werden.

Häufig gibt es für ein bestimmtes Problem, beispielsweise XML-Verarbeitung, mehrere konkurrierende Pakete, und die Entwickler der Sprache favorisieren kein bestimmtes davon. Sie können dann selbst entscheiden, welches Ihnen besonders sympathisch ist, und es mithilfe des spracheigenen Paketmanagers installieren. Natürlich gibt es auch verschiedene Paketformate und Paketmanager, sonst wäre ja wieder alles zu einfach. Aber keine Sorge, die Communities rund um die verschiedenen Sprachen haben sich meist auf je ein Format geeinigt.

Beispiele für Paketmanager einiger bekannter Sprachen:

•    Perl: cpan

•    Ruby: gern

•    Python: pip

•    PHP: PEAR oder Composer

•    Java: Maven2, Ivy oder Gradle

•    JavaScript: Bower oder Jam

•    Node.js: npm

•    .NET: NuGet

•    Objective-C: CocoaPods

Gelegentlich können Sie ein Paket entweder mit dem »großen« Paketmanager Ihres Systems oder mit dem spracheigenen installieren. Wir raten in diesem Fall zum spracheigenen, weil die Pakete hier häufig aktueller sind. Früher oder später werden sie auch in das Repository des systemeigenen Paketmanagers aufgenommen, aber es gibt wenig Gründe, darauf zu warten. Allerdings sollten Sie möglichst vermeiden, ein Paket mit beiden Paketmanagern zu installieren, denn dann verlieren Sie schnell die Übersicht darüber, welche Version Sie in Ihrer Software einbinden.

Frameworks

Will man Software entwickeln, die komplexer wird als ein kleines Shellskript, dann kommt man nicht darum herum, fremden Code einzubinden, der Basisfunktionalität wie

Datenbankzugriff oder XML-Parsing ermöglicht. Häufig wird man auch für ein grafisches Benutzerinterface oder eine Webapplikation auf Fremdcode zurückgreifen.

Nützlichen Code, der allgemeine und immer wieder benötigte Grundfunktionen implementiert, bekommt man in der Regel in Paketen, die als Libraries (siehe Kapitel 19) oder Frameworks bezeichnet werden. Die Abgrenzung zwischen den Begriffen ist nicht immer ganz einfach, insbesondere weil sie nicht immer sauber getrennt werden.

Als Faustregel kann man sagen: Eine Library bietet Funktionen an, die man aus dem eigenen Programm aufrufen kann. Wie man programmiert und wie man die Librar' einbindet, ist der Entwicklerin überlassen. Ein Framework hingegen ist wie ein totalitärer Staat - will man nicht nach seinen Regeln leben, hilft es nur, auszuwandem und ein anderes Framework zu nutzen, denn ein Framework macht ziemlich strikte Vorgaben dafür, wie man sein Programm zu strukturieren hat.

Etwas weniger salopp: Eine Library bietet Lösungen für einen bestimmten Problembereich an (so z.B. XML-Parser, die das Einlesen von XML vereinfachen), während Frameworks ein Gerüst für das gesamte Programm bereitstellen, in das man eigenen Code an bestimmten Stellen nach den Regeln des Frameworks einfügt. Ein Beispiel sind Web-Application-Frameworks wie Ruby on Rails, die die schnelle Entwicklung von dynamischen Websites erleichtern. Während man Libraries zu einem Programm hinzufügt und deren Funktionen aufruft, arbeiten Frameworks nach dem Hollywood-Prinzip: Don't call us, we call you. Das bedeutet, dass man als Programmierer keine main-Methode mehr schreibt und das Programm nicht selbst startet, sondern in Konfigurationsdateien des Frameworks festlegt, welche Funktionalität man will, HTML- oder Code-Templates anlegt, Datenbankschemata einrichtet und dann nur noch den Code schreibt, der für die eigene Anwendung spezifisch ist.

Das muss nicht schlechter sein als die Verwendung einer Library, denn auch wenn es abschreckend klingt, hat die Verwendung eines Frameworks Vorteile:

•    Als weniger erfahrener Programmierer hat man durch die Verwendung eines Frameworks weniger Gelegenheiten dazu, Fehler zu machen. Auch wenn das Framework nicht ideal ist, wird seine Philosophie jedenfalls nicht ganz untauglich sein.

•    Gute Frameworks bauen ein logisches, einfaches Gerüst, dessen Verwendung dem Entwickler viel langweilige Arbeit abnehmen kann.

•    Erfahrene Entwickler kennen die Philosophie, nach der das Framework entworfen wurde, und können ihren Code entsprechend einpassen.

•    Räder nicht neu zu erfinden, ist in der Softwareentwicklung allgemein von Vorteil.

Wahl des Frameworks

Da man mit der Wahl eines Frameworks vielleicht nicht gerade seine Seele verkauft, aber zumindest für die Dauer des Projekts dieses Framework heiratet, ist die Wahl des idealen Partners noch schwerer. Man kann sowohl ein Framework wählen, das zu viel übernimmt und gerade wegen dieser vielen Funktionen unübersichtlich ist, als auch eines, dessen Funktionsumfang zu gering ist. Im Zweifelsfall ist es besser, ein zu bescheidenes Framework zu wählen, weil man dann schneller versteht, wie man damit arbeitet. Fehlende Funktionen programmiert man entweder selbst oder hofft auf eine zukünftige Version mit mehr Features. Ein zu komplexes Framework führt eher dazu, dass man das Projekt nicht weiter verfolgt, sondern sterben lässt.

Bei der Arbeit mit einem Framework kommt möglicherweise ein Moment, an dem Sie sich denken, »Was wollen die um Gottes Willen, das hätte ich ohne Framework in 5 Zeilen abgehandelt.« Das ist ein normaler Teil der Arbeit mit Frameworks - da sie für sehr unterschiedliche Anwendungsfälle ausgelegt sein müssen, sind sie so generisch, dass Einfaches manchmal komplex wird. Die Alternative, alles von Grund auf selbst zu schreiben, ist allerdings auch nur so lange einfach, wie das Programm klein ist. Wird es groß und komplex, dann wächst sich auch jede Änderung zu einem größeren Unterfangen aus. Daher ist die Verwendung eines Frameworks eine Abwägungssache - was ist mehr Arbeit: benötigte Grundfunktionen selbst zu implementieren oder das gewählte Framework zu verstehen und Code und Konfigurationsdateien zu schreiben, um mit ihm arbeiten zu können?

Warnzeichen beim Umgang mit Frameworks

Wenn Sie ständig das Gefühl haben, dass das Framework Ihnen Knüppel zwischen die Beine wirft und alles viel komplizierter ist, als es sein müsste, ist die Wahrscheinlichkeit ziemlich hoch, dass Sie das grundlegende Konzept des Frameworks nicht verstanden haben und versuchen, Ihren Code mit einem anderen Konzept zu schreiben. Manche nennen das »fighting the framework«, manche nennen es »eckige Pflöcke in runde Löcher hauen«.

Frameworks folgen grundsätzlich einer bestimmten Philosophie darüber, wie sie die Zusammenarbeit von Libraries, Templates, projektspezifischem Sourcecode und Ressourcen orchestrieren. Diese Philosophie wirkt sich auch auf Ihren Code aus, denn nur wenn Sie dem Konzept des Frameworks folgen, werden Sie relativ entspannt programmieren können. Andernfalls werden Sie sich ständig über Dinge wundern:

•    »Ich müsste jetzt und hier eine Datenbankverbindung vom Framework bekommen können, aber ich finde nichts, wo ich sie beziehen könnte.« Der Fehler ist möglicherweise, dass das Framework den Entwickler von direkten Datenbankzugriffen abhalten will und stattdessen eine Schnittstelle anbietet, um die Daten wahlweise in eine Datenbank, in Dateien oder auf einen entfernten Server zu schreiben. Statt nach der Datenbankverbindung zu suchen, sollten Sie herausfinden, wo Sie Ihre Objekte dem Framework zur Aufbewahrung übergeben können.

•    »Ich müsste an dieser Stelle Ergebnisse zurückliefern, auf die ich später noch mal zurückgreifen will, aber leider sind sie bis dahin schon in der Datenbank oder an den Benutzer ausgeliefert.« Hier könnte der Fehler sein, dass das Framework eine mehrstufige Verarbeitung vorsieht, in der zunächst Parameter geprüft, dann Daten geholt und zum Schluss Werte ausgeliefert werden. Vielleicht haben Sie Ihren Code an einer falschen Stufe eingehängt.

Es ist für Anfänger schwer, das Gefühl, gegen das Framework zu arbeiten, von den normalen Schwierigkeiten während der Lernphase zu unterscheiden. Sie müssen ohnehin ständig mit den Armen rudern, um nicht unterzugehen. Aber es gibt Gelegenheiten, an denen man laut »DAS KANN! DOCH! NICHT! SO SCHWER SEIN'« schreien möchte. Dann sollte man überdenken, ob es eventuell nicht am Framework liegt, sondern daran, dass man einen Schraubenzieher als Hammer einzusetzen versucht.

Falls im Namen des Frameworks der Begriff »Enterprise« auftaucht, ist dies ein untrügliches Warnzeichen. Hier handelt es sich nicht um ein lustiges Raumschiff, sondern um ein bürokratisches Monster, das für den Einsatz in Großkonzernen geschaffen wurde. Enterprise-Frameworks werden nicht geschrieben, um ein klar umrissenes Themengebiet überschaubar abzuhandeln, sondern mit Blick auf eine Featureliste: Egal, ob gerade Aspect Oriented Programming, Cloud oder Map/Reduce die Hype-Schlagwörter sind, ein Enterprise-Framework hat irgendwelche Features, die Hype-konform sind - leider häufig mehr schlecht als recht. Der Grund dafür ist, dass in Großkonzernen nicht die Entwickler entscheiden, sondern deren Vorgesetzte zwei Hierarchieebenen höher - und die sind zum einen risikoscheu und zum anderen selten noch mit aktuellen Trends vertraut. Also wird im Zweifel lieber ein Framework einer großen Firma mit eindrucksvoller Featureliste gewählt als ein kleines, das für 95% der Anwendungsgebiete überlegen wäre.

1

ja, ja. Oder man nimmt stattdessen einfach Google Docs.