Home
Für ein Nebenprojekt in Rails3 benötige ich wieder mein Rails Gem amount_field. Daher bin ich endlich dazu gekommen, es für Rails3 zu aktualisieren, wenn auch intern eher im Rails2-Style.
Infos unter GitHub.
Ich habe schon immer gedacht, Uncle Bob ist ein wenig anders (im positiven Sinne), wenn es das Vermitteln von Wissen und Erfahrung geht.
Hier jetzt der neueste Streich. Es ist nicht die Tatsache, dass es Videos sind. Es ist das Wie :).
Es lohnt sich!
Wenn ich ein Framework einsetze, habe ich folgende Erwartungen:
- Es wurde aus einer laufenden Anwendung extrahiert
- Es verfügt über eine hohe interne Qualität
- Es ermöglicht einfache Testbarkeit meines Produktionscodes
- Es lässt sich schnell und einfach installieren.
- Es verfügt über gute Dokumentation und Beispiele.
- Es bietet eine einfache und intiutive Schnittstelle
Es wurde aus einer laufenden Anwendung extrahiert.
Das Framework muss aus einer bestehenden laufenden Anwendung extrahiert worden sein. Nur dadurch hat es (zumindest für eine Applikation) seine Funktionsfähigkeit bewiesen. Im Handwerk werden nur Techniken, Konzepte usw. genutzt und weitergegeben, die sich in der Praxis bewährt haben. Erst die Erfahrung lehrt, was geht und was nicht. Gleiches gilt für ein Framework.
Gute Beispiele sind Ruby on Rails oder Spring (letzteres zumindest wegen diesem Punkt). Ein Anti-Beispiel ist EJB bis 3.0. Die Entwicklung auf der grünen Wiese hat wohl mehr Kosten beim Einsatz verursacht als Nutzen gebracht.
Es verfügt über eine Hohe interne Qualität.
Das Framework muss über eine hohe interne Qualität verfügen, d.h. gut lesbaren modularen Code und eine hohe Testabdeckung bieten. Nur so finde ich Vertrauen in das Framework und bin bereit mich darauf zu verlassen. Warum sollte ich einem Framework vertrauen, dass schluderig programmiert wurde und nicht ausreichend automatisiert getestet wird?
Es ermöglicht einfache Testbarkeit meines Produktionscodes.
Das Framework muss mir auf einfache Art und Weise ermöglichen, meinen darauf aufbauenden Produktionscode zu testen. Andernfalls habe ich den Eindruck, die Entwickler haben dem Thema wenig Beachtung geschenkt und das lässt mich skeptisch im Bezug auf den Rest des Frameworks werden.
Auch hier ist Ruby on Rails ein sehr gutes Beispiel, da ich Tests leicht erstellen und ohne laufenden Webserver ausführen kann. Ein Anti-Beispiel ist auch hier EJB bis 3.0, weil die Beans nur innerhalb des Containers getestet werden konnten und das Schreiben umständlich war. Eigentlich unglaublich, das soetwas jemals produktiv eingesetzt wurde (und wird). Bei 3.0 gibt es nun endlich POJOs und damit einfachere Testbarkeit.
Es lässt sich schnell und einfach installieren.
Wir alle sind immer unter Zeitdruck (zumindest gefühlt) und die Installation sollte daher einfach und zügig gehen. Wenn ich erst viele Abhängigkeiten auflösen muss, vergeht mir vermutlich die Lust und der Frust beginnt. Also bitte diese Arbeit nicht auf den Nutzer abwälzen.
Es verfügt über gute Dokumentation und Beispiele.
Eine gute Dokumentation, vor allem viele gute und einfache Beispiele helfen enorm bei der Einarbeitung. Wenn ich direkt ein Archiv herunterladen, auspacken und loslegen kann, bin ich eher angefixt. Auch Videos sind hier eine gute Unterstützung.
Vielleicht sollte ich noch anfügen, dass das Framework keine Eierlegendevollmichsau sein sollte, sondern sich auf eine Sache konzentrieren sollte, die es besonders gut macht.
Und Vorsicht mit sogenannten Standards! Ein Framework ist nicht Standard, weil ein Firma es als solches benennt. Standard soll nur werden, was sich über lange Zeit bewertet. Also ruhig hinterfragen.
Und was sind deine Kriterien?
Mac-Tastenkombination: vorheriges und nächstes Wort in iTerm und Terminal
26. January 2011 | 0 commentsHier eine Lösung, um für ein deutsches Tastaurlayout unter Mac eine Tastaturkombi (Tastaturbelegung) für vorheriges oder nächstes Wort im Terminal bzw. im iTerm festzulegen.

Terminal
Am einfachsten ist es den Hacken bei “Wahltaste als Meta-Taste setzen” zu aktivieren. Leider erzeugt ALT-@ dann nicht mehr das @-Symbol :(

Daher habe ich mich für “Ctrl-Taste Linkspfeil” und “Ctrl-Taste Rechtspfeil” entschieden. Dazu die Einstellungen des Terminal-Programms aufrufen und im Reiter “Einstellungen” die gewünschte auswählen. Dann rechts im Reiter “Tastatur” den Eintrag “Ctrl-Taste Linkspfeil” auswählen und auf Bearbeiten klicken. Folgende Einstellung sind zu tätigen. Den Eintrag im Textfeld erhält man durch “Esc” und danach “b” :

Analog dann für “Ctrl-Taste Rechtspfeil” mit “Esc” und “f”.
iTerm
Wer statt Terminal das Programm iTerm verwendet, geht wie folgt vor. Unter “Bookmarks” den Eintrag “Manage Profiles …” aufrufen und unter “Keyboard Profiles” “Global” auswählen.

Den Eintrag “ctrl-num-cursor-left” auswählen bzw. neu anlegen und folgende Einstellungen vornehmen:

Eventuell den Hacken bei “Higi interception priority” setzen. Analog für “ctrl-num-cursor-right” :

Abei eine Liste einige wichtiger Tastaturkombis:
Ctrl-a -> go to the start of command line
Ctrl-e -> go to the end of command line
Ctrl-p -> previous command in history
Ctrl-n -> next command in history
Ctrl-f -> next character in command line
Ctrl-b -> previous character in command line
Ctrl-r -> reverse search in history file
Ctrl-d -> delete current character
Ctrl-h -> backspace
Ctrl-k -> delete from the prompt to the end of command line
Ctrl-u -> delete from the prompt to the beginning of command line
Ctrl-_ -> undo (yes, but limited)
Meta-< -> go to beginning of history file
Meta-> -> go to end of history file
Ctrl-< -> go to previous word in command line
Meta-b -> go to previous word in command line
Ctrl-> -> go to next word in command line
Meta-f -> go to next word in command line
Meta-d -> delete next word in command line
(from the actual position of the prompt)
Und nun schön üben :)
Gibt es Alternativen? Welche Tastaturkombi hast du hinzugefügt?
Um mich beim Schreiben von Quellcode daran zu erinnern möglichst sauberen Quellcode zu schreiben, habe ich als Gedankenstütze die schöne Aussage “Schreibe Code wie ein Autor” entdeckt (Quelle: Clean Code).
Ich selber habe ein paar Artikel in Fachzeitschriften und sogar ein Buch geschrieben. Wenn ich schreibe, habe ich eine Botschaft, ich möchte etwas vermitteln (meist fachliches Wissen). Und ich möchte, dass der Leser mich versteht. Ich schreibe den Artikel oder das Buch nicht für mich, sondern für den Leser.
Ok, ich schreibe auch für mich, weil man durch das Schreiben über ein Thema (oder auch durch das Präsentieren) das Thema selber besser versteht. Schreiben ist auch ein Stück Selbstverwirklichung und natürlich auch Marketing.
Letztlich hat man beim Schreiben immer den Leser vor Augen. Und genau so sollte es auch beim Schreiben von Quellcode sein! Sicher immer wieder fragen, ob den Code auch ein anderer leicht versteht (oder ich selbst zu einem späteren Zeitpunkt). Nicht aufhören, wenn es funktioniert. Erst aufhören, wenn der Code auch leicht verständlich ist.
Lasse den Code reviewen
Bevor ich einen Artikel oder ein Buch als fertig abgebe, lasse ich das Geschriebene von Freunden und Kollegen reviewen. Ich möchte ein Feedback, ob der Text verständlich ist und keine fachlichen Fehler enthält (und keine Rechtschreibfehler ;) ). Das macht vermutlich jeder Autor.
Auch diese Möglichkeit gibt es in der Softwareentwicklung und verbreitet sich als Praktik immer mehr. Ich spreche von Code Reviews und auch Pair Programming. So wie das Feedback dem Autor hilft, seinen Text zu überdenken, helfen Code Reviews den Quellcode verständlicher zu machen. Pair Programming ist quasi das permanente “Verständlichermachen” des Codes.
Also, immer daran denken: “Schreibe Code wie ein Autor!”
Ressourcen
- Buch: Clean Code
- Blog: Clean Code – Oder der gute Programmierer
Immer wieder kosten IT-Projekte mehr als geplant oder scheitern ganz. Die Gründe sind vielschichtig und häufig nicht technischer Natur. Dennoch muss man sich fragen, was wir als Programmierer zum Erfolg von Projekten beitragen oder auch nicht.
Irgendwo habe ich gelesen: “Schlechte Programmierer schreiben Code, der vom Computer verstanden wird. Gute Programmierer schreiben Code, der von Menschen (anderen Programmierern) verstanden wird.” (kennt jemand die Quelle?).
Das Thema des guten Programmierers ist komplex, aber das Zitat bringt die Sache auf den Punkt. Wenn es um das Schreiben von Quellcode geht, gibt es zwischen Programmierern sehr große Unterschiede.
80% aller Programmierer Schreiben unsauberen Quellcode
Wenn es nur um das Funktionieren des Quellcode geht, bekommen das vermutlich 80% aller Programmierer hin. Wenn es um das Schreiben von sauberen Quellcode geht, sind 80% aller Programmierer eher schlecht als gut. Und das finde ich sehr bedenklich, da sauberer Quellcode essentiell für den Erfolg eines Projekt (eines Softwaresystems) ist.
Was wenn Juristen, Medizinern, Architekten, Handwerkern so schludrig wären. Wo wären wir dann? Wahrscheinlich dort, wo wir jetzt mit der IT sind. Noch weit am Anfang.
Mit schlecht ist hier nicht vorsätzlich schlechte Arbeit gemeint. Eher eine Unwissenheit, Faulheit oder das fehlende Verständnis für die notwendigen Disziplinen eines guten Programmierers.
Vielleicht sind 80% sehr hoch gegriffen. Vielleicht habe ich einen besonders hohen Anspruch, was guten Quellcode ausmacht. Wenn ich sehe, was möglich ist und das mit dem vergleiche, was ich in Projekten sehe, neige ich zu 80%. Das schliesst meinen eigenen Code (zum Teil) mit ein :)
Unsauberer Quellcode hat seinen Preis
Sicher gibt es unzählige Anwendungen, die funktionieren. Es kann also nicht so schlecht um unsere Zunft bestellt sein oder? Aber zu welchem Preis funktionieren diese Systeme? Und vor allem zu welchem Preis der Wartung und Weiterentwicklung?
Sicher hat Software ihren Preis, denn die Entwicklung ist nach wie vor aufwendig. Was für den Manager ein Knopf auf der Seite ist, bedeutet für den Programmierer häufig ein Wunder schaffen. Entweder zahlt man den Preis (bei guten Programmierern) oder man zahlt ihn doppelt (bei schlechten Programmierern). Insgesamt kosten die meisten Projekt aber deutlich mehr als notwendig.
Ein für mich ganz wesentlicher Aspekt ist die interne Qualität des Quellcode, die langfristig deutlich zur Kostenreduzierung beiträgt. Der Punkt ist für mich wichtig, weil ich als Programmierer genau hier etwas beitragen kann. Und zwar, indem ich Quellcode schreibe, der nicht nur funktioniert, sondern auch für andere Programmierer gut lesbar und gut verständlich ist.
Was ist sauberer, gut lesbarer, verständlicher Code?
Prinzipien, Praktiken und Beispiele guten Quellcodes finden sich in CleanCode [1]. Pflichtlektüre!
Siehe auch Schreibe Code wie ein Autor
Warum ist verständlicher Quellcode wichtig?
80% aller Kosten für Software sind Wartungskosten. Die initiale Erstellungen nimmt also den kleineren Teil ein. Beim Schreiben von Code muss langfristiger gedacht werden.
Das Funktionieren des Features ist trotz aller Umstände immer möglich und wird häufig als einziges Mass für das Entwicklungsende verwendet. Es ist offensichtlich. Entweder es funktioniert oder es funktioniert nicht. Das für Menschen lesbarer Quellcode für die langfristige Wartung eine ganz wesentliche Rolle spielt wird nicht gesehen.
Das Projekt schreitet voran und es dauert immer länger, um Features zu entwickeln. Das Team verbringt immer mehr Zeit für die Stabilisierung des Entwicklungsprozesses und die Fehlerbehebung. Die Anzahl neuer Features pro Zeiteinheit sinkt und sinkt.
Wichtig ist zu erkennen, dass Programmierer 80% ihrer Zeit Code lesen und nicht schreiben (siehe auch When understanding means rewriting). Ebenso wird ein Grossteil der Zeit mit dem Ändern von bestehenden Quellcode verbracht. Den kleinsten Anteil bildet das Neuschreiben von Code!
Stunden und Tage gezeichnet von Anforderungsanalyse, Diskussionen, Entwicklung, Fehlerbehebung usw. sind komprimiert im Code gelandet. Bei der Wartung oder Fehlerbehebung muss der (lesende) Programmierer dieses Wissen aus dem kryptischen Code wiedergewinnen. Er muss die Absicht des Originalprogrammierers verstehen, die Geschichte hinter dem Code, die Anforderungen, das Wissen aus Stunden und Tagen. Warum hat er es so gemacht und nicht anders? Gab es keine Alternative oder hat er sie nicht gesehen?
Das ist häufig sehr mühsam und zeitaufwendig, erfordert Konzentration und möglichst keine Ablenkung. (Und ist auch dann nicht immer einfach, wenn der Leser der ursprüngliche Programmierer ist.)
Je unverständlicher der Code, um so größer die Chance, dass er nicht ausreichend verstanden wird und Änderungen neue Fehler bringen. Je unsauberer der Code, um so aufwendiger wird die Wartung oder werden Refactorings.
Daher ist es mehr als notwendig, dass der Quellcode sehr aussagekräftig und lesbar ist. Das bekommt man nicht geschenkt und kann man sich nicht kaufen. Das ist eine Disziplin, ein Handwerk, eine Kunst. Diese unterscheidet u.a. den Anfänger vom Meister, den schlechten vom guten Programmier. Schlecht verständlicher Quellcode ist die Wurzel allen Übels. Und wie gesagt, ich vermute, in 80% aller Projekte ist er eher schlecht als gut.
Am Beginn eines Projekt fällt das noch wenig auf. Aber wer auf hohe interne Qualität verzichtet, muss früher oder später dafür zahlen. Und zwar gewaltig. Ich halte es da mit der Aussage von Uncle Bob aus Clean Code : “The only way to make the deadline – the only way to go fast – is to keep the code as clean as possible at all times.”
Gründe für unsauberen Code
Warum gibt es so vielen schlechten Quellcode? Warum haben wir diesen Kern unserer Arbeit so schwer im Griff?
Kurz gesagt, weil es keine vernünftige Ausbildung gibt.
Vermutlich weil das IT-Handwerk noch so jung ist und wir erst nach und nach lernen, was wirklich wichtig ist. Am offensichtlichsten ist da, dass jemand programmieren kann, wenn das von ihm geschriebene Programm “funktioniert”. Und genau da bleiben die meisten Programmier stehen.
Das Programmieren, die tägliche Arbeit in der Diskussion mit Kollegen und am Rechner ist harte Arbeit. Das Erlernen erfordert viel Disziplin und Zeit.
Das deutsche Handwerk ist weltweit für die Qualität bekannt. Die Ausbildung gehört sicher zur besten in der Welt. Wenn ich Tischler werden will, mache ich eine Ausbildung bei einem Tischlerbetrieb. Der Meister lehrt mich in Theorie und vor allem Praxis. Mit genügend Motivation und Ehrgeiz werde ich zum Gesellen und nach Jahren auch zum Meister.
Affinität zum Thema, Motivation und Eigeninitiative sind für das Erlernen des Handwerks wichtig. Der Meister hilft mir dabei, ist mein Ausbildern und Mentor. Er sorgt dafür, dass ich das Richtige lerne (effektiv) und es richtig lerne (effizient). Das gibt es in der IT-Welt so (noch) nicht oder selten. Oder wo ist der Meister in meiner Stadt, bei dem ich in die Ausbildung gehe?
Es geht mir nicht um die Einführung eines Meisterbriefes für IT-Fachkräfte. Das ist eine andere Baustelle. Es geht um das Fehlen einer fundierte Ausbildung für Programmierer.
Jeder bringt sich Programmieren selber bei
Weder im Studium, in Instituten oder in Firmen erfolgt eine fundierte und angemessene Ausbildung. Eine Ausbildung die weiter geht als “Programmieren ist Funktionieren” (s.u.).
Jeder, den ich kenne, hat sich das Programmieren selber beigebracht. Und damit haben wir den ersten Teilzeitjob bekommen und sind in die Berufswelt als hauptberuflicher Programmierer eingetaucht. Und zwar mehr oder weniger von Null an.
Wo gibt es so etwas in anderen Bereichen? Bei Architekten, Medizinern, Juristen, Handwerkern usw.? Fange ich irgendwo als Mediziner an, weil ich schon mal meinen Hund verarztet habe? Oder als Jurist, weil ich das Grundgesetz gelesen habe?
Klar lernt man nie aus und muss sich selber immer weiterbilden. Auch ein Tischler mit gerade bestandenem Meisterbrief ist nicht am Ende, sondern eher am Anfang. Er muss weiterhin viel Erfahrung sammeln und sich in Theorie und Praxis permanent weiterbilden. Aber er hat zumindest eine solide Ausbildung (von einem Meister) erhalten, die die Grundlage für die weiteren Schritte bildet.
Wenn man bedenkt, das die Softwareentwicklung ein so wichtiger Markt und anspruchsvoller Job ist, wundert mich die nicht vorhandene fundierte Ausbildung.
Der Zugang zur professionellen Arbeit ist wohl bei keiner Zunft so einfach, wie bei der Programmierung. Meines Wissen gibt es kaum Quereinsteiger bei Architekten, Juristen, Medizinern, aber verhältnismässig viele in der IT. Damit sage ich nichts gehen Quereinsteiger. Ich meine nur, dass die Einstiegshürde in anderen Bereichen wesentlich höher ist. Wäre sie in der IT ebenso hoch, gäbe es hier wesentlich weniger Quereinsteiger.
Jeder hat heute einen Computern. Man benötigt ein gewisse Affinität zu diesem (zur IT), kauft sich ein paar Bücher und bringt sich selbst Programmierung bei. So hat es vermutlich jeder von uns gemacht, egal ob Studium, Ausbildung oder Quereinsteiger.
Programmieren ist nicht nur funktionieren
Aber was genau bringt man sich bei? Erst einmal nur Code so zu schreiben, dass der Computer (Compiler) den Code versteht und ausführt. “Hey, er zeigt mir ‘Hello World!’”
Wenn ich Sprachkonstrukte nur richtig schreibe, versteht das der Computer und das Programm läuft. Hie und da schon fummelig und manchmal nervenzehrend, aber mit der nötigen Affinität insgesamt nicht so schwer.
Es hinterlässt den Eindruck, man muss nur lernen, Code so zu schreiben, dass der Computer ihn versteht. Programmieren wird mit “funktionieren” verbunden. Wenn der Code funktioniert, kann ich programmieren, wenn nicht, dann nicht. Das ist logisch und offensichtlich.
Was weniger offensichtlich ist, ist den Quellcode verständlich zu schreiben. Denn dass ist eine Disziplin und kann nicht so leicht nachvollzogen werden, wie ein laufendes oder nicht laufendes Programm.
Aber genau dieser weitere Schritt, macht den Unterschied zum guten Programmierer. Oder wie es Uncle Bob in Clean Code beschreibt: “To many think we are done once the programm work”.
Und es ist ein sehr großer Schritt (eigentlich viele viele kleine) und benötigt Disziplin und Zeit. Und hier scheidet sich dann die Spreu vom Weizen. Wer wirklich gewillt ist, weiter zu kommen, Schritt für Schritt. Und wer die Mühen und den Aufwand scheut und stehen bleibt. Wer Durchschnitt bleibt oder zum Meister wird. (Analog vom Karate-Änfanger zum Meister mit mehreren schwarzen Gürteln. Man schreitet Schritt für Schritt voran und erreicht den höchsten Grad vielleicht nie.)
Keine Zeit für Weiterbildung
Ein weiterer Grund weshalb viele auf der erste Stufe stehen bleiben ist die fehlende Zeit für Weiterbildung. Weil die Basis nicht reicht und weil sich in der IT-Welt alles Wissen ständig weiterentwickelt, muss man sich ständig weiterbilden.
Aber kaum hat man die Basis erlernt, startet man im Job. Und hier hat man eines nicht und das ist Zeit. Jedes Projekt läuft immer unter Hochdruck und die 40 Stunden pro Woche reichen dafür gerade aus. Eine Weiterbildung erfolgt nur, wenn man selber in der Freizeit Bücher liest oder ausprobiert. Und mittlerweile wird die Weiterbildung in der Freizeit quasi von jedem Mitarbeiter erwartet.
(Chef: “Für Weiterbildung ist jetzt keine Zeit. Machen sie es in der Freizeit, machen allen anderen Kollegen auch!”) Kein Wunder, das viele nur das Nötigste lernen, um im Job dranzubleiben.
Man kann nur hoffen, dass die Firma und die Kollegen wissen, was richtig ist und es richtig machen und diese quasi als Meister, Auszubildender oder Mentor fungieren. Und man selbst sein Wissen an andere weitergibt. Darüber hinaus kommt es eben auf die eigene Einstellung an.
Bin ich ein guter Programmierer?
Ich habe schon viel schlechten Code geschrieben. Die Anwendung funktioniert, keine Frage. Aber verständlicher Quellcode ist anders. Wie gesagt, ich wusste es nicht besser, denn ich habe es nie wirklich gelernt. Und das gilt für alle meine Kollegen auch.
Erst nach und nach habe ich wesentliche Disziplinen erkannt und erlernt und bin so stetig besser geworden. Ein wesentlicher Schritt nach vorne war das Lesen vieler Bücher, der Austausch mit gleich gesinnten Kollegen und ganz konkret der Einsatz der testgetriebene Entwicklung.
Clean Code Developer – Software Craftsmanship
Ich könnte hier eine Reihe weitere Punkte aufführen, aber stattdessen verweise ich lieber auf Clean Code Developer. Es enthält quasi alles, was ich für essentiell halte, um ein guter Programmierer zu werden oder zu sein.
Ob ein solides Verständnis von OO, der Einsatz von TDD, von statischer Codeanalyse, Continuous Integration, Code Reviews, Pair Programming oder die eigene Weiterbildung. Alles, alles trägt letztendlich zu sauberem Quellcode bei!
Was mir gefällt, ist dass die vielen wichtigen Prinzipien und Praktiken schrittweise durch das Wertesystem durchlaufen werden. Zu einem Zeitpunkt konzentriert man sich immer auf ein paar Punkte. Dann wechselt man die Farbe und befolgt eine Zeit andere Werte. Am Ende angekommen, beginnt man von vorne. Durch das kontinuierliche Durchlaufen verinnerlicht man alle wesentliche Punkte. Werde ich mal ausprobieren.
Ebenso bin ich angetan von der Bewegung des Software Craftsmanship.
Beide haben das selbe Ziel und zum grossen Teil die selben Prinzipien und Praktiken.
Fazit
Fehlende Ausbildung und fehlende Zeit sind zwei wesentliche Faktoren für schlechten Quellcode. Dieser führt früher oder später zu aufwendigerer Wartung, mehr Fehlern, weniger Zeit für neue Features und zu stetig steigenden Kosten.
In beiden Punkten sind wir Programmierer arme Schweine. Es liegt an uns, ob wir die Mühen und Anstrengungen auf uns nehmen, uns kontinuierlich zu verbessern, um zum Clean Code Developer werden.
In diesem Sinne, ich bin dann mal weg, mich weiterbilden!
Resourcen
Ich bin vergangene Woche aus dem Orga-Team der Rails-Konferenz ausgestiegen. Die Organisation und Planung hat zuletzt nicht mehr meinen Vorstellungen entsprochen. Es hat mir dadurch weniger Spaß gemacht und beruflich bin ich auch sehr eingespannt.
In den vergangenen 4 Jahren haben wir immer sehr gutes Feedback zur Konferenz erhalten. Daher möchte ich mich auf diesem Weg herzlich bei alle Sponsoren, Helfern und Teilnehmern für die prima Unterstützung in den Jahren bedanken. Ohne Euch wäre die Konferenz nicht so erfolgreich gewesen!
Vielleicht finde ich 2011 die Motivation und Zeit eine Konferenz in Hamburg zu organisieren. Mal sehen, in wie weit Interesse dafür besteht.
Ich wünsche allen Beteiligten eine gute Zeit, vielleicht sieht man sich mal wieder.
Bis dahin.
Danke und Gruß, Thomas
Aufgrund einiger Nachfragen, hier kurz eine "Pressemitteilung" :)
Zum Buch "Rapid Web Development mit Ruby on Rails" wird es erstmal keine 4. Auflage geben.
Ralf und ich sind vor allem aus Zeitgründen privater und beruflicher Art nicht in der Lage, eine neue Auflage zu Rails 3 zu schreiben. Kurzfristig gab es die Idee, dass uns Phillip Oertel unterstützt, aber der hat dann ebenfalls aus Zeitgründen passen müssen.
Die Entscheidung ist uns nicht leicht gefallen, aber vorerst geht es nicht anders.
Vielen Dank an aller Leser für das Lob und die Anregungen!
Irgendwann, vermutlich nach einem Update von Ruby und/oder Rails, stand die History meiner Rails Console nicht mehr zur Verfügung.
Nachdem ich damit eine gewisse Zeit leben konnte, wollte ich heute dem Grund auf die Schliche kommen.
Nach einigem Probieren kam ich darauf, dass die Konsole und deren History unter ~/.irb_history schon funktioniert. Sie wird allerdings durch die Datei ~/.rdebug_hist erweitert.
Ein Durchlaufen der einzelnen Einträge durch "Pfeil-Taste hoch" lief erst durch die Einträge des Debuggers und fand dann irgendwann auch die Einträge aus ~/.irb_history. Man musste nur oft genug Tippen :).
Ein Löschen der Datei ~/.rdebug_hist führte dazu, dass die letzten Einträge in der Konsole beim nächsten Aufruf sofort zur Verfügung standen.
Die Datei ~/.rdebug_hist wird durch ruby-debug (genauer ruby-debug-0.10.3/cli/ruby-debug/interface.rb) eingelesen und geschrieben. Ich habe den Code noch nicht ganz durchschaut, aber die Datei wurde trotz des Einsatzes des Debuggers bisher nicht wieder erzeugt. Sicherheitshalber habe ich die Datei selbst schreibgeschützt angelegt, um eine erneute Erzeugung zu vermeiden.
touch ~/.rdebug_hist
chmod 400 ~/.rdebug_hist
Logging in der Rails-Console reaktiviert
Darüber hinaus habe ich das Aktivieren und Deaktivieren der Logausgaben
in der Rails-Konsole wieder hinbekommen. Meine ~/.irbrc sieht wie folgt aus:
1 2 3 4 5 Wirble.init 6 Wirble.colorize 7 8 9 system(%{ri }) 10 end 11 12 if ENV.include?('RAILS_ENV') 13 14 15 ActiveRecord::Base.connection.select_all(query) 16 end 17 18 19 set_logger Logger.new(STDOUT) 20 end 21 22 23 set_logger @logger 24 end 25 26 27 ActiveRecord::Base.connection.instance_variable_get("@logger") 28 end 29 30 31 @logger ||= get_logger 32 ActiveRecord::Base.connection.instance_variable_set("@logger", logger) 33 end 34 35 end 36
Update: Ich nutze Rails 2.3.4 und Ruby ruby 1.8.7
Ein häufiger Denkfehler beim Einbinden eines Moduls per include in eine Klasse ist, dass die Methoden aus dem Modul tatsächlich in die Klasse eingefügt werden. Dem ist nicht so. Hier ein Beispiel:
"M1#foo"
end
end
include M1
end
Der Aufruf von include M1 führt intern nicht zu folgendem Code:
"M1#foo"
end
end
Tatsächlich wird durch include eine anonyme Proxyklasse erzeugt, die auf das Modul verweist und die Klasse A erhält eine Referenz auf diese Proxy-Klasse:
-> M1
end
-> proxy
end
a = A.new
a.foo
Im obigen Beispiel findet Ruby die Methode foo also nicht in der Klasse A, sondern (über die Proxy-Klasse) im Modul M1.
Suche entlang der Vererbungshierachie
Grundsätzlich gilt: Um eine Methode auszuführen, muss Ruby die Definition der Methode finden und sucht die Methode dazu entlang der Vererbungshierachie. Ein Beispiel:
include M1
include M2
end
a = A.new
a.foo
Damit ergibt sich diese Suchreihenfolge:
1) A 2) M2 (über proxy) 3) M1 (über proxy) 4) B
Die Vererbungshierachie sieht wie folgt aus:
A -> (proxy->M2) -> (proxy->M1) -> B
Es wird bei der Klasse A begonnen. Wird die Methode nicht gefunden, wird im Modul M2 gesucht. Ist die Methode hier nicht vorhanden, wird im Modul M1 gesucht und existiert die Methode hier nicht, wird in der Superklasse B nachgeschaut. Dort wiederholt sich die Suche.
Daher hat eine in der Klasse A definierte Methode immer Vorrang vor einer gleichnamigen aus einem inkludierten Modul:
"M1#foo"
end
end
-> proxy -> M1
"A#foo"
end
end
a = A.new
a.foo # => "A#foo"
Ruby sucht die Methode entlang der Vererbungshierachie und findet die Methode in der Klasse A bevor es im Modul M1 sucht.
Modulmethode über super aufrufen
Es ist sicher bekannt, dass die Methode super dazu dient, eine gleichnamige Methode in der Superklasse aufzurufen. Beispiel:
"SuperClass#foo"
end
end
"A#foo: "
end
end
a = A.new
a.foo # => "A#foo: SuperClass#foo"
Was vielleicht nicht sofort einleuchtet ist, dass auch die Modulmethode über super aufgerufen werden kann. Das Modul befindet sich (wie die Superklasse auch) in der Vererbungshierachie und daher kann sowohl die Superklassenmethode, als auch die Modulmethode über super aufgerufen werden:
"M1#foo"
end
end
include M1
"A#foo: "
end
end
a = A.new
a.foo # => "A#foo: M1#foo"
Vorrang beim Einbinden von Modulen
Werden zwei Modul eingebunden und erhalten diese dieselbe Methode, so wird die Methode des zuletzt inkludierten Moduls verwendet. Im Beispiel M2:
"M1#foo"
end
end
"M2#foo"
end
end
include M1
include M2
end
a = A.new
a.foo # => M2#foo
Einschränkung der Sichtbarkeit
Mit dem Wissen um die Wirkung von include, wird auch klar, warum die Einschränkung der Sichtbarkeit wie folgt nicht möglich ist:
"mod_method1"
end
end
"mod_method2"
end
end
include M1
private
include M2 # method mod_method2 is still public
end
A.new.mod_method1 # => "mod_method1"
A.new.mod_method2 # => "mod_method2"
Die Methoden aus dem Modul M2 sind öffentlich (public), obwohl das Modul nach dem Schlüsselwort private eingebunden wird. Und zwar, weil die Methode aus dem Modul nicht in die Klasse eingebunden werden, sondern die Klasse auf das Modul verweist (über den Proxy) und mod_method2 in M2 öffentlich ist.
Korrekt geht es wie folgt:
private
"mod_method2"
end
end
include M1
include M2
mod_method2
end
end
A.new.foo # => "mod_method2"
A.new.mod_method1 # => "mod_method1"
A.new.mod_method2 # => NoMethodError: private method ‘mod_method2’ called
for #<A:0x108d8>
Wenn eine Modulmethode nur für interne Implementierung dient, sollte die Methode auf jeden Fall als private deklariert werden.
Proxy-Klasse
Wozu dient eigentlich die Proxy-Klasse? Warum wird nicht direkt eine Referenz auf das Modul in die Klasse eingefügt? Wozu der Umweg über die Proxy-Klasse?
Die Proxy-Klasse ist notwendig, da von Modulen keine Instanzen erzeugt werden können. Dennoch möchte man eventuell Instanzvariablen von Modulen nutzen.
Inkludieren die Klassen A und B das Modul M1, so darf die Änderung einer Instanzvariablen in der Klasse A nicht den Wert in B beeinflussen. Daher gibt für A und B jeweils eine Proxy-Klasse und die die Werte hält.
Alle Proxy-Klasse verweisen auf dasselbe Modul, daher werden Änderung an Methoden des Moduls in alle Klassen sichtbar:
@foo = v
end
"M#foo: "
end
end
include M
self.foo = v
end
end
include M
self.foo = v
end
end
a = A.new(47)
p a.foo # => "M#foo 47"
b = B.new(11)
p b.foo # => "M#foo 11"
"modified M#foo "
end
end
p a.foo # => "modified M#foo 47"
p b.foo # => "modified M#foo 11"
Hoffe, ich habe für mehr Klarheit sorgen können und nicht mehr verwirrt :)
to be continued ...
Ist schon wieder zwei Wochen her, dass wir die 4. Rails-Konferenz hinter uns gebracht haben.
Diesmal fand die Konferenz im ACHAT Plaza Frankfurt/Offenbach statt. Das Hotel machte einen durchweg guten Eindruck, liegt allerdings verkehrstechnisch nicht besonders günstig. Auch der Vorraum für Pausen ist für 100+ Personen einfach viel zu klein. Die Zimmer waren sauber und geräumig und das Essen gut. Für 2010 werden wir uns aber trotzdem nach einer Alternative umschauen. Wer Tipps hat, bitte melden.
Den Gesprächen und Feedback-Bögen zur Folge, ist die Konferenz auch diese Jahr wieder sehr gut angekommen. Die Workshops, Vorträge und das Socializing zwischendurch ergaben ein rundes Bild.
Nur der Ort des Vorabend-Events kam nicht so gut an, weil die Teilnehmer vom Hotel in Offenbach erst in die Innenstadt von Frankfurt mussten. Das ACHAT-Hotel selbst wäre ein guter Ort gewesen, kostete aber zu viel Geld. Die Lounge im Fleming's Club kam bei den Anwesenden dann aber gut an. Danke auf diesem Wege nochmals an XING für das Sponsoring und die Vorträge!
Danke auch an alle Sponsoren, Speaker und Teilnehmer!!!
Dem Feedback nach zu urteilen, werden auch 2010 wieder genügend Teilnehmer kommen. In diesem Sinne: bis 2010!.
Na, dann mal schnell zuschlagen :)
Vielen Dank an Kaan für die Unterstützung!
Da ich nichts adäquates an Gems oder Plugins gefunden habe, habe ich mich selbst daran gemacht. Und das war anfangs gar nicht so einfach :)
Es ist die Eingabe (die Übertragung aus dem Formular an die Rails-Anwendung) und die korrekt formatierte Ausgabe (Anzeige im View/Formular) zu betrachten.
Eingabe
Vorweg folgende Definition:- Formatvalidierung: z.B. ist "1.234,56" ein gültiges Format?
- Wertvalidierung: z.B. ist 1.234,56 > 1250 ?
- Damit sichergestellt werden kann, dass der eingegebene Wert wirklich ein gültiges Format hat (z.B. 1.234,56), muss zunächst eine Formatvalidierung erfolgen und danach die (sichere) Konvertierung in eine Zahl 1234.56. Im Anschluss kann optional die Wertvalidierung erfolgen.
Ohne die Formatvalidierung würde Rails aus 1.234,56 den Wert 1.23 machen, ohne dass der Anwender das gegebenenfalls merkt. Und das ist schlecht.
-
Die Formatierung (Ein- und Ausgabe) hat eigentlich nichts mit dem Attribut oder dem ActiveRecord-Modell zu tun. Es handelt sich ja mehr um eine bestimmte Repräsentation eines Betrags und dafür ist das Modell nicht zuständig. Zur formatierten Anzeige werden u.a. die View-Helper von Rails genutzt.
Die Konvertierung von "1.234,56" in 1234.56 kann aber nicht auf Controller/View-Ebene erfolgen, da die Validierung der Attribute in ActiveRecord geschieht. Und die Formatvalidierung ist eben eine solche Validierung. Daher bleibt doch nur das Modell.
- Die Zuweisung als Ruby-Zahl an den Setter (an das Attribute) muss weiterhin wie gewohnt möglich sein:
p = Product.new p.price = '12.345,67' # schlecht p.price = 12345.67 # ok - Der Getter des Attributs muss den Wert als (Ruby-)Zahl liefern, damit Berechnungen weiterhin wie gewohnt möglich sind:
p = Product.new(:price => 1.23) p.price # => 1.23 damit Rechnen möglich tax = p.price * 19.0 / 100.0 - Eine clientseitige Formatvalidierung (und Formatierung) durch JavaScript ist hilfreich, verhindet aber nicht unbedingt die Übertragung falsch formatierter Beträge und daher ist eine serverseitige Formatvalidierung immer notwendig.
- Die Formatierung eines Betrags besteht immer aus den drei Werten:
- Separator (Tausendseparator)
- Delimiter (Trennung Ganzzahl und Nachkommastellen)
- Precision (Anzahl der Nachkommastellen)
Die drei Werte bilden die Formatkonfiguration:
deutsch:{ :precision => 2, :delimiter => '.', :separator => ',' }
amerikanisch:{ :precision => 2, :delimiter => ',', :separator => '.' } - Fehlermeldungen bei einen falschen Format sollten internationalisierbar sein
- Hinweis: Active Record speichert den übergebenen Wert “1.234,56” in dem Attribute "price". Erst beim Lesen des Wertes wird dieser konvertiert zurückgeliefert. Daher liefert "price_before_type_cast" den Wert “1.234,56” und "price" den Wert 1.234 zurück. Die Wertvalidierung erfolgt bei Active Record auf Basis von XXX_before_type_cast.
Als Lösung definiere ich einen eigenen View-Helper "amount_field" als Ersatz für "text_field". Das HTML sieht wie folgt aus:
<input name="product[amount_field_price]" class=" amount_field"... />
Der eingegebene Wert (z.B. "1.234,56") wird dadurch über den Parameter amount_field_price und nicht (wie normalerweise) über den Parameter price übertragen.
Zusätzlich existiert das Validierungsmakro "validates_amount_format_of", dass für jedes angegebene Attribut eine spezielle Setter-Methode (z.B. amount_field_price=(value) definiert, die den Parameter amount_field_price annimmt und Werte im Format "1.234,56" akzeptiert.
validates_amount_format_of :price
end
Nach der Validierung und Konvertierung (z.B. "1.234,56" in 1234.56) wird der Wert an das Originalattribut "price" zugewiesen und kann von weiteren Validierungsmakro geprüft werden (z.B: validates_numericality_of :price).
Ausgabe
Damit die Ausgabe des Wertes 1234.56 formatiert erfolgt (z.B. "1.234,56"), verwendet der View-Helper amount_field intern den View-Helper number_with_precision mit der global definierten Formatkonfiguration. Im Fehlerfall wird der Wert nicht formatiert, sondern wie eingegeben angezeigt.
Das Gem (oder Plugin) inklusive Dokumentation ist unter GitHub zu finden.
Freue mich über Feedback, Fragen oder Fehlermeldungen.
