ist etwas das man nur versteht, wenn man "IN" ist.
Also in einer Gruppe, die die Sprache auf die sich das "Referenzwerk" bezieht.
Total cool.
ist etwas das man nur versteht, wenn man "IN" ist.
Also in einer Gruppe, die die Sprache auf die sich das "Referenzwerk" bezieht.
Total cool.
Yay!
Nachdem wir das Innenleben der Software fast komplett ausgetauscht haben ist endlich die Version 2.0 fertig geworden.
Was ein Akt.
Von dem was die Software ausmacht, ist wirklich kein Stein mehr so gelassen worden wie er war.
Jede operation wurde Asyncron gemacht, alles in ein Konzept von Aktionen gepresst (und das war manchmal nicht einfach) die gescheduled werden und (wenn es das Telefon erlaubt) sogar parallel ausgeführt werden können.
Mein Hauptteil daran war das Datenmodell das den synchronen Zugriff auf das Dateisystem des Handies erlaubt - intern aber alle Operationen Asynchron abarbeitet.
Was gar nicht so einfach zu verkapseln war. (Dementsprechend sind die Unit Tests auch fast die noch mal halb so viel Code wie der eigentliche Code).
Das Design für das ich mich letztendlich entschieden habe ist recht simpel: Jeder Dateisystem-Knoten kann einen von mehreren Zuständen haben:
Jobs können zum Beispiel das Kopieren auf oder von dem Handy sein.
Dazu kommt dann natürlich noch etwas Intelligenz die diese Jobs automatisch anwirft wenn es Sinn macht (Verzeichnisse Aktualisieren wenn die GUI sie anzeigt) und unnötiges Kopieren vermeidet (Es gibt einen Cache auf der Festplatte - wird eine Datei einmal vom Handy Kopiert und dann nicht mehr Verändert wird die Kopierte ab da für Operationen verwendet.) Und nicht zu vergessen: Versionierte Backup und Restores gibt es natürlich auch noch.
Ach ja und Rasend Schnell sollte das natürlich auch sein.
War nicht leicht - aber jetzt läuft es rock-solid. Und über die Implementierung erzähle ich später mal mehr.
are not allowed on UNIX.
Damn.
Um das klarer zu machen: Ich will ein Skript schreiben, bei dem oben im shebang) hartcodiert ein Pfad zum interpreter steht.
So weit so gut. ABER. Dieser Interpreter liegt in einem Verzeichnis - und dieses Verzeichnis hat ein Leerzeichen im Namen.
Doh.
Die Regeln sagen nämlich:
The initial line of a script file must begin with #! as the
first two bytes, followed by zero or more spaces, followed by
interpreter or interpreter argument. One or more spaces or tabs
must separate interpreter and argument. The first line should
end with either a new-line or null character.
Und da hält sich auch der Mac OS X Kernel genau daran.
Ich bin auch nicht der erste der darüber gestolpert ist. Hallo Felix. :-)
Das Blöde daran: Die Implementierungen erlauben weder ein Escapen, noch ein "In Anführungszeichen Setzen" des Interpreters.
Hrmpf.
Nach einigem Nachdenken sind mir letztlich nur zwei Lösungsmöglichkeiten aufgefallen:
1) Das Programm in zwei Dateien aufsplitten - die erste startet mit /bin/sh im shebang und dann ganz normal im 'body' den normalen Interpreter mit den normalen Mitteln der Shell (die auch quotes und escapen erlauben).
2) Wenn das Programm ein File bleiben soll / muss, kann ein Polyglot) das Problem lösen.
Das sah bei mir dann so aus:
#!/bin/sh # Solves the problem that shebang lines can't contain spaces # (even escaped or quoted) in the interpreter path via a polyglot """false" exec /Users/dwt/Archiv/Code/Aktive\ Projekte/Trac/env-trac-0.11/bin/python $0 $@ """ import sys print sys.argv
Das funktioniert so:
"""false"
maskiere ich mit Hilfe des Kommandos "false" den Beginn eines Python Doc-Strings / Kommentars / Multiline-Strings.Einerseits finde ich es cool das ich diesen Workaround gefunden habe - andererseits ist das natürlich ein totaler Hack. Insofern bin ich eher dagegen.
Was ich jetzt damit Tue weiß ich jedenfalls noch nicht.
Heute hat mich Bernd auf diesen coolen Wikipedia-Artikel hingewiesen: Proxy Voting. Dort wird das was wir uns bei der Piratenpartei Berlin als Liquid Democracy vorstellen sehr schön beschrieben - insbesondere auch mit vielen Beispielen wo das schon angewendet wird.
Spannend finde ich auch das ein paar Leute wohl gleich versucht haben das in der Wikipedia einzuführen - erst mal ohne Erfolg.
Since I haven't found this info anywhere in the Blogosphere and had to painfully gather it through a long debugging stare, I'm posting it here:
If you want do debug Unit Tests in Xcode 3.1 you have to do the usual, that is:
-SenTest All
DYLD_INSERT_LIBRARIES
to ${DEVELOPER_LIBRARY_DIR}/PrivateFrameworks/DevToolsBundleInjection.framework/DevToolsBundleInjection
DYLD_FALLBACK_FRAMEWORK_PATH
to $(DEVELOPER_LIBRARY_DIR)/Frameworks
XCInjectBundle
to $(BUILT_PRODUCTS_DIR)/InvocationBuilder Tests.octest
This is of course where you have enter the name of your test bundleSo far nothing new.
What is new though is that you also set the variable XCInjectBundleInto
to point to the executable that is going to load the tests (probably to avoid the 3.0 Bug that would load the tests into the shell that GDB used to start the Application). This should be the same as the $(TEST_HOST)
variable that you have to set for the Unit Test bundle. In my case this is $(BUILT_PRODUCTS_DIR)/InvocationBuilder.app/Contents/MacOS/InvocationBuilder
.
This is quite interesting, since it means that otest
is not used anymore to start the tests, but instead RunTargetUnitTests
executes the tests directly.
Well, now that I can again debug my tests maybe I'l even get it to work with debugging Unit Tests which use Mock-Objects sometime. :-)
.. bin ich mal wieder in Wards Wiki gestolpert.
Lovely. :-)
Eines meiner Lieblingszitate über Objektorientierung kommt von Ward Cunningham: "Jedes Objekt ist eine kleine Sprache".
Ich verstehe das so das man mit jedem Objekt das man entwirft eine kleine Sprache schreibt. Eine Sprache die es einfach macht die lösung für ein spezifisches Problem darzustellen.
Fast noch wichtiger finde ich aber jetzt gerade (wo ich mich auf Arbeit mit vielen globalen Variablen herumschlage) das jedes Objekt eben auch einen eigenen Namensraum darstellt - der optimaler weise auch verschachtelt werden kann.
Wunderschön finde ich das zum Beispiel bei Ruby sichtbar: Wenn man in eine Datei direkt Code schreibt, dann ist dieser Code teil eines top-level objekts. Schreibt mann in einer Datei dann weitere Objekte, sind diese Objekte in diesem top-level objekt eingebettet.
Das Prinzip erweitert sich wunderbar zu paketen und paketen von paketen - öffentlichen und privaten klassen (fals man das braucht) etc.
Und das alles ohne ein weiteres Konzept einzuführen - nur die Objektabstraktion. (schnief Java?)
Warum nur machen das so wenige Programmiersprachen so? Objective-C jedenfalls hat noch nix in die Richtung. In C++ hat man sowieso verloren - C hat gar keine Objekte - aber man kann dafür jede Bibliothek als Objekt sehen (so man will).
Stellt sich die Frage: Übersehe ich irgend ein total geiles Feature das man erhält wenn man Pakete als ein eigenes Feature in eine Sprache einbaut?
Hmpf.
Heute habe ich mir mit Felix den Template Teil des Blogs, an dem wir gerade schrauben, angeschaut. Ziel war es eine Blog-Posting Seite zu bauen die möglichst einfach zu warten ist und gleichzeitig möglichst alle Features bietet die auch die Standard Wiki-Editier-Seite von Trac bietet.
Das geht überraschenderweise sogar ganz gut. Denn: Trac ab 0.11 verwendet Genshi als Template-Sprache und Genshi wiederum ist XML mit XPath allüren.
Will heißen wir konnten uns das Template für die normale Wiki-Eingabe nehmen und dann sagen: Aber die Überschrift oben "Editing XXXXX" soll bitte weg und dafür soll da stehen "Create Blog Entry" - ein Feature das die meisten Template-Engines schon mal nicht bieten.
Und das ist natürlich geil, weil wir nicht den kompletten Template-Source kopieren müssen um das gleiche look und feel zu kriegen.
Nur das XPath natürlich wie alles bei XML total kompliziert macht. Das heißt zum Beispiel das man damit nicht sagen kann, nimm dass und ersetze darin das gegen dies. Neeeiiiin. Natürlich ist alles andersherum.
Man sagt also: Meine Welt ist so definiert, das dies immer wenn es auftritt durch das ersetzt wird und jetzt hole ich mal das original in meine Welt hinein und magisch wird darin alles ersetzt.
Großartig.
Klar das geht - aber das hätte man auch einfacher haben können.
p.s.: Weiß jemand wie man mit XPath aus dieser Struktur
<fieldset id="changeinfo"> <legend>Change information</legend> <div class="field"> <label for="tags">Tag under: (<a href="http://xn--hcker-gra.net/cgi-bin/trac.cgi/tags"> view all tags</a>)</label><BR/> <input title="Comma separated list of tags" type="text" id='tags' name="tags" size="30" value="blog"> </div> <div class="field"> <label>Comment about this change (optional):<br /> <input id="comment" type="text" name="comment" size="60" value="" /></label> </div><br /> <div class="options"> <label><input type="checkbox" name="readonly" id="readonly" /> Page is read-only</label> </div> </fieldset>
nur das div mit dem label und input für den Kommentar herausmatchen kann?
Unsere Versuche sind erst einmal bei diesem XPath query stehen geblieben div[@id='changeinfo1']/div[@class='field']
.
GRANDIOS.
Boah war ich gestresst von der Versammlung - aber zumindest ist das Ergebnis zufrieden stellend - die wichtigsten Änderungen zur Satzung sind durchgekommen: Die neue Finanzordnung und die Regelung zum dezentralen Parteitag.
Sonst war aber leider nicht viel los - die Tatsache das so viele Piraten auf einem Fleck saßen konnte nicht genutzt werden - ausser um über GO-Anträge zu streiten.
Der Inhaltlich produktivste Teil der Veranstaltung wohl das gemeinschaftliche Besäufnis am Abend nach dem ersten Tag. Da wurde wenigstens mal überhaupt etwas Inhaltliches getan (Wenn ich mich auch nicht mehr an alles erinnern kann).
Also ein gemischtes Fazit.