published on 24.11.2007 20:39.

Firefox LiveHTTPHeaders bugfix for Alt-L / @

the firefox LiveHTTPHeaders extension is a great tool for monitoring the http requests going on between your browser and a server—ideal for debugging requests or optimizing caching.

however, the extension has a small but very annoying bug, especially on Mac OS X. it’s sidebar shortcut is Alt-L, which is already occupied by the @ sign. so with this extension installed, you can’t type @s anymore. aaarrgh!

the bug is already (somewhat) fixed in CVS, but it doesn’t look like there’ll be an official release anytime soon. so i dove into the code, did the bare minimum to fix the problem, and made a new xpi. install the patched extension here: livehttpheaders-cvs-patched-071124.xpi.

i moved the sidebar shortcut to Shift-Cmd-J. ”!!?$ Shift-Cmd-J ???!!”, you ask?
“why from Alt-L to Shift-Cmd-J?” well, first, the CVS version already moved the command to Shift-Cmd-L. good. unfortunately Shift-Cmd-L (and Shift-Cmd-K) are already used by the firebug extension, so i moved the key leftwards to the first unoccupied one.

as mentioned above, i did the bare minimum to get the extension to work. no perfection here … but i hope it works for you, too!

Posted in , ,  | Tags , , , ,  | 1 comment

published on 11.11.2007 15:04.

"The suits people are surrounding us."

—Matz, on Ruby becoming “Enterprisey” (via project.ioni.st)

that’s almost a shock, makes me afraid. but he’s right—at last railsconf europe for example, sun, ibm & co showed up. pushing their tools, and ideas of “how to develop”, without any deeper knowledge of ruby. let’s hope they’ve learnt or are willing to learn, and aren’t just disguising just to enter this market and sell their stuff to people who can’t tell the difference.

make sure ruby and the community stay the way they are, it’s what’s makes it special, and what made it successful.

Posted in ,  | no comments

published on 07.10.2007 14:02.

so what's duck typing?

duck typing is actually a simple concept. the best explanations i have come across (from wikipedia 1, 2):

»Suppose you see a bird walking around in a farm yard. This bird has no label that says ‘duck’. But the bird certainly looks like a duck. Also, he goes to the pond and you notice that he swims like a duck. Then he opens his beak and quacks like a duck. Well, by this time you have probably reached the conclusion that the bird is a duck, whether he’s wearing a label or not.” (Immerman 1982, p. 102)«

So, in programming, duck typing is a style of dynamic typing in which an object’s current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class, or implementation of a formal interface.

The ruby mailing list has a great post called ”How to duck type? - the psychology of static typing in Ruby”, explaining the rationale and why duck typing is a good thing (in ruby). an excerpt:

»Many people coming to Ruby from a statically-typed language are somewhat afraid of Ruby’s dynamism, or “don’t get it(TM)”. David Black and I (edit: Tim Bates) believe that this is in part because it is thought that the uncertainty and changeability built into Ruby are dangerous and one wants to find shelter from them.«

Posted in ,  | Tags , ,  | no comments

published on 09.09.2007 16:06.

refactoring five year old javascript code to use the prototype.js library

i’ve long been skeptical of javascript libraries. web 1.0’s myriads of “dhtml” / cross browser libraries didn’t improve the javascript programming experience much. at least there was no library i found so useful that i’d use it in all my projects. so all i had was a couple of snippets picked up here and there, like addEvent() / removeEvent() by the good ole Scott Andrew.

web 2.0 brought a lot of new buzzwords, and more frontend fun. and frontend fun requires: new javascript libraries! fortunately, these libraries seem to be different:

  • they are professionally written, complete with unit-tests
  • their developers don’t have to waste their time coding for horribly bad, pre-DOM browsers (Netscape 4, IE/mac anyone?).
  • they are better integrated in the core of the language
  • their developers have learned from their and other’s experience
  • there are a handful of popular libraries that have been widely adopted, which are continuously developed and improved, producing high quality, reliable code.
  • they focus on developer productivity, instead of eye-candy and supplying drop-in high-level components
  • computers have become faster, allowing to write code that makes developers more productive, although it requires more cpu

ENTER PROTOTYPE.JS

as an experiment, i wanted to refactor a web page i created in 2002, thomasgraggaber.com, to use a current javascript library. since i’ve already used prototype.js, the library is well-established, well-documented, robust (and bundled with ruby on rails), i decided to use it for the experiment.

so here are the stats for the “application” javascript, i.e. everything that’s specific for the site:

  • original lines of code: 571 (65 of them in cross-browser helper methods)
  • lines of code after refactoring to use prototype.js: 445. that’s 22% less code.
  • the cross-browser helper methods were “library code” as well. ignoring those it’s still 10% less code.

of course you add 3271 lines of code for prototype.js (in v. 1.5.1). what’s important however: you usually don’t have to maintain, debug and completely understand the internals of prototype.js when creating your application.

the major code changes are:

Iterators, $$ and Event.observe

before:

var allDivs = document.getElementsByTagName('DIV');
for (i=0; i < allDivs.length; i++) {
    // ...
    else if(allDivs[i].className == 'sidebar')
    {
        addEvent(allDivs[i],"mouseup",dragManager);
        addEvent(allDivs[i],"mousedown",dragManager);
    }
    // ...
}

after:

$$('.sidebar').each(function(div) {
    Event.observe(div, 'mouseup', dragManager);
    Event.observe(div, 'mousedown', dragManager);
});
  • $$() is the swiss army knife for selecting elements in a document. give it a css selector and it will return all matching items in a collection. it probably isn’t the most efficient thing to use, but fine here, and is short. prototype’s document.getElementsByClassName() could also have been used.
  • the temp variable allDivs can be removed, since the iterator function #each works with the result of $$’s return value directly.
  • Event.observe is prototype’s way of registering an event handler cross-browser.

another example. nothing new here, but it takes even more advantage of the iterators:

// photosThumbs viewer
var photosThumbsNodeList = contentDivs['photosThumbs'].getElementsByTagName('IMG');
for (i=0; i < photosThumbsNodeList.length; i++)
{
    addEvent(photosThumbsNodeList.item(i),"click",photoManager);
    addEvent(photosThumbsNodeList.item(i),"mouseover",photoManager);
    addEvent(photosThumbsNodeList.item(i),"mouseout",photoManager);
}
var newsThumbsNodeList = contentDivs['news'].getElementsByTagName('IMG');
for (i=0; i < newsThumbsNodeList.length; i++)
{
    addEvent(newsThumbsNodeList.item(i),"click",photoManager);
    addEvent(newsThumbsNodeList.item(i),"mouseover",photoManager);
    addEvent(newsThumbsNodeList.item(i),"mouseout",photoManager);
}
var portraitThumbsNodeList = contentDivs['portrait'].getElementsByTagName('IMG');
for (i=0; i < portraitThumbsNodeList.length; i++)
{
    addEvent(portraitThumbsNodeList.item(i),"click",photoManager);
    addEvent(portraitThumbsNodeList.item(i),"mouseover",photoManager);
    addEvent(portraitThumbsNodeList.item(i),"mouseout",photoManager);
}

becomes

// photosThumbs viewer
$w('photosThumbs news portrait').each(function(divName) {
    $$("div#" + divName + " img").each(function(img) {
        $w('click mouseover mouseout').each(function(eventName) {
            Event.observe(img, eventName, photoManager);
        });
    });
});
  • $$() is used again. it could be replaced by “$A($(‘border’).getElementsByTagName(‘div’))” if it gets too slow.

the $w function

before:

// add event handlers
var naviDivs = document.getElementById('border').getElementsByTagName('DIV');
for (i=0; i < naviDivs.length; i++)
{
    addEvent(naviDivs.item(i),"click",ggNaviManager);
    addEvent(naviDivs.item(i),"dblclick",ggNaviManager);
    addEvent(naviDivs.item(i),"mouseover",ggNaviManager);
    addEvent(naviDivs.item(i),"mouseout",ggNaviManager);
    addEvent(naviDivs.item(i),"mousedown",ggNaviManager);
    addEvent(naviDivs.item(i),"mouseup",ggNaviManager);
}

after

// add event handlers
$$('div#border div').each(function(naviDiv) {
    $w('click dblclick mouseover mouseout mousedown mouseup').each(function(eventName) {
        Event.observe(naviDiv, eventName, ggNaviManager);
    });
});
  • $w is a nice adoption from ruby (where it’s %w). it splits the string argument by whitespace, returning an array of the items (“words”). very readable in this case.

Event.element(e), and returning only element nodes

e = (e) ? e : ((window.event) ? window.event : '');
eTarget = e.srcElement ? e.srcElement : e.target;   
while(eTarget.nodeName != 'DIV') {
    eTarget = eTarget.parentNode;
}

becomes

eTarget = Event.element(e);

nice.

  • prototype handles finding the event target in a cross-browser way. (note: prototype 1.6.0 will make this even simpler. the event handler will be bound to the event target, so the event target will be available in the “this” variable.)
  • prototype only returns element nodes, so the while() loop looking upwards for a div element becomes obsolete. it was required since it’s possible that the text node inside the element was clicked. this behavior allowed removal of a couple of these loops.

“DOM walking” with up(), down()

scrolledDiv = first_child(node_after(eTarget.parentNode.parentNode));

becomes:

scrolledDiv = eTarget.up('.box').down('.content')
  • firstchild() and nodeafter() were some of the utility methods to walk through the DOM, and already ignoring whitespace and text nodes. element.up(…).down(…) do the same, but are nicer, shorter, clearer to use.

show() and hide()

before:

function displayNavi()
{
    document.getElementById('sponsorFlash').style.display = 'none';
    document.getElementById('border').style.display = 'block';  
}

after:

function displayNavi()
{
    $('sponsorFlash').hide();
    $('border').show();
}
  • the code becomes more concise, and more expressive.
  • i don’t have to remember which elements require which display style in order to be displayed correctly (block/table/inline elements have different values).

conclusions

  • by using prototype.js i was able to remove 10% of the code
  • at the same time, the code is more readable than before
  • as an additional benefit, the site now probablyworks in safari (and all browsers that prototype supports)!

prototype.js rocks, because it’s developed by smart people, and because javascript itself rocks!

Posted in ,  | Tags , , , , ,  | no comments

published on 11.08.2007 16:32.

25 german startups, and their technology choices

jetzt.de (the “youth” magazine of the süddeutsche zeitung) gives an interesting overview of 25 current german startups, asking every one of them around a dozen questions.

greenmiles.de

i found the greenmiles.de idea particularly interesting: you enter your planned trip and transportation type, then they calculate how much co2 is produced. you can then donate an appropriate amount of money to climate conservation programs, allowing you trip to be climate neutral. of course very rough, but nevertheless interesting feedback on how much co2 one of us produces in his day to day life. for example, one round-trip flight hamburg-munich produces 9m³ of co2, which equals a cost of 8 euros.

german startup technology choices

i was curious which technologies these startups would consider best for their success, so i looked at the programming languages and frameworks they used. here are the results:

60% php
16% ruby (= ruby on rails)
16% java
4% asp.net
4% (project offline)

a couple of observations:

php & java have been at the availability of web developers since at least 1999 (that’s when i started) and ruby on rails had it’s 1.0 release in december 2005. so i can only say: go rails! :-)

so let’s say konichiwa to these ruby on rails projects:

looking at php

of course with 60%, php is the most important language by far. it’s the technology one needs least development experience for, and it allows fast results; therefore very appealing. working with less experienced developers however also means things can go really bad down the road – remember the studivz scalability and security issues, for example. and still not all of the startups seem to do their php development in a professional way. some use a CMS (typo3) as a base for their site, others still run php version 4, which has been replaced by php5 three years ago and is now discontinued.

there is only rails

the java and php projects use a variety of frameworks, but in the ruby projects – there is only rails. that’s good – a ruby web developer will almost certainly know how to work with rails. a php developer will more than likely not know how to work with your framework, since there are so many open source php frameworks out there, and still many people roll their own one.

on a side note, only one startup runs on microsoft technology …

i figured out what a site runs by looking at their webserver’s responses (server type, cookie name) and the generated html. if in doubt i checked their tech jobs postings, too. for the technically inclined, here’s the full list:

  • dealjaeger.de: java
  • spickmich.de: php
  • cellity.com: java (jboss)
  • autoaid.de: php (symfony) AND/OR python
  • hitflip.de: php
  • verwandt.de: php
  • amiando.de: java
  • dawanda.de: ruby on rails (/w mongrel server)
  • hiogi.de: php
  • zeitkapsel.de: php
  • wazap.de: java
  • schutzgeld.de: php (typo3)
  • frazr.de: php
  • rankaholics.de: php
  • sevenload: php
  • imedo.de: ruby on rails (/w mongrel server)
  • globalzoo.de: php
  • greenmiles.de: php (typo3, still php4!)
  • jajah.com: asp.net
  • mitbringzentrale.de – (offline)
  • mymuesli.de: php (still php4!)
  • qype.de: ruby on rails (/w lighttpd server)
  • spielerkabine.de: ruby on rails (/w lighttpd server)
  • edelight.de: php
  • studivz.de: php

Posted in , ,  | no comments

published on 18.05.2007 12:26.

some bash shell tricks

phillipoertel@[~]: cd Documents/seaside/
phillipoertel@[~/Documents/seaside]: cd -
/Users/phillipoertel
phillipoertel@[~]: a b c
-bash: a: command not found
phillipoertel@[~]: !$
c
-bash: c: command not found
phillipoertel@[~]: a b c
-bash: a: command not found
phillipoertel@[~]: !!
a b c
-bash: a: command not found
phillipoertel@[~]: a b c
-bash: a: command not found
phillipoertel@[~]: !*
b c
-bash: b: command not found
phillipoertel@[~]: 

see also: nubyonrails.com

Posted in  | no comments

published on 18.05.2007 00:18.

flickr.phillipoertel.com

just gave my flickr api toys a little overhaul. check them out. more coming soon, for example entering your username to show your contacts’ photos, instead of mine.

Posted in , ,  | no comments

published on 18.04.2007 13:37.

"This path leads to the gates of madness."

»Because if itself is an expression, you can get really obscure with statements such as:«

if artist == "John Coltrane"
  artist = "'Trane"
end unless nicknames == "no"

from the original pickaxe by dave thomas.

Posted in ,  | Tags , , ,  | 1 comment

published on 27.03.2007 08:06.

PHP: a quick SimpleXML benchmark

update: needs work to become comparable with the ruby benchmark posted earlier.

as an update to the ruby xml performance test, some info for PHPs standard way of parsing XML, SimpleXML. since it uses libxml2 internally, the results are more comparable to ruby’s libxml2 parser, although not identical … (i don’t yet understand where the factor 10 difference in xpath comes from).

loading an xml file

file size ms
10KB 0.71
100KB 5.88
1.6MB 120.97

simple xpath expression

file size ms
10KB 0.75
100KB 6.39
1.6MB 79.52

the test code

<?php

function benchmark($function)
{
   $start = microtime(true);
   for ($i=0; $i<10; $i++) {
      // execute the anonymous function ("yield")
      $function();
   }
   echo ((microtime(true) - $start) / 10) * 1000;
   echo "\n";
} 

// put file into filesystem cache (hope this works)
file_get_contents('products.xml');
/**
 * info: using create_function does not change performance 
 * (in comparison with executing the code in a more traditional php way)
 */

// loading xml into an object
benchmark(
   create_function(
      // function arguments as string
      '',
      // method body as string
      '$doc = simplexml_load_file("products.xml");'
   )  
); 

benchmark(
   create_function(
      // function arguments as string
      '',
      // method body as string
      '$doc = simplexml_load_file("products.xml");
       foreach ($doc->xpath("//articles/article/shortdesc") as $node) {
          //echo $node;
       }'
   )
);

?>

Posted in ,  | Tags , , ,  | no comments

published on 27.03.2007 07:43.

extending PHP's SimpleXML

PHP’s XML workhorse, SimpleXML can be extended. you can supply a class of your own for PHP to wrap all XML nodes instead of the default SimpleXMLElement. do this by passing the desired class name as a string to the simplexml_load_(file|string) methods:

<?php

class MySimpleXMLElement extends SimpleXMLElement
{     
   // extending parent method
   public function xpath($path)
   {  
      echo "evaluating the following xpath expression: $path\n";
      $result = parent::xpath($path);
      echo "found " . sizeof($result) . " nodes";
      return $result;
   }
}

$doc = simplexml_load_file('products.xml', 'MySimpleXMLElement');
// calling an extended method
$nodes = $doc->xpath('//articles/article/shortdesc');
echo "\n";

// calling a parent method
echo $doc->root->getName();
echo "\n";

?>

i didn’t poke around in the internals of the parent class too much, no idea how well that would. on the other hand, in many cases it might be a better solution to delegate to SimpleXML instead of inheriting and extending from it.

Posted in ,  | Tags , ,  | no comments

Older posts: 1 2 3 4 5 6