Martin Häckers Blog - Software, Go / Baduk / Weiqi, Liquid Democracyurn:uuid:d0d51cf8-c6be-310d-a416-bf22c1661ce72022-02-19T00:00:00ZHeimautomatisierung mit Tradfri, Hue und HomeKit - und e-Müll vermeiden2022-02-19T00:00:00ZMartin Häckerurn:uuid:a58210e7-1b2a-385a-90e5-d05f5b825528<p>Zu meinen Ikea Trådfri Leuchten habe ich mir jetzt einen Phillips Hue LED-Streifen dazu geholt. Letztlich aus drei Gründen:</p>
<ul>
<li>Weil die viel Heller sind als fast alle Konkurrenzprodukte</li>
<li>Weil sie auch <a href="https://de.wikipedia.org/wiki/ZigBee">ZigBee</a> verwendet und damit nahtlos in meine Ikea Trådfri infrastruktur passt (theoretisch…)</li>
<li>Weil ich mir die Ikea Bridge sehr bewusst ausgesucht habe, weil sie eben <em>ohne</em> einen Cloud zwang daher kommt.</li>
<li>Weil ich sie in einem Sonderangebot 3 Meter für 50 € bekommen habe.</li>
</ul>
<p>Well, also der Klebestreifen auf der LED-Schlange verdient diesen Namen schon mal nicht. Nicht nur das man den in 10 cm Inkrementen abpulen musste, er klebt zwar prima an der Tapete - aber nicht am LED-Streifen. WTF?</p>
<p>Davon abgesehen ist er super hell und lässt sich über Tradfri gut anbinden und steuern. ABER: Tradfri pusht ihn <em>NICHT</em> nach <a href="https://de.wikipedia.org/wiki/HomeKit">HomeKit</a> wie es das mit den anderne Ikea eigenen Produkten macht. 😣💩😣💩😣🤬</p>
<p>Software Updates spielt die Tradfri Basis auch nicht ein - aber ok, das kriege ich via Bluetooth hin, was der LED-Streifen auch noch kann.</p>
<p>Jetzt extra noch eine Hue Bridge zu kaufen, nur damit ich dieses eine Gerät auch in HomeKit schalten kann, sehe ich jedenfalls mal gar nicht ein. Also hab ich mein trusty schweizer Messer Python ausgepackt und <a href="https://github.com/dwt/home-automation">mit etwas Code</a> nachgeholfen das fehlenden Device von Trådfri nach HomeKit zu pushen. Et Voila. :-)</p>
<p>Fazit: Die Schaltzeiten leiden etwas, Kann durchaus auch mal eine Sekunde dauern, anstatt der fast instantanen schaltzeit der Lampen die direkt über die Tradfri Bridge gehen. Aber wurscht, keine extra Bridge, etwas Spaß mit Python und die Erfahrung das es leicht geht da beliebigen eigenen Code einzubinden, der z.B. schöne Hintergrund-Farbwechsel ambient Lights produziert.</p>
Elon Musks Design Philosophie2021-10-21T00:00:00ZMartin Häckerurn:uuid:b0737890-2fac-35d5-bb70-1ed4504fcf7a<p>Beim lesen <a href="https://everydayastronaut.com/starbase-tour-and-interview-with-elon-musk/">dieses Interview mit Elon Musk</a> (<a href="https://www.youtube.com/watch?v=t705r8ICkRw">hier auch als Video</a>) hatte ich wirklich Spaß.</p>
<p>Diese Dinge sind nichts neues - aber mir ist klar geworden dass ich in der Vergangenheit viel zu Wenig wert darauf gelegt habe Requirements als Dumm zu identifizieren und Los zu werden, sowie Prozesse zu löschen. Autsch. Mea Culpa - ich gelobe Besserung.</p>
<p>Hier vor allem für mich selbst archiviert:</p>
<h2>Musk’s Engineering Philosophy:</h2>
<p>Musk overviewed his five step engineering process, which must be completed in order:</p>
<ol>
<li>Make the requirements less dumb. The requirements are definitely dumb; it does not matter who gave them to you. He notes that it’s particularly dangerous if someone who is smart gives them the requirements, as one may not question the requirements enough. “Everyone’s wrong. No matter who you are, everyone is wrong some of the time.” He further notes that “all designs are wrong, it’s just a matter of how wrong.”</li>
<li>Try very hard to delete the part or process. If parts are not being added back into the design at least 10% of the time, not enough parts are being deleted. Musk noted that the bias tends to be very strongly toward “let’s add this part or process step in case we need it.” Additionally, each required part and process must come from a name, not a department, as a department cannot be asked why a requirement exists, but a person can.</li>
<li>Simplify and optimize the design. This is step three as the most common error of a smart engineer is to optimize something that should not exist.</li>
<li>Accelerate cycle time. Musk states “you’re moving too slowly, go faster! But don’t go faster until you’ve worked on the other three things first.”</li>
<li>Automate. An important part of this is to remove in-process testing after the problems have been diagnosed; if a product is reaching the end of a production line with a high acceptance rate, there is no need for in-process testing.
Additionally, Musk restated that he believes everyone should be a chief engineer. Engineers need to understand the system at a high level to understand when they are making a bad optimization. As an example, Musk noted that an order of magnitude more time has been spent reducing engine mass than reducing residual propellant, despite both being equally as important.</li>
</ol>
Was sagt mir ein Covid-Schnelltest Ergebnis?2021-05-13T00:00:00ZMartin Häckerurn:uuid:3e0fabb0-55f2-38a2-83e1-6b6a64a47a2f<p>Inspiriert von <a href="https://www.youtube.com/watch?v=lG4VkPoG3ko">diesem Video von 3Blue1Brown</a>, hat sich mein Verständnis wie man über Covid-Tests nachdenkt, grundsätzlich gewandelt.</p>
<p>Zwar war mir schon sehr lange Bewusst, dass Test-Ergebnisse kontra-intuitiv sein können, weil sie eben auch Gesunde als krank erkennen können.</p>
<p>Das ist einfach nachzuvollziehen, wenn man einen Covid-Schnelltest anschaut. Die Güte dieser Tests wird fast immer mit zwei Zahlen angegeben: Sensitivität (wie viele der tatsächlich Kranken werden erkannt) und Spezifizität (wie viele der Gesunden werden auch als Gesund erkannt). Nehmen wir an unser Test hat jetzt 90% Sensitivität und 90% Spezifität (fiktive Zahlen für leichteres Rechnen - echte Zahlen kommen später).</p>
<p>Wende ich diesen Test jetzt auf 100 menschen in einem Land an, das Zero-Covid hat. Dann sollten trotzdem 10 Personen als Krank gemeldet werden. Was heißt das jetzt? Logischerweise nix, denn es sind ja alle Gesund.</p>
<p>Gehe ich stattdessen ins Krankenhaus auf die Covid-Station und mache den Test dort mit 100 Personen, dann sollten trotzdem 10 Personen als Gesund gemeldet werden. Was heißt das jetzt? Logischerweise auch nix, die Leute sind ja schon wegen Covid in Behandlung und nicht durch den Test plötzlich gesundet.</p>
<p>Und das ist die wichtige Denk-Änderung die 3Blue1Brown in seinem Video motiviert - man muss beim nachdenken über Testergebnisse einfach immer auch darüber nachdenken wie wahrscheinlich es ist das man tatsächlich Krank ist. (<a href="https://de.wikipedia.org/wiki/Satz_von_Bayes">Bayes läßt grüßen</a>)</p>
<p>Und jetzt kommt der Dreh - alles wird viel einfacher, wenn man von vorne herein nicht denkt dass der Test mir sagt ob ich gesund oder Krank bin, sondern:</p>
<blockquote><p>Jeder Test hat ein <em>Vorhersagekraft</em>, und dieser Faktor <em>verändert meine Wahrscheinlichkeit</em> Krank zu sein.</p>
</blockquote>
<p>Es wäre also viel Einfacher, wenn man bei Tests nicht Sensitivität und Spezifizität angibt, sondern daraus die <em>Vorhersagekraft</em> des Tests berechnet. Damit kann man dann nämlich plötzlich viel einfacher Denken und verstehen. Und insbesondere ist es viel einfacher eine 'Vorhersagekraft' nicht mit 'Wahrscheinlichkeit das ich Krank bin' zu verwechseln, was einfach jeder tut der sich mit dem Thema nicht intensiv auseinander setzt.</p>
<p>Und das beste: Wenn man nicht in Prozent, sondern in Verhältnissen rechnet, dann ist das sogar präzise!</p>
<p>Wie kommt man jetzt auf diese <em>Vorhersagekraft</em> (auch Bayes Faktor genannt)</p>
<p>Jeder Test ist durch zwei Zahlen (Sensitivität[welcher Anteil der Kranken wird erkannt], Spezifität[welcher Anteil der Gesunden wird als Gesund erkannt]) bzw. durch die Komplemente davon (Falsch-Negativ-Rate, Falsch-Positiv-Rate) bestimmt.</p>
<p>Interessiert man sich jetzt für die Frage was ein Positiver-Test aussagt, kann man aus dem Quotient von Sensitivität geteilt durch Falsch-Positiv-Rate die Vorhersagekraft eines Positiven Tests und aus dem Quotient von Falsch-Negativ-Rate geteilt durch Spezifität die Vorhersagekraft eines Negativen Tests erhalten.</p>
<p>Ein Beispiel: Angenommen ein Test hat Sensitivität 90% und Spezifität 95% (also Falsch-Negativ-Rate 10%, Falsch-Positiv-Rate 5%). Dann ist die Vorhersagekraft eines Positiven Tests 90%/5%=18. Das heißt, wenn ich einen Positiven Test habe, dann weiß ich, dass sich die Wahrscheinlichkeit das ich Krank bin 18 mal vergrößert hat zu dem wie sie vorher war. Und umgekehrt: Ein Negativer Test 10%/95%≈ 1/10. In Worten: Ein Negativer Test verkleinert meine Chance krank zu sein um etwa eine Größenordnung.</p>
<blockquote><p>🤯</p>
</blockquote>
<p>Rechnet man in Prozent ist das leider nur eine Abschätzung, aber wenn man das ganze in <a href="https://de.wikipedia.org/wiki/Chance_(Stochastik">Chancen</a>) rechnet wird aus der Abschätzung eine präzise Formel!</p>
<blockquote><p>🤯 🤯</p>
</blockquote>
<p>Schauen wir also mal auf ein paar reale Zahlen an.</p>
<p>In Berlin (stand 13. Mai 21, sind nach <a href="https://pavelmayer.de/covid/risks/">Pavels Covid Tabelle</a>) derzeit einer von 394 Personen Ansteckend.</p>
<p>Für einen Covid-Test den ich gerade da habe <a href="https://images.vinocentral.de/media/pdf/87/1d/be/BOSON-SARS-CoV-2-Antigen-Schnelltest-Information-Zusammenfassung.pdf">findet sich hier</a> eine Sensitivität ~93,5% und Spezifität ~98%.</p>
<p>Die Vorhersagekraft eines Positiven Tests ist 93,5%/2% ~47. Demnach wächst meine Chance heute ansteckend zu sein von 1/394 um das fast fünfzigfache auf etwas mehr als 1/4.</p>
<p>Die Vorhersagekraft eines negativen Tests ist 6,5%/98%~0,06. Demnach wächst meine Chance Gesund zu sein um fast zwei Größenordnungen von 1/394 auf etwa 6,5/38.612.</p>
<p>Oh wie schön wäre es, wenn das auch überall so kommuniziert würde…</p>
Open Source Flugelektronik 2 - BLE und Serial2021-04-22T00:00:00ZMartin Häckerurn:uuid:9d400487-c53e-3329-9e5c-5d1fa5d3b0e6<p>Langsam nähere ich mich meinen <a href="https://github.com/lyusupov/SoftRF">Soft-RF-Geräten</a> an. Ich kann jetzt auch über <a href="./">Bluetooth Low Energy (BLE)</a> mit dem Gerät reden. Das Python Framework <a href="https://pypi.org/project/bleak/">Bleak</a> war dabei unglaublich hilfreich, da ich fast den ganzen BLE-Code sehr plattform-neutral Scheiben kann. I.e. der Code ist zwar nur auf MacOS getestet, wird aber sehr wahrscheinlich auch unter Linux funktionieren. Der Code zu diesem Post liegt <a href="https://github.com/dwt/softrf-interfacing">auf github</a>.</p>
<p>Wie läuft das jetzt? Zuerst braucht man einen BLE-Scanner, um die Adresse des Geräts zu finden. Bei mir sieht das so aus:</p>
<pre><code>% ./ble_scanner.py
........................................
[...]
0975FAB7-6F50-4B60-A0D8-9F11C817FB6D: SoftRF-f0c010-LE
[...]
</code></pre>
<p>Mit dieser Adresse kann man dann reden um sich anzuschauen welche BLE-Services sie anbietet:</p>
<pre><code>% ./ble_explore_device.py 0975FAB7-6F50-4B60-A0D8-9F11C817FB6D
Connected: True
[Service] 0000ffe0-0000-1000-8000-00805f9b34fb (Handle: 40): Vendor specific
[Characteristic] 0000ffe1-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read,write-without-response,notify), Value: b',,,,,,,,,99.99,99.99'
[Descriptor] 00002901-0000-1000-8000-00805f9b34fb (Handle: 43): Characteristic User Description) | Value: b'HMSoft'
[Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 44): Client Characteristic Configuration) | Value: b'\x00\x00'
</code></pre>
<p>Was heißt das? Das gerät bietet den Service <code>0000ffe0-*</code> an und darauf eine Characteristik <code>0000ffe1-*</code> die wiederum zwei Deskriptoren enthält. <code>00002901-*</code>und <code>00002902-*</code>. Nicht das ich BLE vollständig verstehe, aber zumindest weiß ich das ein Service der Grundsätzliche Behälter für alle BLE Interaktionen ist und eine Charactreristik einen lese und schreibbaren Wert darstellt. Deskriptoren können darin verschachtelt sein und sind entweder zusätzliche lese und schreibbare Werte oder haben einen technischen Sinn. In diesem Beispiel ist der zweite Descriptor notwendig um auf der Charakteristik nicht nur lesen und schreiben, sondern auch Notify zu implementieren -> und das braucht es für die Serielle Schnittstelle.</p>
<p>Entscheidend ist hier die Service-Charakteristik <code>0000ffe1-0000-1000-8000-00805f9b34fb</code> Hier spielt die ganze Musik. Die Serielle Ausgabe des SoftRF kann man mittels Notify davon auslesen und man kann auf die Serielle Schnittstelle schreiben indem man darauf schreibt. Soweit so simpel. Und damit kriegt man auch schon ein sehr primitives UART hin:</p>
<pre><code>% ./ble_uart.py 0975FAB7-6F50-4B60-A0D8-9F11C817FB6D
Connected, start typing and press ENTER...
0.00,0000.0000,N,00000.0000,E,0,00,100.0,0.0,M,0.0,M,,*5C
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$PFLAU,0,0,0,1,0,,0,,,*4F
$GPRMC,,V,,,,,,,,,,N*53
$GPGGA,000000.00,0000.0000,N,00000.0000,E,0,00,100.0,0.0,M,0.0,M,,*5C
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99$PFLAU,0,0,0,1,0,,0,,,*4F
$GPRMC,,V,,,,,,,,,,N*53
$GPGGA,000000.00,0000.0000,N,00000.0000,E,0,00,100.0,0.0,M,0.0,M,,*5C
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$PFLAU,0,0,0,1,0,,0,,,*4F
$GPRMC,,V,,,,,,,,,,N*53
</code></pre>
<p>Yay!</p>
<p>Nächste Tasks: das NMEA Encoding verstehen und mal schauen ob ich damit eine erste simple Visualisierung hinbekomme.</p>
Wie und wann den Retter werfen?2021-04-17T00:00:00ZMartin Häckerurn:uuid:4a1b9d86-543d-34a5-b0ec-924e3d4cf7d8<p><a href="https://www.youtube.com/watch?v=Oa1JCLqIwS0">Diesen Vortrag von Theo de Blic</a> finde ich sehr sehenswert, da er a) viel Erfahrung mit Rettern hat - immerhin 14 Retterwürfe hat er schon durch, und b) einen wunderschön strukturierten Gedanken-Ablauf hat wan und wie man seine Retter werfen soll.</p>
<p>Besonders Wertvoll fand ich die Folie 'Know your limits' in denen er wiedergibt wann Er seinen Retter wirft. Ich habe beschlossen das ich mir diese 'Gedankenkarte' auf jeden fall auch ziehen möchte. Also: 'Note to self' - Wann immer eine dieser Situationen auftritt, egal welche Höhe, ziehe ich meine Rettung!</p>
<h2>Know your limits</h2>
<h3>Höhe</h3>
<ul>
<li>Ich bin niedrig</li>
<li>Ich bin nicht sicher ob ich hoch oder niedrig bin</li>
</ul>
<h3>Verloren Fühlen</h3>
<ul>
<li>Ich weiß nicht was ich tun soll</li>
<li>Ich weiß nicht wo ich bin</li>
<li>Ich verstehe nicht was passiert</li>
</ul>
<h3>Unlösbare Situationen</h3>
<ul>
<li>Line over</li>
<li>Mehrere twists</li>
<li>Große Krawatte</li>
<li>Kaputter Flügel</li>
</ul>
Open Source Flugelektronik mit Lora2021-04-17T00:00:00ZMartin Häckerurn:uuid:8fe7de32-bbfb-385d-9e4c-ae441b249a37<p>Inzwischen gibt es mehrere Projekte die Lora Funktechnik für Ad-Hoc-Netzwerke in der Luft (und am Boden) verwenden.</p>
<p><a href="https://github.com/lyusupov/SoftRF">SoftRF</a> ist vermutlich das bekannteste, da es mit günstiger Hardware eigentlich alle Standards unterstützt. <a href="https://de.aliexpress.com/item/4001286458852.html">Dieses</a> für in der Luft und und <a href="https://de.aliexpress.com/item/4000571051141.html">dieses</a> als Gegengerät am Boden und für Experimente - jeweils in der in Europa zugelassenen 868Mhz Variante - habe ich mir besorgt, da sie nur jeweils ~25€ Kosten.</p>
<p>SoftRF kommt darauf sogar schon vorinstalliert, das ist wirklich sehr komfortabel.</p>
<p>In Betrieb lassen sich die Geräte auch ganz gut nehmen, einfach via USB an den Rechner anschließen, bei dem einen geht dann ein WLAN auf über das man es Konfigurieren kann, bei dem anderen hat man direkten Zugriff über die serielle:</p>
<div class="hll"><pre><span></span>$ pip install pyserial
$ python -m serial.tools.list_ports
<span class="o">[</span>...<span class="o">]</span>
$ python -m serial.tools.miniterm /path/to/port
</pre></div>
<p>Konfigurieren kann man das Gerät dann über eine Config-String, den man <a href="http://soaringweather.no-ip.info/SoftRF/settings.html">in diesem Web-Interface</a> generieren kann.</p>
<p>Easy peasy.</p>
<p>Next Tasks:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/NMEA_0183">NMEA</a> Nachrichten Parsen und lesbar Ausgeben</li>
<li>Das zweite Gerät über Bluetooth Low Energy verbinden</li>
<li>BLE mit einem meiner Flug-Computer-Smartphone Apps verbinden - <a href="http://flyskyhy.com">FlySkyHy</a> oder <a href="https://evario.variosoft.eu">eVario</a></li>
<li>Herausfinden was es braucht um da noch einen guten Barometrischen Sensor mit einzubauen</li>
</ul>
Crosswords Puzzle2021-03-15T00:00:00ZMartin Häckerurn:uuid:895a87f6-13a4-3267-81c9-628608a973e3<p>Kreuzworträtsel finde ich eigentlich langweilig. Aber die Idee die Vorgaben über Reguläre Ausdrücke zu machen finde ich <em>klasse</em>.</p>
<p><a href="http://jimbly.github.io/regex-crossword/">Hier geht es zum Puzzle</a> - mit Herzlichem Dank an <a href="https://github.com/Jimbly">Jimb Esser</a>.</p>
<p>Ursprünglich entworfen hat es <a href="https://web.mit.edu/puzzle/www/2013/coinheist.com/rubik/a_regular_crossword/">Dan Gulotta am MIT</a> aber die JS Implementierung von <a href="https://github.com/Jimbly">Jimb Esser</a> ist einfach Gold wert.</p>
Thermik-Gradienten lesen2021-03-14T00:00:00ZMartin Häckerurn:uuid:23bd1f52-29c2-3a35-aecc-fe7397d5869c<p>Im aktuellen Thermik-Magazin gab es einen Artikel über Thermik-Gradienten - und insbesondere diese kleine Tabelle, die es leicht macht aus der Stärke der Gradienten auf die vorhandene Thermik zu schließen. Note to self: Gradienten über 0,7 vorerst vermeiden.</p>
<p><img src="Gradient Legende.png" alt="Gradienten Legende"></p>
Dependable API Evolution2021-02-18T00:00:00ZMartin Häckerurn:uuid:1c73ef64-b4ea-3a59-93bd-e814a6091a95<p>This is an old text that I just found on my hard disk. It's too good not to publish I think, as pretty much everything in it is still completely relevant. So here goes - a shout to the past, as this was written ca. 2014. At the time I discovered Semantic Versioning - and was discontent, because it is simply not enough. We as a community need a better name for what we want to do with APIs - just Semantic Versioning is not enough to reliably move forward and stay sane.</p>
<h2>My Suggestion: Define Dependable API Evolution</h2>
<p>The problem that prompted me to write this: I am sick and tired of APIs that do not evolve and that have old warts that are not fixed. At the same time I hate APIs that make every update to multi hour 'joy-ride' of debugging and finding out why the heck my system doesn't work anymore.</p>
<p>For this I think that <a href="https://semver.org">Semantic Versioning</a> is just not enough.</p>
<p>As an API provider you should adopt a dependable API evolution strategy that gives your users timely updates and new functionality, makes updating to a your newest version a breeze and joy because of new features instead of a reason for despair because of the amount of work it requires.</p>
<p>As an API user you should demand this so that you can send you patches and actually hope that they will get into the next version in a timely manner while it is not a burden to update to new revisions. And then there is the small part of actually enjoying an API that works and is extended in a good and healthy way.</p>
<p>Consider libraries like jQuery or Apples Cocoa where it is pretty much a no brainer to update to the newest version immediately. At the same time, they stay current and adapt and absorb new emerging patterns in a timely manner while fixing old warts and making the framework more and more consistent all the time. (Ok, some warts are not fixeable, but they try very hard)</p>
<p>I think it is Common Sense to do <strong>Dependable API Evolution</strong>, but for some reason it hasn't yet caught on as common knowledge - and there is no easy way to refer anyone to a document that explains it. So here I go.</p>
<h2>Problems</h2>
<ul>
<li>API's suddenly change names / types / behaviour from version to version</li>
<li>API's are suddenly removed from version to version without a warning period</li>
<li>Bugs/ Inconsistencies in APIs are not fixed</li>
<li>New and improved patterns or API designs are not adapted in a timely matter</li>
</ul>
<p>Extremes to avoid:</p>
<ul>
<li><p>The <em>Python Standard Library Syndrome</em>: Your Library is so <em>stable</em> that a module has to be dead/ unmaintained for 3-5 years before you consider adding it to your library. Some symptoms: API changes rarely, your API has very inconsistent naming, and design pattern use varies widely across your API. Also many of the non core modules have alternatives in the wild that have a vastly more fluent / short / powerful / consistent / modern APIs. Consider the Python standard library. Almost no development happens in there, many of it's modules are 10 and more years old with only the most required bugfixes going in. Not even the standard naming convention of python is used consistently throughout it's API.</p>
</li>
<li><p>The <em>Python 3k Syndrome</em>: Your users stick with an old version of your API and are very reluctant to update. Symptoms: You are forced to release new versions of it instead focussing your engineering on the newest version. You add Interims Versions, i.e evolutions of the old API version to make it easier for your users to switch to the newest version. You release new versions of your new API that add in old features again to make it easier for your users to upgrade. Consider the introduction of Python 3.0. Nobody used it. Three major revisions where required (3.0, 3.1, 3.2) before the community is actually considering its adoption. (And now - 2021 - some 12 years after this text was written, there is still a lot of software around that is on Python 2).</p>
</li>
<li><p>The <em>Thousands of Patches Flying in Close Formation Syndrome</em>: Different parts of the API have very different fluency to it and don't match very well. Symptoms: Knowing one part of the API doesn't make it any easier to guess the names and workings of other parts of your API. Documentation cannot be consolidated by talking about the Design Patterns adopted by your framework, but instead is separated from each other and also very needed because you need to look at it for every module anew.</p>
</li>
<li><p>The <em>DOM API Syndrome</em>: Different implementations / versions of your API are so inconsistent, that it is almost impossible for users to consume all of them. Symptoms: There are adapter packages around to wrap your API and make it easier for users to actually use them and allow them to target different versions of that API that are in use in the wild. Consider the success of jQuery that does nothing that hiding the DOM-APIs behind something sane and manageable. (2021 me here - the web has started to tackle this problem, but boy, is this still a nightmare. Just the fact that projects like <a href="https://caniuse.com">can I use</a> are so much needed…)</p>
</li>
<li><p>The <em>Ruby Debugger Syndrome</em>: Different versions of your API change so much that consumers are unable to evolve an API that builds on it. Symptoms: Different versions of your API have different incompatible packages that implement the same functionality in an incompatible way. Backwards compatibility is virtually impossible. Consider the different Ruby-Debugger gems that have sprung up for the various versions of the interpreter. 'ruby-debug' for Ruby 1.8, 'ruby-debugger19' and later 'debugger' for Ruby 1.9, 'byebug' for Ruby 2.0 and it seems Ruby 2.1, already needs another different debugger package. Maybe it is 'pry' now...</p>
</li>
<li><p>The <em>Version 2 Rewrite Syndrome</em>: Symptoms: You have a branch in your repository that contains your next version, because it's so much different that you really need to retain a branch of the current version to apply bugfixes while you finish up the next version. Again, Python 2 and 3 comes to mind as an abhorrent example of this problem. 12 years after the release of Python 3.0 the, old version 2 branch was still around and kind of alive as small features where added, bugs fixed. Thats a problem - not a great achievement.</p>
</li>
</ul>
<h2>Solutions</h2>
<ul>
<li>Have a clear deprecation cycle and use it. It should stretch over multiple versions, and depending on the size or importance of that Deprecated API, this could be several major versions.</li>
<li><p>Your deprecation cycle should contain these steps (which could itself be a multi version rollout)</p>
<ul>
<li>Deprecated APIs are clearly marked in the documentation and source.</li>
<li>There is a clear statement in the source or documentation what the expected alternative is. What is the the developer expected to do / use instead?</li>
<li>Using a deprecated API should emit a warning.</li>
<li>Deprecated API is removed from the documentation. Still using it raises a warning.</li>
<li>Switch that warning to an error for developers, while only warning users.</li>
<li>Then and only then it should disappear. </li>
</ul>
<p>This is the single most important thing to do, everything else follows from this.</p>
</li>
<li>Don't just change / remove API. You released it? It's out there. Deprecate it but retain it for a time and then remove it! Document what users are expected to do instead. This documentation should be referred to / included in the warning that is raised when that API is used.</li>
<li>Document warts that you cannot fix anymore because they are too engrained in the API and are too widely adopted. It is important that your users understand that this is a wart and nothing to use as an example for others or patches that they send you. This ensures that your errors of the past are not repeated.</li>
<li>Never miss an opportunity to change your API to make it more uniform and or adopt a deeper pattern across it.</li>
<li>Focus a major part of your documentation on the patterns that underly your API and then don't repeat yourself in every part of the documentation but just refer to it.</li>
</ul>
<p>Do this and your API becomes more and more coherent over time. Users of such an API can often just use a broad lisit of your API packages / objects / methods that are easy to scan / search. With that they can get an overview of what is available at a glance. They will often not need detailed documentation as they can just guess how stuff works, what stuff is named, how error handling works, … All of that makes for coding that is enjoyable and code just flows out of your fingers.</p>
<p>Also, users will update in a heartbeat allowing you to actually focus on newer versions, instead of having to maintain long term stable old versions and waste developer time on this rather non productive stuff.</p>
<p>What do you think? Should I set up a webpage like <a href="http://semver.org">semver.org</a>? Do we need stickers like <img src="https://img.shields.io/badge/Dependable%20API%20Evolution-1.0-success" alt="Dependable API Evolution">?</p>
<p>Text will be evolved (on Github)[<a href="https://github.com/dwt/Dependable_API_Evolution">https://github.com/dwt/Dependable_API_Evolution</a>]</p>
<p>Feedback welcome.</p>
Yeehaw! Endlich wieder ein Blog!2018-07-16T00:00:00ZMartin Häckerurn:uuid:76b8ddbb-b7f4-3df6-9fb0-dba24029518d<p>Lange hat es gedauert - Ahem.</p>
<p>In den letzten Monaten habe ich mich mit <a href="https://getlektor.com">Lektor</a> auseinandergesetzt. Mit ein Paar Plugins (<a href="https://github.com/humrochagf/lektor-creative-commons">CreativeCommons</a> und <a href="https://github.com/lektor/lektor-markdown-highlighter">Markdown Highlighter</a>) kann man viel Spaß beim Blog-Post schreiben haben.</p>
<p>Der große Vorteil von Lektor ist, dass man eine komplett statische Seite damit rendert. Man kann die Seite danach also über ein CDN ausliefern - 'Internet Scale' ist also gar kein Problem…</p>
<p>Solche Systeme gibt es natürlich viele - aber mit Lektor kriegt man zusätzlich noch ein CMS (das Lokal läuft) - oder auch hinter <code>.htaccess</code> geschützt laufen kann, so dass man keine Sorgen haben muss, dass einem über so eine Webseite der Server aufgemacht wird.</p>
<p>Aber Lektor überzeugt auch mit einer moderat einfachen <a href="https://www.getlektor.com/docs/api/">API</a>, selbst plugins dafür zu schreiben ist einfach und macht Spaß. Fast wie es bei <a href="https://trac.edgewall.org">Track</a> ganz am Anfang auch einmal war. ☺️</p>
<p>Ich freue mich darüber dass ich jetzt eine voll-responsive Seite haben, die mit HTML und CSS wirklich auskommt - no JS needed. (Ich werde aber vielleicht in der Zukunft für Experimente auch JS in der Seite verwenden). Für jetzt ist es erst mal das Experiment wie lange ich ohne JS auskomme.</p>
<p>Da wäre zum Beispiel das Menü - das auf Mobil mit Animation schön aufklappt. Hierzu habe ich verschiedene Techniken kombiniert.</p>
<ol>
<li><p>Die Verhältnisse der ganzen Abmessungen werden über <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables">CSS-Variablen</a> und <a href="https://developer.mozilla.org/de/docs/Web/CSS/calc">CSS-Calc</a> einmal global gesetzt. Das geht zwar noch nicht vollständig, da man CSS Variablen <a href="https://stackoverflow.com/questions/40722882/css-native-variables-not-working-in-media-queries#40723269">nicht in Media Queries einsetzen kann</a>, aber immerhin. Einzig dass man Stylesheets noch nicht 'nested' aufschreiben kann stört.</p>
</li>
<li><p>Die Animation beim klick auf das <a href="https://de.wikipedia.org/wiki/Hamburger-Menü-Icon">Hamburger Menü</a> sowie das Öffnen des Menüs kommt komplett ohne JS aus. Damit das geht braucht es ein DOM Element, dass den State 'ein oder ausgeblendet' hält, gleichzeitig via CSS abgefragt werden kann sowie diesen State durch Klick auf ein anderes Element ändert. Well, dafür funktioniert lustiger Weise das <code><input type=checkbox id=menu-state></code> Element. Das wechselt den <code>checked</code>-Zustand, was mann dankenswerter Weise in CSS mittels <code>:checked</code> herausfinden kann. Der Clou ist aber, dass man irgendwo anders im Dokument ein <code><label for=menu-state></code> haben kann, auf das man Klicken kann um diesen State zu wechseln. Und <code><label></code> kann man im Gegensatz zu <code><input type=checkbox></code> in allen Browsern vernünftig stylen. Und man kann mittels <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations">CSS-Animationen</a> alles animieren. Fuck yeah!</p>
</li>
</ol>
Lockless Algorithms2015-02-14T00:00:00ZMartin Häckerurn:uuid:eb502ea1-c872-354b-a2ed-37da2b8d4fd1<p>Schon lange habe ich keine so passende Visualisierung mehr für etwas gesehen:</p>
<p><a href="https://en.wikipedia.org/wiki/Non-blocking_algorithm">Lockless Algorithms / Schlosslose Algorithmen</a>:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/ufK2XRGUjuc" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><p><a href="http://devopsreactions.tumblr.com/post/110529123748/lockess-algorithm">via devopsreactions</a></p>
Melderecht Datenweitergabe jetzt ohne Zustimmung2012-07-12T00:00:00ZMartin Häckerurn:uuid:f9b2c4b3-498a-38e3-b72a-93628bcc1502<p>Das ist doch ein Juwel: Melderechter sollen in Zukunft meine Daten an jedes Industrieunternehmen weitergeben dürfen - wenn die Firma die Daten für ein "update" schon vorhandener Daten anfragt.</p>
<p>Was pikanterweise die Voraussetzung fast jeder Anfrage ist.</p>
<p>Dem kann man dann gar nicht mehr widersprechen - de fakto hat man also keine Möglichkeit mehr dieser Geschäftspraktik der Meldeämter wenigstens für sich persönlich Einhalt zu gebieten.</p>
<p>Compact hält dagegen und hofft auf 200.000 unterstützer in möglichst kurzer Zeit:</p>
<p><a href="http://www.campact.de/melderecht/sn1/signer">http://www.campact.de/melderecht/sn1/signer</a></p>
<p>Dafür!</p>
SSL Certificate Trouble2011-11-18T00:00:00ZMartin Häckerurn:uuid:55f253b1-c615-3b3e-b74a-00b812b567ae<p>If you should ever stumble upon this bug, consider yourself very lucky that I have found the solution to this already, because it took me <em>AGES</em> to figure this out. No shit.</p>
<p>So here's the problem: We used a self signed certificate on on of our servers and curl and all tools relying on curl just couldn't connect to this server at all (with certificate validation). Despite the fact that the root certificate that signed the server certificate was happily in my keychain and marked as trusted.</p>
<p>The solution first: Turns out that the Keychain will eat certificates in many formats, specifically it supports DER and PEM. curl however can't use the DER certificate in the keychain and just reports it as missing. Exporting the certificate, converting it to PEM and then reimporting it (making sure to remove the DER version beforehand) fixed it.</p>
<p>I converted the file with this command
<code>openssl x509 -inform DER -in some.ser.ver.der -out some.serv.ver.pem</code></p>
<p>Here's some of the error messages I got:</p>
<div class="hll"><pre><span></span><span class="gp">% </span>curl -I https://some.serv.ver -v
<span class="go">* About to connect() to some.serv.ver port 443 (#0)</span>
<span class="go">* Trying some.ip... connected</span>
<span class="go">* Connected to some.ser.ver (some.ip) port 443 (#0)</span>
<span class="go">* SSLv3, TLS handshake, Client hello (1):</span>
<span class="go">* SSLv3, TLS handshake, Server hello (2):</span>
<span class="go">* SSLv3, TLS handshake, CERT (11):</span>
<span class="go">* SSLv3, TLS alert, Server hello (2):</span>
<span class="go">* SSL certificate problem, verify that the CA cert is OK. Details:</span>
<span class="go">error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed</span>
<span class="go">* Closing connection #0</span>
<span class="go">curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:</span>
<span class="go">error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed</span>
<span class="go">More details here: http://curl.haxx.se/docs/sslcerts.html</span>
<span class="go">curl performs SSL certificate verification by default, using a "bundle"</span>
<span class="go"> of Certificate Authority (CA) public keys (CA certs). If the default</span>
<span class="go"> bundle file isn't adequate, you can specify an alternate file</span>
<span class="go"> using the --cacert option.</span>
<span class="go">If this HTTPS server uses a certificate signed by a CA represented in</span>
<span class="go"> the bundle, the certificate verification probably failed due to a</span>
<span class="go"> problem with the certificate (it might be expired, or the name might</span>
<span class="go"> not match the domain name in the URL).</span>
<span class="go">If you'd like to turn off curl's verification of the certificate, use</span>
<span class="go"> the -k (or --insecure) option.</span>
</pre></div>
<p>If you hit this brick wall - hope this helps you too.</p>
Mappei Stützen und Rechnungsstellung2011-07-12T00:00:00ZMartin Häckerurn:uuid:cadcbbbe-0824-3eb4-bac5-94db67a4b98f<p>Gerade habe ich endlich für mein GTD-System ein super-Zubehör gefunden, <a href="http://classei.de/de/boxen/mappenstuetzen.html">Mappenstützen von Classei</a>. Der große Vorteil davon: Die Mappen stehen in den Boxen auch stabil wenn diese nicht voll sind - damit kann man seine GTD-Ablage viel entspannter aufbauen. :)</p>
<p>Und noch ein witziges Detail: Classei gewährt 2% Skonto wenn man zügig bezahlt. Das bedeutet natürlich das sie eigentlich 2% mehr verlangen, wenn man nicht zügig bezahlt. Ich wette aber, dass das viele Leute dazu veranlasst schnell zu bezahlen. Und das finde ich einen schönen Trick. :-)</p>
Musik ist doch was feines2011-04-05T00:00:00ZMartin Häckerurn:uuid:e2cdcdf6-cdd6-301d-951a-e6526191a6d9<p>Da gibts so viele Möglichkeiten.</p>
<ul>
<li><a href="http://www.youtube.com/watch?v=dmoDLyiQYKw">Auf einem Floppy-Drive</a></li>
<li><a href="http://www.robotlab.de/instru/video.htm">Auf einem Roboterarm</a></li>
<li><a href="http://www.youtube.com/watch?v=Ht96HJ01SE4">Auf einem Scanner</a></li>
<li><a href="http://www.youtube.com/watch?v=qEG-1iYpgKU">Tesla Spulen</a></li>
<li><a href="http://www.youtube.com/watch?v=fp4jQNa_9sY">Festplatten</a> <a href="http://www.youtube.com/watch?v=g8Y1i6_IMwU">und nochmal</a></li>
<li><a href="http://www.youtube.com/watch?v=OhnK5LdUCiQ">Schleifgeräten</a></li>
</ul>
Iranische Männer weinen nicht...2011-03-21T00:00:00ZMartin Häckerurn:uuid:04cda5c1-d229-34a8-8a4f-ed445a00c4b5<p>... hat Ihm seine Mutter beigebracht als er ein Fahrad wollte dass sie sich nicht leisten konnte. Und dann weinte er so stark dass er sein Auto nicht mehr weiter fahren konnte und am Straßenrand anhalten musste.</p>
<p><a href="http://www.thegreenwave-film.com/">http://www.thegreenwave-film.com/</a></p>
<p>Dieser Film hat mich tief traurig gemacht, weil es Länder wie den Iran gibt, in denen so viele Menschen nicht ihre Freiheit genießen und so sorgenfrei aufwachsen und leben können wie ich das hier konnte und kann.</p>
<p>Sehr sehenswert.</p>
Ägypten2011-01-30T00:00:00ZMartin Häckerurn:uuid:e0b721e6-c4bb-369d-a95d-9e9fd2eac3d7<p><a href="http://twitpic.com/3u6gvc">http://twitpic.com/3u6gvc</a></p>
<p>Dabei läufts mir jedesmal wenn ich das anschaue kalt über den rücken.</p>
Umfragen und Ergebnisse - so gehts!2011-01-10T00:00:00ZMartin Häckerurn:uuid:d088f698-ed47-37bd-86f2-77b871974fde<p>Viel zu selten kriegt man mal bescheid wenn man an einer Umfrage / Untersuchung teilgenommen hat und dann endlich die Ergebnisse vorlegen.</p>
<p>Um so schöner wenn das mal funktioniert!</p>
<p><a href="http://www.philhist.uni-augsburg.de/lehrstuehle/germanistik/sprachwissenschaft/ada/runde_7/">Die Uni Augsburg hat das mal richtig gemacht!</a></p>
<p>Und dann auch gleich <a href="http://www.philhist.uni-augsburg.de/lehrstuehle/germanistik/sprachwissenschaft/ada/runde_8/">zur nächsten Runde eingeladen</a>. Jawohl!</p>
Liquid Feedback2011-01-03T00:00:00ZMartin Häckerurn:uuid:d01b3242-3864-3d90-897d-2a3f887719e3<p><a href="http://darkbln.wordpress.com/2011/01/03/offener-brief-liquid-democracy/">Darauf</a> bin ich heute gestoßen.</p>
<p>Interessant.</p>
<p>Was mir durch den Kopf geht: Schade, What goes around comes around, wie geht es mit Liquid bei den Piraten weiter? Wie geht es bei dem Projekt weiter wenn die haupt-Triebfeder nicht mehr treibt?</p>
<p>Mal nachdenken.</p>
Die meisten wissenschaftlichen Ergebnisse sind falsch2011-01-03T00:00:00ZMartin Häckerurn:uuid:066472b0-872f-35f9-9bc4-e71a7d8fea1d<p>Geiler Titel eh? Trotzdem das Ergebnis gut replizierbarer wissenschaftlicher Forschung. Hach die Ironie.</p>
<p><a href="http://www.newyorker.com/reporting/2010/12/13/101213fa_fact_lehrer?currentPage=all">Hier gibt es dazu einen sehr schönen Artikel.</a> (via fefe)</p>
Angst vor Badewannen?2010-11-24T00:00:00ZMartin Häckerurn:uuid:b6b6736d-da76-31a3-9aed-27601212ba36<p>Diese ganze Terror-Panik-Mache geht mir sowas von auf den Geist - das ich in Diskussionen dazu schon immer ganz ungemütlich werde.</p>
<p>Und immer fallen mir dann die entscheidenden Argumente dazu nicht ein - zum Beispiel zu so einem Security-Theater wie gerade am hier am Bahnhof, wo irgend ein Arsch eine Tüte hat stehen lassen und für Stunden der ganze U-Bahnhof gesperrt war und alle U-Bahnen weiträumig umgeleitet / gesperrt wurden.</p>
<p>Grah!</p>
<p>Da kann ich mich doch nur einem <a href="http://www.schneier.com/blog/archives/2007/12/refuse_to_be_te.html">Blogpost von Bruce Schneier</a> anschließen:</p>
<p>I am not afraid of terrorism, and I want you to stop being afraid on my behalf. Please start scaling back the official government war on terror. Please replace it with a smaller, more focused anti-terrorist police effort in keeping with the rule of law. Please stop overreacting. I understand that it will not be possible to stop all terrorist acts. I accept that. I am not afraid.</p>
<p>Jawoll!</p>
<p>Bitte anschließen - und <a href="http://www.youtube.com/watch?v=ka5FdP-gNF0">das Video dazu</a> kucken.</p>
Nukleare Abschreckung2010-11-19T00:00:00ZMartin Häckerurn:uuid:3ef4346f-24ea-3787-8184-f82999833f8b<p>Bei den Gorleben Protesten kriegt man ja inzwischen doch eine ganze menge gute Informationen - sogar manchmal über die großen Medien. Und man interessiert sich auch mal ein wenig zu dem Thema.</p>
<p>Sehr gut gefallen hat mir dabei <a href="http://gffstream-3.vo.llnwd.net/c1/download/1289332860/quarks/wdr_fernsehen_quarks_und_co_20101109.mp4">diese Quarks & Co Sendung</a> die ich hier auch wärmstens weiterempfehlen möchte.</p>
<p>Vor allem war mir überhaupt nicht klar WIE groß die Katastrophe in der Asse derzeit eigentlich ist.</p>
<p>Anschaubefehl.</p>
<p>Ein paar Gedankenanstöße:</p>
<ul>
<li>Wenn es eine Stelle gibt an der so gegen sämtliche Regeln des Verstandes und der Sicherheit verstoßen wurde</li>
<li>Dann gibt es in der Nähe von dieser Stelle noch mehr ähnliche Probleme</li>
<li>Eines davon <a href="http://www.spiegel.de/wissenschaft/technik/0,1518,654829,00.html">zum Beispiel das AKW Biblis</a>. Die Techniker dort wollen es nicht mehr Reparieren da sie dann "... mit einem Bein im Gefängnis ständen...".</li>
<li>Jetzt bitte genau nachdenken wie viele dieser Problemfälle immer noch vor uns Geheim gehalten werden.</li>
</ul>
<p><em>grusel</em></p>
<p>Update: Wer noch nicht genug gegruselt ist, dem empfehle ich <a href="http://elementarfragen.de/2010/06/ef03-tschernobyl/">diesen Podcast mit Sebastian Pflugbeil</a> der sich als Atomphysiker mal den Reaktor in Tschernobyl sehr genau angeschaut hat (er ist dort gewesen!).</p>
Interessante Details zur Castor Lieferung2010-11-08T00:00:00ZMartin Häckerurn:uuid:f12be98d-6401-32e8-85a8-3c1f727ffd6c<ol>
<li>Die Castoren sind (durch die Strahlung?) 120 grad heiß wenn sie geliefert werden, Eier die man darauf wirft verkohlen sofort. :-)</li>
<li>Die Castoren müssen erst mal 30 Jahre auskühlen bevor sie überhaupt in einer Salzmine endgelagert werden können</li>
<li>Diese 30 Jahre stehen sie in einer Blechhalle nicht weit von Gorleben und strahlen da (hoffentlich nicht) vor sich hin</li>
<li>Bevor sie in Gorleben eingelagert werden können müssen sie noch in kleinere Behälter 'Pollux' genannt umgefüllt werden</li>
<li>Die Technologie dafür gibt es noch gar nicht</li>
<li>Gorleben als Endlager ist noch gar nicht genehmigt</li>
</ol>
<p>Krass. <a href="http://www.zeit.de/2003/48/Gorleben">via</a></p>
Unsere Obsession mit der Shell2010-10-26T00:00:00ZMartin Häckerurn:uuid:eeea5555-a9ea-33de-80a2-076bfc8a1aa7<p>Grade dachte ich mir ich mache mal wieder zum Spaß etwas an einem Open Source Projekt, checke es aus und will es mal bauen um etwas im Code herum zu lesen - und das erste was mir passiert ist das der Build-Prozess einfach irgendwann verstirbt.</p>
<p>Nach einiger Debugging Zeit stellt sich dann heraus das das selbstgestrickte build-system (eine Sammlung von Shell-Scripten) halt nicht mit spaces im Pfad zu den Sourcen klarkommt.</p>
<p>Gnarf! Wieso macht man sowas in Shell? Muss das sein?</p>
<p>Ok, aber es gibt ja workarounds, und die kenne ich ja auch und die lassen sich ja auch relativ einfach einbauen. ABER: Nicht mal die Abhängigkeiten ([<a href="http://pkg-config.freedesktop.org/">pkg-config</a>] in diesem Fall) baut mit spaces im Pfad.</p>
<p>ARGH!</p>
<p>Und natürlich haben die ein <a href="http://www.shlomifish.org/open-source/anti/autohell/">Autohell</a> buildsystem an das ich nun wirklich nicht ranfassen will. :-(</p>
<p>Wie sollen wir als Softwareentwickler eigentlich irgendwann zu dem Punkt kommen wo unsere Software auch nur so etwas einfaches wie Pfade korrekt verarbeitet - also mit Leezreichen, Umlauten und Sonderzeichen (jep '/' ist auch gemeint) - wenn nicht mal unsere Eigenen Build-Tools und Shell-Sprachen damit verlässlich klar kommen? Also die Basis auf die einfach immer wieder zurückgegriffen wird?</p>
<p>Unglaublich.</p>
Objective-C Metaprogrammierung: Blöcke zu Methoden2010-06-20T00:00:00ZMartin Häckerurn:uuid:6b20c8fd-cabc-364e-a374-0bed3dd07d1c<p>Die Ruby Welt verwendet Blöcke (Closures) liebend gerne für alles mögliche. Zum Beispiel als Builder-Methapher um Baumstrukturen (XML, GUI's, HTML, Tests) in der Sprache hinzuschreiben und dann nur noch in die Target-Sprache zu rendern.</p>
<p>Das sieht in Tests zum Beispiel so aus:</p>
<div class="hll"><pre><span></span><span class="n">describe</span> <span class="s2">"something"</span> <span class="k">do</span>
<span class="n">it</span> <span class="s2">"should do fnord"</span> <span class="k">do</span>
<span class="n">someObject</span><span class="o">.</span><span class="n">should</span> <span class="n">be_fnordy</span>
<span class="k">end</span>
<span class="k">end</span>
</pre></div>
<p>Der Trick dabei ist das alles von <code>do</code> bis <code>end</code> jeweils ein Block ist der von der Methode describe oder it dann in eine UnitTest Klassenstruktur eingehängt wird um dann später als 'ganz normale' unit tests ausgeführt zu werden.</p>
<p>Jetzt wo Objective-C auch Blöcke unterstützt (ok, die können natürlich weniger als das Ruby Equivalent) müsste das eigenltich auch gehen - und siehe da mit <a href="http://github.com/pivotal/cedar">Cedar</a> gibt es auch schon einen ersten Versuch <a href="http://rspec.info/">RSpec</a> in Objective-C nachzubauen.</p>
<p>Well und daher habe ich mir mal angeschaut wie weit man denn kommt wenn man in Objective-C einen Block in eine Instanz-Methode umwandeln will.</p>
<p>Gleich vorneweg - das Typ-System von Objective-C macht mir hier einen kleinen Strich durch die Rechnung - ich habe es nicht geschafft einen Block nicht direkt als Funktions-pointer verwenden.</p>
<p>Aber mit etwas Umweg geht es doch.</p>
<p>Der Trick ist das Blöcke auch <code>id</code>'s sein können, d.h. man kann sie bequem in ein NSMutableDictionary packen.</p>
<p>Also brauche ich auf meiner Klasse nur ein Dictionary, speichere die Blöcke darin mit dem Namen der Methode ab und baue mir einen generischen Dispatcher-IMP der den Selector (zweites unsichtbares Argument jeder Objective-C Methode) verwendet um den Block aus aus dem Dictionary zu ziehen und führe ihn dann einfach aus.</p>
<p>[source:/open-source/adding-blocks-as-methods/trunk/AttachBlocksAsMethods.m So sieht dass dann aus]</p>
Die schönsten Testsuiten2010-05-29T00:00:00ZMartin Häckerurn:uuid:06c0043d-c478-36af-bb70-a116206f4b8c<p>Sowas wünsche ich mir auch mal für andere Programmiersprachen. Eine ständig aktuelle Hitliste der schönsten Testsuiten von Open Source software.</p>
<p><a href="http://blog.plataformatec.com.br/2010/04/best-ruby-open-source-test-suites-awards/">Sowas hier</a> - aber systematisch und crowdsourced immer aktuell.</p>
<p>Hach, man kann träumen. :-)</p>
Klarträumen2010-04-06T00:00:00ZMartin Häckerurn:uuid:e12fdf80-36f9-38ff-a202-aa4fa0158fe8<p><a href="http://de.wikipedia.org/wiki/Klartraum">Klarträumen</a> ist etwas das ich gerne lernen möchte und das mich derzeit beschäftigt. Erste Resultate habe ich schon - denn nach Jahren in denen ich mich vielleicht an einen Traum pro halbes Jahr erinnern konnte, erinnere ich mich jetzt an ein bis drei Träume pro nacht.</p>
<p>Stattlich. :-)</p>
<p>Sehr gut funktioniert für mich dass ich vor dem Schlafengehen via iPhone noch ein zwei YouTube Videos zu Klarträumen sehe um mich a) fortzubilden und b) mein Gehirn mit Klarträumen zu beschäftigen um die Warscheinlichkeit zu erhöhen dass ich mich an Träume erinnere (und später dass ich in einem Traum merke dass ich träume).</p>
<p>Eine super Einführung finde ich nach wie vor <a href="http://www.youtube.com/watch?v=e3GJTkG60X4">Reece Jones</a> <a href="http://www.youtube.com/watch?v=qK0hDfBvZh0">2</a>, <a href="http://www.youtube.com/watch?v=aZO3RSI7PnI">3</a>, aber auch andere Videos von ihm sind interessant (gleiten allerdings recht schnell in viel zu esoterische Gefilde ab für meinen Geschmack).</p>
<p>Abends (und morgens bevor ich noch einmal zum Träumen einschlafe) verwende ich momentan zur Beschäftigung mit meinem Träumen die Videos von <a href="http://www.youtube.com/user/lucidipedia">Lucidipedia</a> die zwar etwa länglich, dafür aber gut verständlich und sehr Detailreich gute Tips zum Träumen geben. Besonders gefallen mir daran die vielen Beispiele die er gibt und die Art wie er sie erklärt.</p>
<p>Noch ein paar Webseiten:</p>
<ul>
<li><a href="http://de.wikipedia.org/wiki/Klartraum">Wikipedia</a></li>
<li><a href="http://de.wikibooks.org/wiki/Klartraum">Wikibook</a></li>
<li><a href="http://www.lucidipedia.com/">Lucidipedia</a></li>
<li><a href="http://www.lucidity.com/">Lucidity Institute</a></li>
</ul>
<p>Aber auch eine einfache <a href="http://www.youtube.com/results?search_query=lucid+dreaming">YouTube</a> Suche bringt erstaunlich viele Ergebnisse.</p>
jQuery editInPlace2010-03-26T00:00:00ZMartin Häckerurn:uuid:5f46fb6b-2e21-3c20-9173-40e5d2678381<p>Well, I just finished some major reworking of that jQuery plugin, so now it has [browser:/open-source/jquery-edit-in-place/trunk/spec/unit/spec.js a real testsuite] and conforms to the <a href="http://docs.jquery.com/Plugins/Authoring">jQuery Plugin Guidelines</a> and doesn't pollute the core prototypes (of String) anymore.</p>
<p>There are a few new features, most prominent the ability to define a class to apply for the hover effect (so you can style the hover in css instead of having to hand in the colors directly and more control over the way errors are presented so it is easier to embed into bigger applications.</p>
<p>So enjoy <a href="http://jquery-in-place-editor.googlecode.com/svn/trunk/demo/index.html">the demo</a> and <a href="http://code.google.com/p/jquery-in-place-editor/downloads/list">the download</a> while they are hot, and keep a bookmark to <a href="http://code.google.com/p/jquery-in-place-editor/">the project homepage</a>. :)</p>
<p>Stuff I'd like to note:</p>
<ul>
<li><a href="http://visionmedia.github.com/jspec/">JSpec</a> rocks, writing tests with it is a breeze. The DOM Testrunner they have could use some work though to become even more usefull</li>
<li>Writing the tests with no dom insertion is a <em>great</em> technique to get a fast testsuite where you can almost guarantee that it has no test-ordering issues.</li>
<li>jQuery allows you to almost completely drive the interaction with the editor as a user would, making it almost like an acceptance test (and with very little dependency on the internal working of the editor.</li>
<li>Refactoring JavaScript Code is hard if you don't have a testsuite. My Advice: Break it down into smaller bits. I found it incredibly hard to refactor larger pieces of the code, as not having a testsuite means there's no way you know what still works. :/</li>
</ul>
Wo findet Innovation beim Lehren statt?2010-02-14T00:00:00ZMartin Häckerurn:uuid:7c8710a9-1c1b-3f35-9bf2-83949430e2fc<p>Früher mal dachte ich, dass das ja in den Universitäten sein muss. Schließlich ist da alles auf einem fleck. Forscher und Lehrer und Schüler.</p>
<p>Optimale Bedingungen eigentlich - nur dass dort an der Lehre überhaupt nicht geforscht wurde. Schließlich war das ja nur ein Anhängsel das Zeit kostet. Kein Forschungsgebiet.</p>
<p>In der Schule natürlich sowieso nicht und danach?</p>
<p>Im Beruf?</p>
<p>Ich bin natürlich mein eigenes Forschungssubjekt, weil ich weiter lerne und das beobachte. Und für mich selber ist es natürlich so dass ich ständig mit Innovationen habe, durch meine Möglichkeit das Netz zu verwenden.</p>
<p>Aber ab und an trifft man auf etwas großartiges. In einem <a href="http://itc.conversationsnetwork.org/shows/detail4386.html">Interview von John Udell</a> bin ich auf die <a href="http://khanacademy.org/">Khan Academy</a> gestoßen.</p>
<p>Das ist ein Mensch der seine Erfüllung darin findet dass er kurze Videos (~10 Minuten lang) aufnimmt in denen er eine Sache - ein Konzept aus Mathematik, Physik, Chemie, Finanzen und vielen weiteren Themen.</p>
<p>Und die sind gut!</p>
<p>Ausserdem hat er <a href="http://khanexercises.appspot.com/">eine Software online gestellt</a> die ein sehr spannendes Konzept verfolgt: Wissen ist dort als Graph aufgestellt - von einfachster Addition bis zu relativ komplexen Themen. (Aber viel weniger als als Video verfügbar ist).</p>
<p>Der Clou: Man fängt bei einfacher Addition an und kriegt die nächst-Schwierigeren Aufgaben erst wenn man 10 Aufgaben aus einem Wissensgebiet erfolgreich direkt hintereinander gelöst hat.</p>
<p>Dazu gibt es jeweils den ganzen Lösungsweg plus einen Link auf das dazugehörige Video wenn man es noch mal im Detail braucht.</p>
<p>Das führt dazu dass Kinder gerade bei Mathe ihre Lücken auffüllen können die sie irgendwo im Verständnis haben. Und das finde ich Großartig - denn das ist eines der größten Probleme von Großgruppen-Lernen. Wenn ein Thema vorbei ist, dann ist es vorbei - egal ob man es verstanden hat oder nicht.</p>
<p>Verdammt schade dass es noch soo lange dauern wird bis solche Konzepte auch in der "Offiziellen" Lehre angekommen sind.</p>
Gletscher Rückzug2010-02-08T00:00:00ZMartin Häckerurn:uuid:c6767358-8669-33cb-beb4-bd5c05b507b9<p>Klima-Veränderung ist ein schwer zugängliches Thema.</p>
<p>Aber auch Sau-Wichtig. Und daher finde ich es grandios was James Balog für eine Arbeit gemacht hat um den Gletscher-Rückzug zu dokumentieren. Mit knapp 30 Zeitraffer-Kammeras macht er über Jahre Hinweg jede Stunde ein Bild von vielen Gletschern und daraus dann einen Film.</p>
<p>Wow.</p>
<ul>
<li>Gibts bei <a href="http://www.ted.com/talks/james_balog_time_lapse_proof_of_extreme_ice_loss.html">TED als Video</a></li>
<li>Oder auf <a href="http://www.extremeicesurvey.org/">der Homepage des Projekts</a></li>
<li>Mein <a href="http://www.extremeicesurvey.org/index.php/new_gallery/timelapse_171/">Lieblingsvideo dort bisher</a></li>
</ul>
100 mal Floss Weekly2010-01-31T00:00:00ZMartin Häckerurn:uuid:62b43a9d-7182-3515-bde8-0a8e6269a187<p>:) Einer meiner Lieblingspodcasts hat es jetzt auf die 100. Ausgabe gebracht.</p>
<p>Und da muss ich doch mal gratulieren. Vor allem weil ich bei der Quiz-Show über Programmiersprachen und deren Verbreitung absolut herzhaft gelacht habe. :-)</p>
<p>Hörenswert! Immer wieder großartige Interviews mit Machern von Open Source Projekten.</p>
<p>[Hier gehts zur 100-sten Show <a href="http://twit.tv/floss100">http://twit.tv/floss100</a>]</p>
Softwareentwicklung als Kooperatives Spiel2010-01-28T00:00:00ZMartin Häckerurn:uuid:ee76d24c-6c22-3f63-86cd-5969a4cd286d<p>Das ist ein steinalter <a href="http://alistair.cockburn.us/Software+development+as+a+cooperative+game">Vortrag von Alistair Cockburn</a> (gesprochen Co-Burn) in dem er darlegt wieso er findet das das eine sehr gute Sichtweise auf Softwareprojekte ist.</p>
<p>Der Vortrag ist schon 10 Jahre alt - und trotzdem finde ich ihn sehr Aktuell.</p>
<p>Lesenswert!</p>
Python Saug Punkte contd.: x += y ist nicht x = x + y2010-01-15T00:00:00ZMartin Häckerurn:uuid:f1e549a2-ef5a-3f55-a04b-200a4d4e654c<div class="hll"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="n">b</span> <span class="o">=</span> <span class="nb">list</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="p">[</span><span class="s1">'foo'</span><span class="p">]</span>
<span class="nb">print</span> <span class="n">b</span> <span class="c1"># => []</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">b</span> <span class="o">=</span> <span class="nb">list</span><span class="p">()</span>
<span class="n">a</span> <span class="o">+=</span> <span class="p">[</span><span class="s1">'foo'</span><span class="p">]</span>
<span class="nb">print</span> <span class="n">b</span> <span class="c1"># => ['foo']</span>
</pre></div>
<p>Doh. Wie kann das sein? Kommt man von C ist das erst mal sehr verblüffend - und auch die meisten anderen Programmiersprachen die ich kenne verwenden <code>a += b</code> als equivalent für <code>a = a + b</code>.</p>
<p>Well, nicht so Python. Weil <a href="http://www.python.org/dev/peps/pep-0203/">da gab es offenbar mal Programmierer</a> die fanden dass man Code der mit Matrizen rechnet lieber mit Operatoren schreiben möchte weil sich das besser ließt. Natürlich nicht mit den normalen operatoren wie */+-, weil, da kann man ja den empfänger nicht in place modifizieren, und wie jeder weiß sind Matrizen ja so groß dass die dann nicht mehr in den Ram passen.</p>
<p>Also haben sie die <op>= operatoren in Python so spezifiziert, dass sie ihre left-hand-variable in place modifizieren wenn diese mutable sind.</p>
<p>:-(</p>
Python Saugpunkte: Klassenobjekte2010-01-13T00:00:00ZMartin Häckerurn:uuid:f28147d0-1623-3ddf-88c2-44440ed73e7a<p>Klassenobjekte sind special - daher hat man im boddy einer klasse keinen Zugriff auf das klassenobjekt.</p>
<p>Weil, self ist ja auch nicht automatisch und man muss es in Methoden immer als explizites Argument hinschreiben, und so etwas gibt es ja bei Klassen nicht, denn das sind ja keine Methoden und daher kann man halt das Klassenobjekt nicht referenzieren im body.</p>
<p>Doh.</p>
<p>Und das nervt natürlich total bei der meta-programmierung.</p>
<p>Hier mal ein Beispiel von etwas SQL-Alchemy Code wo mir das wieder aufgefallen ist:</p>
<div class="hll"><pre><span></span><span class="k">class</span> <span class="nc">Poll</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="n">proposal</span> <span class="o">=</span> <span class="n">relation</span><span class="p">(</span><span class="n">proposal</span><span class="o">.</span><span class="n">Proposal</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="n">backref</span><span class="p">(</span><span class="s1">'polls'</span><span class="p">,</span> <span class="n">cascade</span><span class="o">=</span><span class="s1">'all'</span><span class="p">,</span>
<span class="n">lazy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">order_by</span><span class="o">=</span><span class="n">Poll</span><span class="o">.</span><span class="n">begin_time</span><span class="o">.</span><span class="n">desc</span><span class="p">()))</span>
</pre></div>
<p>Das geht nicht, weil ich auf Poll nicht zugreifen kann und damit nicht auf andere attribute der Klasse. Der Workaround den SQLAlchemy dafür macht ist das man einen String hineinreicht und die den dann aufwendig parsen. Total gar nicht toll.</p>
<p>:-(</p>
Grand Unified Theory of Programming?2010-01-13T00:00:00ZMartin Häckerurn:uuid:e4d4a914-89d5-3169-abac-1cfb36c66a65<p>Das höchste Ziel in der Physik ist alle Kräfte durch eine Formel auszudrücken bzw. sie in Beziehung zueinander zu setzen. Maxwell zum Beispiel gelang das für elektrische und magnetische Felder - und dafür ist er noch heute berühmt.</p>
<p>In der Software-Entwicklung gibt es so etwas bisher nicht. Klar, es gibt Daumenregeln, so wie:</p>
<ul>
<li>Keep it <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a></li>
<li><a href="http://stephane.ducasse.free.fr/FreeBooks/BestSmalltalkPractices/Draft-Smalltalk%20Best%20Practice%20Patterns%20Kent%20Beck.pdf">Keep your Methods Small</a> **</li>
<li>Work <a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod">SOLID</a></li>
<li>Obay the <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a></li>
<li>und so weiter…</li>
</ul>
<p>Aber, und das ist der wichtige Teil: diese Daumenregeln sind keine Unifikation die die verschiedenen Probleme beim Programmieren abwägen und in Beziehung setzen.</p>
<p>Daher finde ich <a href="http://onestepback.org/">Jim Weirichs</a> Vortrag <a href="http://mwrc2009.confreaks.com/14-mar-2009-18-10-the-building-blocks-of-modularity-jim-weirich.html">The Building Blocks of Modularity</a> sehr spannend - denn da stellt er den Ansatz der <a href="http://www.slideshare.net/LittleBIGRuby/the-building-blocks-of-modularity">Connascence</a> vor (ab Folie 35).</p>
<p>Das ist letztlich eine Klassifizierung welche Art von Abhängigkeit man sich durch welche Programmiertechnik einfängt - und damit kann man 'normales' Refactoring anwenden um von problematischeren Connascence's (?) zu weniger problematischen zu kommen.</p>
<p>Ach ja, ursprünglich kommt das aus dem Buch <a href="http://books.google.com/books?id=089qQgAACAAJ">What every Programmer should know about Object Oriented Design</a>. Davon kann man aber Getrost nur noch den dritten Teil lesen (über Connascence) - der rest ist nach 15 Jahren einfach veraltet. :)</p>
<p>** Niemand sagt das so gut wie Kent Beck: "Lots of little pieces - Good code invariably has small methods and small objects. Only by factoring the system into many small pieces of state and function can you hope to satisfy the “once and only once” rule. I get lots of resistance to this idea, especially from experienced developers, but no one thing I do to systems provides as much help as breaking it into more pieces."</p>
Python Saug Punkte contd.2010-01-11T00:00:00ZMartin Häckerurn:uuid:8c310be9-8b20-3b57-a73b-306886d1f487<p>Eine Sache die mich bei Python immer wieder ärgert ist die Tatsache dass Standardwerte für Methodenargumente zur Parsezeit festgelegt werden anstatt zur Aufrufzeit.</p>
<p>Das ist total doof, denn dadurch teilen sich alle aufrufe der Funktion den gleichen default-wert - was zwar schön schnell sein mag, aber trotzdem in fast allen Fällen nur bei nicht veränderbaren Objekten (so wie Integer und Strings) Sinn ergibt.</p>
<p>So führt das dazu dass man in Python eine ganze Menge Workarounds braucht um mit default-argumenten zu arbeiten.</p>
<p>Das wichtigste dabei ist der default typ None. Das ist der workaround für alle mutable-objekte, da man die in fast keinem Fall zwischen verschiedenen Methodenaufrufen teilen möchte. So sieht das aus:</p>
<div class="hll"><pre><span></span><span class="k">def</span> <span class="nf">end_poll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">end_time</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">end_time</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">end_time</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">utcnow</span><span class="p">()</span>
<span class="c1"># work with end_time...</span>
</pre></div>
<p>Der Punkt hier ist dass man datetime.utcnow() nicht in das standard Argument hineinschreiben kann, da man sonst bei jedem Aufruf der Methode den gleichen Wert hätte: Die Parsezeit. Nicht sonderlich nützlich.</p>
<p>Das hat zur Folge dass man:</p>
<ul>
<li>aus der Signatur nicht sehen was das Standardargument ist (utc/gmt oder vielleicht ewas ganz anderes?). Immerhin gibt es inzwischen immer mehr IDEs die diese Signatur beim aufrufen für autocompletion nutzen oder sie wenigstens anzeigen können.</li>
<li>Man beim verwenden von Standardargumenten immer überlegen muss ob man dieses Argument jetzt in die Methodendefinition oder in den Body aufnehmen muss.</li>
<li>für jedes Standardargument noch mal zwei extra Zeilen braucht. Das nervt vor allem deswegen weil man sich mit den standard Argumenten ja Zeilen sparen möchte. Das heißt die Kosten für Standard-Argumente steigen und man benutzt sie seltener.</li>
<li>die default argumente noch mal separat dokumentieren muss, da ein dokumentations-extraktions-Werkzeug ja den Code nicht sieht, der das tatsächliche Standardargument setzt. Und natürlich hat man dann noch mal DRY verletzt da die Information jetzt zwei mal da steht.</li>
<li>richtig fiese Bugs kriegt, weil viele Leute diese Probleme nicht kennen oder sie ab und an vergessen und mal ein <code>list()</code>, <code>dict()</code> oder <code>set()</code> als Standardwert nehmen was dan für viel Freude beim Debuggen sorgt.</li>
</ul>
<p>Also, know your Python und vorsicht mit Standardargumenten!</p>
<p>Vielleicht kriegen wir ja irgendwann von unserem BDFL ein <code>from __future__ import runtime_standard_argument_evaluation</code>.</p>
SOLID object oriented design2010-01-10T00:00:00ZMartin Häckerurn:uuid:e4559082-d3eb-3117-87de-3d84d54ead54<p>Ein Vortrag von der <a href="http://goruco2009.confreaks.com/30-may-2009-15-40-solid-object-oriented-design-sandi-metz.html">GORUCO</a> - sehr zu empfehlen.</p>
<p>Besonders gefallen hat mir ihr Fazit dass man mehr als nur <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> als Prinzip beim Refactoring anwenden soll um bei gutem Code anzukommen.</p>
<p>Sandy Metz empfiehlt das man sich an den 'Grünen' Stellen des Red/Green/Refactor Zyklus für jedes Objekt diese Fragen stellt:</p>
<ul>
<li>Is it DRY?</li>
<li>Does it have one responsibility?</li>
<li>Does everything in it change at the same time?</li>
<li>Does it depend (only) on things that change less often than it does?</li>
</ul>
<p>Und bringt das auch an einem ordentlichen Beispiel auf den Punkt.</p>
<p>Alles in allem: Ein Vortrag der zum Nachdenken über den eigenen Code-Stil einlädt. Empfehlenswert!</p>
Method argument naming confusion2010-01-08T00:00:00ZMartin Häckerurn:uuid:e6dbe7a1-d18f-3f7d-beb9-2bd61ec1369a<p>Schon seit einigen Wochen bin ich am grübeln, nach welcher Regel ich in Python meine variablen für Methoden-Argumente benennen soll. Das ist erstaunlicherweise gar nicht so klar.</p>
<p>Hier mal das Problem: In Objective-C ist alles sehr klar und einfach (von Smalltalk kommend). Jede Methoden-Deklaration besteht abwechselnd aus einem Teil Methodennamen und dann einer Variablen. Hier mal ein Beispiel:</p>
<div class="hll"><pre><span></span><span class="p">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="nf">setValue:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">aValue</span><span class="w"> </span><span class="nf">forKey:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">aKey</span><span class="w"></span>
</pre></div>
<p>Das hat den großen Vorteil dass man den Methodennamen benutzen kann um Stück für Stück die Argumente zu dokumentieren. Verwendet wird das so, dass das Stück Methodennamen das vor einem Argument kommt die Rolle beschreibt die das Argument spielen wird, während der Name der Variablen eher generisch ist und sich eher am Typ orientiert. Dazu kommt natürlich das man die Typen auch explizit auszeichnen kann, was die notwendigkeit für die Typ-Annotation im Namen der Variablen im vergleich zu Smalltalk oder Python noch mal vermindert und man kann ihn ganz der Rolle hingeben die die Variable in der Methode spielen wird - versehen mit dem a/an/some/etc. prefix der Argumente (als generische Instanzen von etwas) von den lokalen und instanz-variablen unterscheidet.</p>
<p>In Python geht das so nicht. Man kann versuchen das auf zwei wegen anzunähern:</p>
<div class="hll"><pre><span></span><span class="k">def</span> <span class="nf">set_value_for_key</span><span class="p">(</span><span class="n">a_value</span><span class="p">,</span> <span class="n">a_key</span><span class="p">):</span> <span class="k">pass</span>
<span class="c1"># benutze als: some_dict.set_value_for_key('value', 'key')</span>
</pre></div>
<p>Das hat den Vorteil das man die Argumente mehr oder weniger benennen kann wie man möchte, aber den Nachteil das die Dokumentation der argumente nicht mit diesen zusammen ist. Das hat schon mal den unangenehmen seiteneffekt das es sehr viel schlechter auf mehrere Argumente skaliert und damit sehr fix mehr extra-dokumentation nötig macht.</p>
<p>Der andere Weg wäre so:</p>
<div class="hll"><pre><span></span><span class="k">def</span> <span class="nf">set</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">for_key</span><span class="p">):</span> <span class="k">pass</span>
<span class="c1">#benutze als: some_dict.set(value='value', for_key='key')</span>
</pre></div>
<p>Das hat den Vorteil dass der MethodenNamen von der Dokumentationshürde befreit ist - und damit Kurz wird. Auf der anderen Seite sind die Argument-Namen jetzt effektiv teil des Methoden-Namens und damit kann man sie nicht mehr so gut benutzen um den Typ der Argumente zu dokumentieren.</p>
<p>:-(</p>
<p>Das ist der Grund wieso ich die Objective-C / Smalltalk Syntax so gerne mag, weil es darin so einfach ist selbstdokumentierenden Code von hoher qualität zu schreiben.</p>
Here be electric dragons2010-01-08T00:00:00ZMartin Häckerurn:uuid:235d7d10-6598-3d18-9e90-12da2a1db8a6<p>Ich vertrete ja schon länger den Punkt dass ein Grundeinkommen eine Notwendigkeit sein wird in einer Gesellschaft in der Maschinen uns alle physischen Arbeiten abnehmen können.</p>
<p>Well, jetzt habe ich endlich jemanden gefunden der dieses Argument auch vertritt.</p>
<p>Auf dem 26C3 im Vortrag <a href="http://events.ccc.de/congress/2009/Fahrplan/events/3452.en.html">Here be electric dragons</a></p>
<p>Sehr sehenswert!</p>
Python Saug-Punkte2009-12-23T00:00:00ZMartin Häckerurn:uuid:6d74eccf-34e1-327e-8a6c-ab82a7abc2ac<p>Viele standard-funktionen und module in python haben zu kurze namen.</p>
<p>Das ist deshalb ein Problem weil, man diese Namen nicht für lokale Variablen verwenden kann bzw. ungewollt eine Standardfunktion überschreibt.</p>
<p><code>id</code> zum Beispiel. Oder <code>dict</code>, <code>list</code>.</p>
<p>Module sind dabei aber auch Problemkandidaten - vor allem wenn man sie häufig wie ein Objekt benutzt. Das <code>json</code> Modul macht mir immer wieder probleme, weil ich eine lokale Variable die json enthält nun mal gerne json nennen würde. <code>json_serialization</code> wäre vielleicht ein besserer Name für das Modul.</p>
<p>Die Standard-Bibliothek ist leider voll von solchen Beispielen und der Include-Mechanismus von Python der die Module quasi als Objekt im namespace des Empfängers verfügbar macht hilft da nicht wirklich weiter. Das ist zwar IMO eine bessere Idee als der C-Präprozessor <code>#include</code> (was Ruby ja zum Beispiel nachbaut) aber gerade bei so kurzen Namen kann das wirklich nerven.</p>
<p>Wenn man aus einem Modul ein Objekt importiert ist das interessanterweise kein Problem, da Objekte in Python (wenn sie sich an die Namenskonvention halten - leider auch oft nicht der Fall in der Standardbibliothek) immer mit einem Großbuchstaben anfangen und dadurch diese Namenskollision nicht auftritt.</p>
<p>Für mich ist da das Problem dass die Python Programmierer leider so eine Obsession damit haben alles möglichst kurz machen zu wollen - und dabei aber dem Programmierer der mit der (Standard-) Bibliothek arbeiten möchte gerade wieder Steine in den Weg legen dass kurz zu machen was für Ihn am meisten sinn macht - lokale Variablen.</p>
<p>Das ist leider Premature Optimisation in Reinstkultur - und es stört mich beim Entwickeln von meiner Software. :-(</p>
How to crash IE 7 with javascript2009-12-12T00:00:00ZMartin Häckerurn:uuid:a3263997-f085-3c84-963b-7fc2f4d6c504<p>Well, it's all too easy apparently. We stumbled upon the problem when suddenly our web application crashed left and right on us in IE 7.</p>
<p>I've since reduced the code involved and created a plugin to jQuery to make it easier to reproduce this.</p>
<p>Well, maybe perhaps sometimes somebody even discovers a use for the crashIE7 jQuery plugin. :)</p>
<p>In any event - it was fun creating this. :)</p>
<p>See the blog post page for the attached source and how to use this.</p>
Python distributions2009-12-05T00:00:00ZMartin Häckerurn:uuid:b33347bd-070d-3ac4-9f03-c53cc93b8e8e<p>Endlich mal hab ich einen überblick gefunden wo die Entwicklung momentan hingeht.</p>
<p><a href="http://mail.python.org/pipermail/python-dev/2009-October/092754.html">http://mail.python.org/pipermail/python-dev/2009-October/092754.html</a></p>
<p>Kurz zusammengefasst:</p>
<ul>
<li>easy_install, ez_setup und Konsorten wird sterben. <a href="http://packages.python.org/distribute/">distribute</a> ist die Zukunft</li>
<li>easy_install wird sterben -> <a href="http://pip.openplans.org/">pip</a> ist die Zukunft</li>
<li>Metadata wird aus dem setup.py script herauswandern und stattdessen in einem ini file zur Verfügung gestellt (Da ist mir noch nicht ganz klar wie das funktionieren soll - aber gut).</li>
<li>Deinstallieren wird auch mit den distutils gehen - man braucht also nicht mehr pip um das zu machen</li>
</ul>
<p>Und noch mehr. Aber das find ich schon mal am wichtigsten. :)</p>
Flagge zeigen2009-11-29T00:00:00ZMartin Häckerurn:uuid:d430ecd8-0ea6-3884-a763-e7e0458f184e<p><img src="http://wurstball.de/static/ircview/pictures/ba57e733f5f0157a130c99f7e648cb58.jpg" alt="Image"></p>
<p><a href="http://wurstball.de/25017/">via</a></p>
Zur Schweinegrippe2009-11-18T00:00:00ZMartin Häckerurn:uuid:55ab626a-3160-3938-9114-38034679fcce<p>Meine Mutter hat diesen lesenswerten Text dazu geschrieben - und den möchte ich gerne (mit ihrer Erlaubnis) noch mehr Leuten zugänglich machen. Grund dafür ist diese Email die gerade mit diversen gut klingenden Arzt-Namen als Absender auch durch meine Inbox wandert</p>
<hr>
<p>Für alle, die überlegen sich impfen zu lassen :</p>
<p>Die beiden Impfstoffe gegen die so genannte Schweinegrippe <em>Pandemrix® Und Focetria®,</em> enthalten als Adjuvans (Impfverstärker ) <em>Squalen</em>. Beim Menschen ist Squalen bei den US-Soldaten des ersten Golfkriegs als Impfverstärker eingesetzt worden.</p>
<p>23-27% (also jeder Vierte, auch solche, die zu Hause blieben) bekamen Die Golfkriegskrankheit, Mit chronischer Müdigkeit, Fibromyalgie (Muskelrheuma), neben Gedächtnis-und Konzentrationsproblemen, persistierenden Kopfschmerzen, Erschöpfung und ausgedehnten Schmerzen charakterisiert. Die Krankheit Kann auch chronische Verdauungsprobleme und Hautausschlag einschließen.</p>
<p>Die Erkrankung hat sich seit 1991 also seit 18 Jahren nicht gebessert. Bei 95 % der Geimpften mit Golfkriegssyndrom wurden Squalen-Antikörper Gefunden.</p>
<p>Erst nach mehr als 10 Jahren wurden die Schäden vom US-Verteidigungsministerium anerkannt.</p>
<p>Wenn die Bundesregierung ihren Willen durchsetzt und 35 Millionen Menschen geimpft werden, ist damit zu rechnen, dass 8-9 Millionen Bundesbürger für die nächsten Jahrzehnte unter chronischer Müdigkeit und Fibromyalgie etc. leiden werden.</p>
<p>Unterschrieben von:</p>
<h2>$GUT_KLINGENDER_ARZT_NAME</h2>
<p>Dazu hat sie diese gute Antwort geschrieben:</p>
<p>Ja, es stimmt.
Pandemrix + Focetria enthalten Squalen, das injiziert zum Imunogen wird. Das
ist seine wirkstoffverstärkende Ebene. Es wird auch in unserer Leber
produziert, aber liegt natürlicherweise in öliger Form vor. Im Impfstoff
aber als Emulsion, was einen Unterschied für die Verstoffwechselung im
Körper macht. Der Verdacht, dass es etwas mit dem Golfkriegsyndrom zu tun
hat, ist nicht erhärtet. Neuere Studien mit größeren Teilnehmergruppen
zeigen keinen Zusammenhang zwischen Squalen-Antikörpern und chron.
Symptomen.- Dennoch wird unabhängig von diesem Aspekt der Debatte um diese
Impfstoffe ihre Sicherheit als ungenügend geprüft eingeschätzt. Er wird
schlechter vertragen als ein Spaltimpfstoff ohne Wirkverstärker. Das ist
sicher. ER wurde noch nicht an Schwangeren und Kindern erprobt und die jetzt
eingesetzte Wirkstoffverstärkerdosis ist viel höher als in bisher
eingesetzten Impfungen. Nebenwirkungen wurden noch nicht systematisch
erfaßt. Auch seine Wirksamkeit ist noch nicht hinreichend erforscht, da eine
verringerte Dosierung gegenüber der Zulassungsphase jetzt vermarktet wird.</p>
<p>Da die Grippe gutartig abläuft und kein höheres Risiko darstellt, als die
bisherigen Herbstgrippen, ist davon bei sonst gesunden Menschen abzuraten,
ebenso bei Schwangeren und Kindern. Hier herum impfen nur wenige Ärzte und
auch die Kinderärzte sind sehr zurückhaltend.
Jürgen hat herausgefunden, dass 1974 dieser Virus schon mal "um die Welt
lief", so dass alle, die damals schon sich anstecken konnten, wahrscheinlich
immun sind.</p>
<p>Mein Rat an alle, die sich schützen wollen und dazu beitragen möchten, das
sich die Viren nicht ausbreiten:</p>
<ol>
<li>Bei ersten Symptomen ca 25 mg Zink einnehmen (gibt es als Tabletten) an zwei aufeinanderfolgenden Tagen. Parallel dazu Vitamin C Stoß mit heißer Zitrone o.ä. 2x täglich.</li>
<li>Cystus 052 Infektblocker Tabl. lutschen (pflanzlicher Virenblocker).</li>
<li>Wenn Fieber kommt, dieses auf über 39°C steigen lassen und abwarten. Viren werden durch Temperaturen über 39°C abgetötet. Es ist der effektivste Abwehrmechanismus. Die Nebenwirkungen des Fieberanstiegs ertragen sich am besten im Bett mit viel trinken und schlafen. Sobald die Viren keine Bedrohung mehr darstellen, geht das Fieber wieder runter (bei normalem Verlauf).</li>
<li>Auch ohne Fieber soll sich jeder im Stadium des Niesen und Hustens von seinen Mitmenschen fernhalten, da er wie eine lebende Viren-Schleuder wirkt. Am besten freiwillig daheim bleiben und viel Zeit auf Pflege der Gesundheit verwenden (Nasenspülung, Inhalieren, Tee trinken, ausruhen, an die frische Luft gehen wenn möglich, Basenbäder nehmen, bei Bedarf Brustwickel, Atemübungen, viel frisches Obst).</li>
</ol>
<hr>
<p>Ich hoffe dass das auch für viele anderen Leute einiges an Fragen beantwortet und die Pharmaindustrie hoffentlich deutlich einnahmen kostet.</p>
Das Wikipedia Dilemma Lösen2009-11-14T00:00:00ZMartin Häckerurn:uuid:772f70ea-6afd-3c3d-beb9-e1bc0aaaeac0<p>Ich weiß ich bin etwas spät mich dazu auch zu äussern - aber jetzt wo die <a href="https://secure.wikimedia.de/spenden/list.php?datum=2009-11">Wikipedia wieder zu Spenden aufruft</a> möchte ich was dazu sagen wieso ich nicht spende.</p>
<p>Das ist doch alles Kindergarten was in der Wikipedia gerade läuft.</p>
<p>Also gut, "embrace your enemy" oder wie es heißt, da können wir etwas tun.</p>
<p>Lasst uns einen Kindergarten eröffnen. Jeder neue Wikipedia-Artikel ist zuerst im Kindergarten und wenn er Groß und Stark geworden ist kann er irgendwann ins Erwachsenen-Artikel-Leben übertreten.</p>
<p>Das hätte folgenden Vorteil: Alle Exkludisten und die die nur die beste Qualität haben wollen legen einen Schalter um und sehen diese Einträge erst mal nicht.</p>
<p>Alle anderen verlieren nicht sofort die Lust an der Mitarbeit wenn einer Ihrer Artikel gelöscht wurde - weil er nicht gelöscht wurde.</p>
<p>Wenn jemand auf eine Seite kommt die unterhalb seines Qualitätslevels liegt, kann er ja einen Hinweis kriegen dass sie existiert, damit er sie mit einem Klick zu sehen bekommt bzw. er seine Einstellung ändern kann.</p>
<p>Alle sind Glücklich!</p>
<ul>
<li>Jeder Artikel kann jederzeit in den Kindergarten geschickt werden bis er groß wird.</li>
<li>Jeder Artikel kann jederzeit aus dem Kindergarten "graduieren"</li>
<li>Wer nur Inhalte von größtmöglicher geprüfter Qualität sehen möchte kann diese ausschließen</li>
<li>Alle Anderen kriegen einen deutlichen Hinweis dass der Artikel noch im "Kindergarten" ist</li>
<li>Man könnte Kindergarten Artikel generell anders Rendern damit der Unterschied ganz klar ist</li>
</ul>
<p>Ich persönlich würde es vorziehen wenn die Standardeinstellung "Alles anzeigen" ist - aber auch wenn der Standard wäre "nur die geprüften Artikel anzeigen" und man jederzeit sieht wenn man an einer Stelle ist die im Kindergarten noch mehr Inhalt enthällt und man die nach bedarf zeigen kann wäre ich zufrieden.</p>
<p>Platz ist in der Wikipedia ja kein Problem - nur von Admins und regelmäßigen Mitarbeitern gepflegter Platz ist knapp.</p>
<p>Was ich will, ist das die User entscheiden können was sie lieber wollen. Mehr Artikel, oder besser geflegte - und nicht die die die meiste Zeit in das Projekt stecken. Das halte ich für absolut wichtig.</p>
<p>Ach ja, und falls das innerhalb der Wikipedia nicht funktioniert, müsste man so etwas als eigene Applikation davor setzen wikinursery.de / kindergarten.wikipedia.de oder per greasemonkey oder als iPhone App oder eben als "vollständige Wikipedia" irgendwo anders.</p>
<p>Nur innerhalb der Wikipedia wäre natürlich am besten - wobei zweifelhaft ist ob die macher des Projekts dafür bereit sind.</p>
<p>Ja, die Idee wurde schon von ein paar anderen Leuten geäussert - ich wollte sie auch noch einmal aufschreiben weil ich sie so wichtig finde.</p>
Hamam2009-11-08T00:00:00ZMartin Häckerurn:uuid:21c540c1-9763-32d6-8233-52a7fda65bdc<p><a href="http://www.sultan-hamam.de">Ahhhhhhhhhh</a></p>
Wie viel kostet die Finanzkriese?2009-11-05T00:00:00ZMartin Häckerurn:uuid:5a026e3e-4b02-34ba-b13e-4242e52f2949<p>Im vergleich zum Irak-Krieg? Oder alle Kinder dieser Welt für 5 Jahre zu ernähren?</p>
<p><a href="http://www.informationisbeautiful.net/visualizations/the-billion-dollar-gram/">Hier wunderschön visualisiert</a>.</p>
<p>So viel ist klar - man sieht was wichtig ist im Staat und was nicht. Leider.</p>
<p><a href="http://blog.fefe.de/?ts=b40c8b76">via</a></p>
Wieso Blöcke keine echten Funktionen sein sollten2009-11-04T00:00:00ZMartin Häckerurn:uuid:0ec2bd45-8122-34f5-ac79-cee9e791ace4<p>Zu <a href="http://www.youtube.com/watch?v=hJRV50_tJ0E">"Ergie" von Rainer von Vielen</a></p>
<p>In meiner Freizeit beschäftige ich mich gerade viel mit Ruby - sowohl <a href="http://www.amazon.com/Ruby-Way-Second-Techniques-Programming/dp/0672328844">The Ruby Way</a>, als auch <a href="http://oreilly.com/catalog/9780596516178">The Ruby Programming Language</a> sind dafür gute Bücher.</p>
<p>Und ich muss sagen, das Ruby ist nicht unspannend. Zwar gibt es auch einiges dass ich ganz schön eklig finde (z.B. das Flip-Flop Statement, oder dass so viel mit globalen Variablen gearbeitet wird, oder dass viele Sachen so komplex sind.</p>
<p>Aber darum gehts hier gar nicht. Mir geht es hier um die Erkenntnis wieso und unter welchen umständen man Blöcke als etwas anderes sehen möchte als anonyme Funktionen.</p>
<p>Das dauert nämlich bis man das merkt.</p>
<p>Zuerst einmal die Konfusion: Ruby hat eine Syntax für Methoden</p>
<div class="hll"><pre><span></span><span class="k">def</span> <span class="nf">method</span><span class="p">(</span><span class="n">positional_argument</span><span class="p">,</span> <span class="o">*</span><span class="n">all_other_arguments</span><span class="p">)</span>
<span class="c1"># some body</span>
<span class="k">end</span>
</pre></div>
<p>und eine für Blöcke</p>
<div class="hll"><pre><span></span><span class="mi">10</span><span class="o">.</span><span class="n">times</span> <span class="k">do</span> <span class="o">|</span><span class="n">positonal_argument</span><span class="p">,</span> <span class="o">*</span><span class="n">all_other_arguments</span><span class="o">|</span>
<span class="c1"># some body</span>
<span class="k">end</span>
</pre></div>
<p>Wieso der Unterschied? Wieso macht man Blöcke nicht einfach zu normalen Funktionen die man dann auch gleich mit <code>()</code> aufrufen kann anstatt immer ein <code>a_block.call()</code> verwenden zu müssen?</p>
<p>Echte Lambdas gibt es ja noch zusätzlich in Ruby.</p>
<p>Well, den Unterschied in der Syntax verstehe ich immer noch nicht. Aber dahinter steht der Grund dass Blöcke eine andere Aufgabe haben als Methoden - der Punkt ist nämlich dass man sie gerne als Teil der sie lexikalisch umgebenden Methode betrachten möchte damit man sie nutzen kann um mit ihnen Kontrollstrukturen zu implementieren. Hier mal ein Beispiel:</p>
<div class="hll"><pre><span></span><span class="k">def</span> <span class="nf">find</span><span class="p">(</span><span class="n">needle</span><span class="p">,</span> <span class="n">haystack</span><span class="p">)</span>
<span class="n">haystack</span><span class="o">.</span><span class="n">each</span><span class="o">.</span><span class="n">with_index</span> <span class="k">do</span> <span class="o">|</span><span class="n">index</span><span class="p">,</span> <span class="n">element</span><span class="o">|</span>
<span class="k">if</span> <span class="n">element</span> <span class="o">==</span> <span class="n">needle</span>
<span class="k">return</span> <span class="n">index</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">return</span> <span class="kp">nil</span>
<span class="k">end</span>
</pre></div>
<p>(Also als Python Programmierer muss ich ja sagen dass die <code>end</code> statements ganz schön auf die Nerven gehen. Doppelte Zeilenanzahl für null zusätzliche Information oder Nützlichkeit. But I digress.)</p>
<p>Das spannende daran ist die Zeile <code>return index</code>. Seht ihr was daran besonders ist? Ich Puzzle es mal auseinander als wäre der Block eine funktion, dann wird es klar.</p>
<p>find ruft einen iterator auf dem haystack auf, d.h. übergibt ihm eine Funktion die das richtige Element findet. Diese Funktion erhällt ein Element aus dem haystack und einen index und gibt diesen index zurück wenn das element das gesuchte ist.</p>
<p>Und da ist das Problem: Damit <code>find</code> funktioniert muss <code>return index</code> find verlassen und nicht nur die iterator-funktion.</p>
<p>Das ist der Grund wieso man Blöcke als etwas anderes als Funktionen/Methoden betrachten muss wenn man sie nutzen will um damit Kontrollstrukturen implementieren zu können und ihre volle Nützlichkeit für Abstraktionen verwenden zu können.</p>
Worin liegt der Erfolg von "Ruby on Rails"2009-10-24T00:00:00ZMartin Häckerurn:uuid:600eaddc-4ddf-34f1-b665-0c31af549d94<p>Liegt es vielleicht wie <a href="http://stackoverflow.com/questions/1099305/why-is-ruby-more-suitable-for-rails-than-python/1099367#1099367">auf Stackoverflow angekündigt</a> an der Sprache?</p>
<p>Jedenfalls fand ich den ersten Kommentar hervorragend.</p>
<pre><code>"Python on Pails" just doesn't have the same feel to it... – ephemient
@Ephemient: I believe it would be Python on Planes. – Jimmy
@Jimmy: Who needs planes? import antigravity ;-) xkcd.com/353 – Vinay Sajip
Is there a Java in Jails? – Nosredna
</code></pre>
<p><em>lol</em> Eindeutig, die Sprache ist schuld.</p>
Playing with JavaScript variable lookup2009-10-17T00:00:00ZMartin Häckerurn:uuid:dae45399-5c6c-3597-8bbc-dad6d505eb12<p>I am always amazed at the very nice features of JavaScript on the one hand and the very, very bad features of it on the other side.</p>
<p>Here's something I learned the other week that I find quite interesting: <code>eval</code> vs. <code>new Function</code>. Here's what I wanted to achieve: I was looking for a way to do some meta-programming with JavaScrip, specifically prevent the problem that any variable you assign to but don't declare ends up as a member of the global object.</p>
<p>The problem is that name lookup in JavaScript is quite peculiar. First it consults the current function activation for local variables and then it goes straight back to the <code>window</code> object and just prepends all it's contents to the local namespace.</p>
<p>Doh. This has the very bad consequence that every variable you forget to declare via the <code>var someVariableName</code> syntax becomes part of the global object - and therefore itself global.</p>
<p>Now you can change this lookup by inserting some of your objects in this lookup chain by using the <a href="http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/">somewhat controversial</a> <code>with</code> statement like so:</p>
<div class="hll"><pre><span></span><span class="kd">var</span> <span class="nx">namespace</span> <span class="o">=</span> <span class="p">{</span><span class="nx">foo</span><span class="o">:</span><span class="s1">'bar'</span><span class="p">};</span>
<span class="kd">with</span> <span class="p">(</span><span class="nx">namespace</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// this scope now has a local variable foo with the value bar</span>
<span class="p">}</span>
</pre></div>
<p>This is considered a bad feature, as it means that if you assign to <code>foo</code> that will assign a new value to <code>namespace</code> but if you assign to something else or mistype, that will still end up on the global object. Not very nice - and therefore most JavaScript programmers don't use <code>with</code> ever.</p>
<p>Still with some working and eval it can be used to re-map free functions transparently, so that you can do something like this:</p>
<div class="hll"><pre><span></span><span class="kd">var</span> <span class="nx">namespace</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">equals</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">actual</span><span class="p">,</span> <span class="nx">expected</span><span class="p">){</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">actual</span> <span class="o">!==</span> <span class="nx">expected</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'actual'</span><span class="p">,</span> <span class="nx">actual</span><span class="p">,</span> <span class="s1">'does not equal expected'</span><span class="p">,</span> <span class="nx">expected</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">test</span><span class="p">(</span><span class="nx">aDescription</span><span class="p">,</span> <span class="nx">aTestFunction</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">useNamespaceForFunction</span><span class="p">(</span><span class="nx">namespace</span> <span class="p">,</span> <span class="nx">aTestFunction</span><span class="p">)();</span>
<span class="p">}</span>
<span class="nx">test</span><span class="p">(</span><span class="s2">"that I can call equals as a free function"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">equals</span><span class="p">(</span><span class="mf">1</span><span class="p">,</span><span class="mf">1</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>
<p>Which would allow you to not pollute the global namespace with all the testing equality functions but still call them in a convenient way (that is without needing to go through an object.</p>
<p>All in all, quite nice really - even though I haven't really found a use for this yet. :-)</p>
<p>Implementing the <code>useNamespaceForFunction</code> however isn't quite as straightforward as I had thought - here's my first go at it:</p>
<div class="hll"><pre><span></span><span class="kd">function</span> <span class="nx">useNamespaceForFunction</span><span class="p">(</span><span class="nx">aNamespace</span><span class="p">,</span> <span class="nx">aFunction</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">with</span> <span class="p">(</span><span class="nx">aNamespace</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">eval</span><span class="p">(</span><span class="s1">'('</span> <span class="o">+</span> <span class="nx">aFunction</span> <span class="o">+</span> <span class="s1">')'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>I have since learned that actually using <code>new Function</code> to do the eval might be quite a good idea as the whole point of it is that it ignores the namespace around it, so here's my version two:</p>
<div class="hll"><pre><span></span><span class="kd">function</span> <span class="nx">useNamespaceForFunction</span><span class="p">(</span><span class="nx">aNamespace</span><span class="p">,</span> <span class="nx">aFunction</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">namespacingCode</span> <span class="o">=</span> <span class="s2">"with (aNamespace) { return ("</span> <span class="o">+</span> <span class="nx">aFunction</span> <span class="o">+</span> <span class="s2">"); }"</span><span class="p">;</span>
<span class="c1">// using new Function instead of eval to prevent the current namespace leaking into the eval<</span>
<span class="k">return</span> <span class="ow">new</span> <span class="nb">Function</span><span class="p">(</span><span class="s2">"aNamespace"</span><span class="p">,</span> <span class="nx">namespacingCode</span><span class="p">)(</span><span class="nx">aNamespace</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>So, lets see what uses come up for this technique - I've seen some js code that does an Interpreter of sorts with this trick - but thats about it.</p>
<p>So - I didn't achieve my initial goal - but I did come nearer to it. So I'll call it a success here for now.</p>
<p>If you find any use for this technique, please let me know!</p>
<p>[browser:open-source/javascript-hacks/trunk/namespacing-functions.js Get the source!]</p>