<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href="http://inside.webfactory.de/static/common/rss-feed.xsl" type="text/xsl" media="screen"?><rss version="2.0">

  <channel xml:base="http://inside.webfactory.de/en/blog/">
	<title>webfactory Neuigkeiten</title>
	<link>http://inside.webfactory.de/en/blog/</link>
	<description></description>
	<language>en_gb</language>
	<copyright>© 2010 webfactory GmbH</copyright>
	<pubDate>Fri, 12 Mar 2010 08:42:07 +0100</pubDate>

	<image>
	  <url>http://inside.webfactory.de/static/img/logo.gif</url>
	  <title>Logo webfactory</title>
	  <link>http://www.webfactory.de/</link>
	</image>

	<item>
	  <title>Yes, we geek or A Tale of Mincemeat and Zucchini</title>
	  <link>http://inside.webfactory.de/en/blog/trueborn-geeks.html</link>
	  <description>&lt;p&gt;Yesterday we (dr, hs and sb) were working late, and around 10:00pm lunch seemed very long ago indeed. A quick survey of the kitchen confirmed that we had enough leftover ingredients for spaghetti bolognese with onions, tomatoes and zucchini. What we didn't have was mincemeat and somebody willing to leave his desk long enough to cook.&lt;/p&gt;&lt;p&gt;A short IM battle ensued.&lt;/p&gt;&lt;p&gt;&lt;em&gt;sb:&lt;/em&gt; go and cook us dinner :)&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; you two designers.. me one programmer..&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; is this democracy?&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; yes&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; this is oppression&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; yes&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; NOW COOK &lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; NO!&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; NO YOU COOK&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; we fight for our freedom!&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; COOK!&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; permission denied&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; COOK!&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; permission denied&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; COOK!&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; permission denied&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; you don't get it..&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; COOK!&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; permission denied&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; hmm.. maybe I should say: &quot;insufficient rights&quot; &lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; &lt;strong&gt;sudo cook dinner -hs -sb&lt;/strong&gt; &lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; damn. I'll do it...&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; buy mincemeat! &lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; what! we'll eat vegan&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; we have zucchini!&lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; &lt;strong&gt;sudo buy mincemeat&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; shit. &lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; pwnage &lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; &lt;strong&gt;Enter password:&lt;/strong&gt; &lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; mincemeat &lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; &lt;strong&gt;Sorry, try again. Remaining tries: 2&lt;/strong&gt; &lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; ahh.. mom: &lt;br /&gt;&lt;em&gt;dr:&lt;/em&gt; ******** &lt;br /&gt;&lt;em&gt;sb:&lt;/em&gt; SHIT&lt;/p&gt;&lt;p&gt;The quite enjoyable dinner was served soon after.&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/trueborn-geeks.html</guid>
	  <pubDate>Thu, 09 Jul 2009 00:00:00 +0200</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>About the TCP MSS and wrong checksums</title>
	  <link>http://inside.webfactory.de/en/blog/tcp-checksum-off-by-one-errors-with-mss-1380.html</link>
	  <description>&lt;p&gt;During the last days, I had to refresh my knowledge about the gory details of the TCP protocol. By far I'm not versed enough to get into something like &lt;a href=&quot;http://www.sigcomm.org/sigcomm2000/conf/abstract/9-1.htm&quot; shape=&quot;rect&quot;&gt;this&lt;/a&gt; or &lt;a href=&quot;http://valerieaurora.org/tcpip.html&quot; shape=&quot;rect&quot;&gt;that&lt;/a&gt;, but at least my current problem was solved.&lt;/p&gt;&lt;p&gt;I spent a few hours troubleshooting a strange TCP connection problem. HTTP connections to one particular host were no longer working since we got a new Cisco ASA 5510 firewall managed by an external provider, set up to NAT outgoing connections. Initial connections to that host and the first HTTP request returning a redirect worked, but the following request would only return a few KB of HTML and then stall. Only that host was affected, at least we had not observed the problem somewhere else.&lt;/p&gt;&lt;p&gt;I did a tcpdump of the traffic between the firewall and our SDSL uplink and got the following.&lt;/p&gt;&lt;pre xml:space=&quot;preserve&quot;&gt;
mp@blackbook:~$ sudo tcpdump -v -ttt -s0 -n host remote.host
tcpdump: listening on en0, link-type EN10MB (Ethernet), capture size 65535 bytes&lt;br /&gt;000000 IP ([...], length 48) firewall.26167 &amp;gt; remote.host.80: S, cksum 0x0b7b (correct), 3325973421:3325973421(0) win 65535 &amp;lt;mss 1380,nop,nop,nop,nop&amp;gt;&lt;br /&gt;213304 IP ([...], length 44) remote.host.80 &amp;gt; firewall.26167: S, cksum 0xe020 (correct), 83736657:83736657(0) ack 3325973422 win 32768 &amp;lt;mss 1380&amp;gt;&lt;br /&gt;000320 IP ([...], length 40) firewall.26167 &amp;gt; remote.host.80: ., cksum 0x778e (correct), ack 1 win 65535&lt;br /&gt;000555 IP ([...], length 396) firewall.26167 &amp;gt; remote.host.80: P, cksum 0x3f23 (correct), 1:357(356) ack 1 win 65535&lt;br /&gt;225193 IP ([...], length 317) remote.host.80 &amp;gt; firewall.26167: P, cksum 0xdd51 (correct), 1:278(277) ack 357 win 32768&lt;br /&gt;017471 IP ([...], length 1420) remote.host.80 &amp;gt; firewall.26167: P, cksum 0x9fce (incorrect (-&amp;gt; 0x9fcd), 278:1658(1380) ack 357 win 32768&lt;br /&gt;016391 IP ([...], length 1420) remote.host.80 &amp;gt; firewall.26167: P, cksum 0x766d (incorrect (-&amp;gt; 0x766c), 1658:3038(1380) ack 357 win 32768&lt;br /&gt;203816 IP ([...], length 40) firewall.26167 &amp;gt; remote.host.80: ., cksum 0x762a (correct), ack 278 win 65258&lt;br /&gt;226371 IP ([...], length 1420) remote.host.80 &amp;gt; firewall.26167: ., cksum 0x6120 (incorrect (-&amp;gt; 0x611f), 3038:4418(1380) ack 357 win 32768&lt;br /&gt;2. 398071 IP ([...], length 1420) remote.host.80 &amp;gt; firewall.26167: P, cksum 0x9fce (incorrect (-&amp;gt; 0x9fcd), 278:1658(1380) ack 357 win 32768&lt;br /&gt;2. 947090 IP ([...], length 1420) remote.host.80 &amp;gt; firewall.26167: P, cksum 0x9fce (incorrect (-&amp;gt; 0x9fcd), 278:1658(1380) ack 357 win 32768&lt;br /&gt;5. 479496 IP ([...], length 1420) remote.host.80 &amp;gt; firewall.26167: P, cksum 0x9fce (incorrect (-&amp;gt; 0x9fcd), 278:1658(1380) ack 357 win 32768
&lt;/pre&gt;&lt;p&gt;That looked as if the remote host was sending a lot of packets with wrong TCP checksums. Our firewall would just trash those packets, not sending out ACKs for them and wait for a retransmission. Those retransmissions can be seen at the end of the trace and trickled away with geometrically increasing intervals. As the retransmissions show the same error, the bottom line is that nothing gets along anymore.&lt;/p&gt;&lt;p&gt;Interestingly, the checksums were always off by just one. Had the packets really been altered (for example, corrupted by bit errors on the wire) during transport, the deviations should be arbitrary.&lt;/p&gt;&lt;p&gt;So my first guess was that the remote host or some component along the path had a bug in the procotol stack and was putting in incorrectly calculated checksums. But OTOH it's hard to imagine that we would be the first to discover such a bug.&lt;/p&gt;&lt;p&gt;When taking the firewall out of the mix the connections worked fine and all packets were ok. This is strange, as the &lt;a href=&quot;http://www.tcpipguide.com/free/t_TCPChecksumCalculationandtheTCPPseudoHeader.htm&quot; shape=&quot;rect&quot;&gt;TCP checksum is calculated&lt;/a&gt; based on a single TCP packet with some additional information from the IP layer. So as to the correctness and verification of the checksum, it is irrelevant what has been sent in the other direction before and whether such previous packets have passed the firewall or not.&lt;/p&gt;&lt;p&gt;Now one important observation was that the incorrect checksum was only in packets that were 1420 bytes in total size. This is the maximum possible size one can observe in this connection for a MSS of 1380 is negotiated during the TCP handshake and 40 byte for IP and TCP header come on top of that.&lt;/p&gt;&lt;p&gt;Using a test host placed outside (before) the firewall would result in working connections with an MSS of 1460, which is the Ethernet MTU of 1500 minus the 40 bytes. Setting the MTU to 1420 on that host yielded a MSS of 1380, but the returning packets were correctly checksummed in this case.&lt;/p&gt;&lt;p&gt;So although the MSS seemed not to be a sufficient condition to trigger the problem, I started to investigate why the firewall would use a value of 1380 where 1460 should be possible. We found a setting called &quot;force maximum segment size for TCP proxy connections&quot; in the Cisco's admin interface that was set to 1380. We unset that option and voilà, everything worked with the MSS going up to 1460.&lt;/p&gt;&lt;p&gt;What rankles me is that although the symptoms are cured, I still haven't found the cause for the wrong checksums. I don't see why setting the MSS to a lower value than necessary should be a problem at all (performance issues aside). And, having the checksums always off-by-one smells like another bug somewhere along the connection's path. I googled a lot for this one, but the only relevant results were in a discussion in the context of SMTP (but that's TCP after all) &lt;a href=&quot;http://archives.neohapsis.com/archives/postfix/2006-09/0317.html&quot; shape=&quot;rect&quot;&gt;over there&lt;/a&gt; and &lt;a href=&quot;http://archives.neohapsis.com/archives/postfix/2006-09/0340.html&quot; shape=&quot;rect&quot;&gt;there&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Hopefully, this article will save someone some headaches. If you have any ideas regarding the cause of this problem, I'd be glad to hear from you. Feel free to leave a comment!&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/tcp-checksum-off-by-one-errors-with-mss-1380.html</guid>
	  <pubDate>Fri, 06 Mar 2009 00:00:00 +0100</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>wfDevCamp 2008: Work Away From Work</title>
	  <link>http://inside.webfactory.de/en/blog/wfdevcamp-2008.html</link>
	  <description>&lt;p&gt;Sometimes, special tasks require unusual measures. It was obvious that we needed to move the development of wfDynamic, webfactory’s content management framework, a big step forward. So in December 2008 the webfactory team headed to an apartment in the Austrian mountains for a week of focused, uninterrupted work.&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;Photo session on the balcony :-)&quot; class=&quot;XStandardImageLeft&quot; src=&quot;../../static/common/wfimage/70b60b3b94fbc9dbeefec1a6b5ab91ff.jpg&quot; width=&quot;250&quot; /&gt;In the middle of daily routines, it is difficult to bring all the people together that are needed to achieve giant leaps in product development. At a small software development company like webfactory, everyone is working on different projects with different rhythms. There are meetings with customers, impromptu meetings of small sub teams on project-related minutiae and phone calls that need to be handled.&lt;/p&gt;&lt;p&gt;But we needed to get things done: wfDynamic heavily relied on user interface techniques that didn't comply to today's web standards and accessibility guidelines. Replacing these techniques by state-of-the-art alternatives was a job that needed time, focus and every skill we had on the team.&lt;/p&gt;&lt;p&gt;We felt that a week away from the office with the whole team would be the break we needed. Enough distance from „business as usual“ to really be able to zone into product development. The idea of a webfactory DevCamp was born.&lt;/p&gt;&lt;h2&gt;Laying the groundwork&lt;/h2&gt;&lt;p&gt;The first step to take was finding a location. We agreed on a few particular requirements:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;far enough from home to have a clean cut from everyday life&lt;/li&gt;&lt;li&gt;no distractions (no phone, no emails)&lt;/li&gt;&lt;li&gt;a flexible and inspiring working environment for the team&lt;/li&gt;&lt;li&gt;attractive options for breaks&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We were very fortunate to find a place that almost perfectly met our requirements in the Austrian Alps. One team member's family had been using a holiday apartment in Westendorf, Tyrol for years. The apartment, situated on a small mountain road, had a good size to accomodate our company of five. The fresh mountain air and great views over the valley from our balcony provided an inspiring background for a concentrated working atmosphere. A ski lift in walking distance and many hiking trails through the snow-covered forest behind the house were just calling for attention whenever we needed a longer break. However, most of the time we were too captivated by our ideas and discussions to even consider going outside.&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;View from the balcony&quot; src=&quot;../../static/common/wfimage/7fd31fd3753b4e4cfa3d5bd7df3f3ba6.jpg&quot; width=&quot;500&quot; /&gt;&lt;/p&gt;&lt;h2&gt;The setup&lt;/h2&gt;&lt;p&gt;Westendorf is about 700km south of our office. We decided to hire a van for the trip to foster team communication even on the journey.&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;Our mobile office infrastructure&quot; class=&quot;XStandardImageRight&quot; src=&quot;../../static/common/wfimage/266404f6c4e5bf5f87aeb218af545df3.jpg&quot; width=&quot;250&quot; /&gt;On arrival in Westendorf we hit the next „Hofer“ discount market to buy some food and a &lt;a href=&quot;http://www.yesss.at/diskont-surfen/home.php&quot; shape=&quot;rect&quot;&gt;„yesss“ mobile internet flatrate&lt;/a&gt; with USB stick. Equipped with the USB stick, a Mac Mini was serving as our router for internet access and also as host for our version control repository. It took a while to set up, but after we got it running it didn’t let us down once.&lt;/p&gt;&lt;h2&gt;Discussions&lt;/h2&gt;&lt;p&gt;&lt;img alt=&quot;Discussions during coffee time&quot; class=&quot;XStandardImageLeft&quot; src=&quot;../../static/common/wfimage/6069f5661375ef1141a536300ddd6b5c.jpg&quot; width=&quot;250&quot; /&gt;The team that set to work reinventing our product was quite diverse. Besides the more obvious division in software developers and interface designers, there were also subtly different flavours to each member. Analytical minds mixed with visual thinkers, the urge to save time for careful consideration clashed with pragmatic hands-on approaches. The question to what extent we would reuse the old code or start from scratch was another controversial subject.&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;Combined living/working/sleeping room&quot; class=&quot;XStandardImageRight&quot; src=&quot;../../static/common/wfimage/621cb65bf5124ec0e0e2ea6666a0d893.jpg&quot; width=&quot;250&quot; /&gt;All of it led to some very difficult but interesting and productive discussions throughout the week. Incidentally, it took more than half a day before the developers touched the first lines of code. The designers dug into Photoshop to knock up a few visual ideas while the most fundamental code discussions were under way.&lt;/p&gt;&lt;h2&gt;Iterative Improvements&lt;/h2&gt;&lt;p&gt;It was interesting to see how we tended to discard the previous day’s ideas every morning because someone had come up with an even better approach after a break and/or getting a few hours of sleep. At last, Day 4 of our stay saw the first implementations of our new designs.&lt;/p&gt;&lt;h2&gt;Sum of the parts&lt;/h2&gt;&lt;p&gt;&lt;img alt=&quot;Scribbling the GUI concept&quot; class=&quot;XStandardImageLeft&quot; src=&quot;../../static/common/wfimage/6943526c7f70743b0c9957722725f612.jpg&quot; width=&quot;250&quot; /&gt;After getting a better idea of the user's flow through and interactions with our application, the designers went back to their wireframes and started implementing them based on growing HTML outputs from the development faction. It worked quite smoothly and we had a rudimentary system up and running on the last day. With a lot of work left ahead, but a solid new code foundation under our belts, we returned home in high spirits.&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;The webfactory DevCamp exceeded all our expectations. The development results were fabulous and we are absolutely convinced that we could never have achieved anything remotely similar during regular hours at the office. The event was also a great team building experience - shared memories of our day out (braving the slopes on sleighs) and of a few quite effective discussions during the shorter hikes around the house top the charts next to the energetic and productive atmosphere during development.&lt;/p&gt;&lt;p&gt;We will definitely do this again!&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;On the way to the sleigh ride&quot; src=&quot;../../static/common/wfimage/0733109a26f8e1a6072dad89f9858959.jpg&quot; width=&quot;250&quot; /&gt; &lt;img alt=&quot;Downhill!&quot; src=&quot;../../static/common/wfimage/6243a6016cb2612254d9f02674dd173b.jpg&quot; width=&quot;250&quot; /&gt;&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/wfdevcamp-2008.html</guid>
	  <pubDate>Wed, 28 Jan 2009 00:00:00 +0100</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>Preach What You Practice</title>
	  <link>http://inside.webfactory.de/en/blog/preach-what-you-practice.html</link>
	  <description>&lt;p&gt;webfactory has always been about creating &lt;a href=&quot;http://www.webfactory.de/en/services/website-development/attractive-content/&quot; shape=&quot;rect&quot;&gt;highly usable&lt;/a&gt; and &lt;a href=&quot;http://www.webfactory.de/en/services/website-development/accessibility/&quot; shape=&quot;rect&quot;&gt;accessible&lt;/a&gt; websites, keeping a close watch on &lt;a href=&quot;http://www.webstandards.org/learn/&quot; shape=&quot;rect&quot;&gt;web standards&lt;/a&gt; and the &lt;a href=&quot;http://microformats.org/wiki/POSH&quot; shape=&quot;rect&quot;&gt;POSH paradigm&lt;/a&gt;. This September we finally decided it was time to start preaching what we practice.&lt;/p&gt;&lt;p&gt;So you say, „Dude, get real! It’s 2008! Web standards are not only known among the web working crowd, they’re our bread and butter!“. Sadly, there are still websites &lt;a href=&quot;http://www.seitenbacher.de&quot; shape=&quot;rect&quot; title=&quot;www.seitenbacher.de - This page was relaunched with table-based layout in October 2008!&quot;&gt;prooving&lt;/a&gt; &lt;a href=&quot;http://www.commerzbank.de&quot; shape=&quot;rect&quot; title=&quot;www.commerzbank.de - Not the worst site in town, but they could have used a list for their navigation. Really.&quot;&gt;you&lt;/a&gt; &lt;a href=&quot;http://www.mcdonalds.com&quot; shape=&quot;rect&quot; title=&quot;www.mcdonalds.com - Honestly? Nothing says &amp;quot;I'm lovin' it&amp;quot; like a black background paired with outdated code.&quot;&gt;wrong&lt;/a&gt;. There is still need to spread the gospel and point both established and new web workers in the right direction.&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;Per lectures the workshop crowd about semantic HTML&quot; class=&quot;XStandardImageLeft&quot; src=&quot;../../static/common/wfimage/975feaa5f28d648dbf96a2da7ba63f8d.jpg&quot; width=&quot;150&quot; /&gt;On a sunny Saturday afternoon we invited a group of students who are serving apprenticeships as digital media designers like webfactory’s own &lt;a href=&quot;http://www.webfactory.de/en/company/team/soeren-birkemeyer/&quot; shape=&quot;rect&quot;&gt;Søren Birkemeyer&lt;/a&gt; into our company's Bistro and set about to highlight the advantages of semantic HTML and web standards. After an initial phase of explaining concepts and best practices, we confronted the group with a real-world task: translating a finished design (a Photoshop file) into HTML and CSS.&lt;/p&gt;&lt;p&gt;With one exception, all attendees had a print-related background in their companies and were rather new to both HTML and CSS. And yet, after only half an hour, people got to grips with &lt;a href=&quot;http://notepad-plus.sourceforge.net/&quot; shape=&quot;rect&quot; title=&quot;Notepad++ is a free source code editor and Notepad replacement that supports several languages.&quot;&gt;our editor of choice for the workshop&lt;/a&gt; and the first discussions arose about correct semantics and markup. „Is this a headline at all?“ „I have ‚by’ and ‚from’ looking special to me in this sentence, but if I emphasize them that’s not what really want, or is it?“&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;Per and a participant winding down at the kicker table after a long workshop&quot; class=&quot;XStandardImageRight&quot; src=&quot;../../static/common/wfimage/fce17ccfc1a74647ad261629517fd23f.jpg&quot; width=&quot;150&quot; /&gt;With regard to the exemplary weather we had been planning for a quite open workshop, hoping for perhaps two hours of concentrated work before the session dissolved around beers and a game or two on our kicker table. Alas, we ended up closing the door behind the last die-hards after seven hours of hard work, coffee and beautiful code.&lt;/p&gt;&lt;p&gt;We are really happy about the turnout and will certainly continue with another workshop in the near future, so stay tuned! After all, who could resist the chance to turn people into POSH-&lt;a href=&quot;http://www.randsinrepose.com/archives/2007/11/11/the_nerd_handbook.html&quot; shape=&quot;rect&quot; title=&quot;&amp;quot;The Nerd Handbook&amp;quot; by Michael Lopp&quot;&gt;nerds&lt;/a&gt;? :-)&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/preach-what-you-practice.html</guid>
	  <pubDate>Tue, 07 Oct 2008 00:00:00 +0200</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>Browsertesting can be fun!</title>
	  <link>http://inside.webfactory.de/en/blog/browser-testing-can-be-fun.html</link>
	  <description>&lt;p&gt;Okay, enthusiasm may have gotten the better of me when I was punching in this entry's title. But even when you're doing what every frontend engineer hates by default – testing and retesting your page in the major browsers known to mankind – there are a few tools that can really make things easier for you.&lt;/p&gt;&lt;p&gt;Let us revisit a great talk by Nate Koechley first. I saw him at this year's &lt;a href=&quot;http://www.vivabit.com/atmedia2008/london/&quot; shape=&quot;rect&quot; title=&quot;@media Conference 2008 in London, official website&quot;&gt;@media conference&lt;/a&gt; where he went and instilled some (needed?) pride into those of us who work the (X)HTML/CSS/JS/DOM/Browser angle of websites. Is frontend engineering a &quot;real&quot; job? Hell yeah! Check out the &lt;a href=&quot;http://nate.koechley.com/blog/2008/06/11/slides-professional-frontend-engineering/&quot; shape=&quot;rect&quot;&gt;slides of his talk&lt;/a&gt; on his blog and see how he arrives at the magic number of 672 different situational combinations of website/user environments that we have to prepare and test for.&lt;/p&gt;&lt;p&gt;So what can ease the job with the actual testing work? It goes without saying that you should always develop with at least three to four browsers, namely the current builds of IE7, FF3, Opera and Safari, open next to your IDE. It's miles better to check browser behaviour immediately than finishing off a template for Firefox, opening it in IE and having to start all over again.&lt;/p&gt;&lt;p&gt;I have the advantage of working on a Mac with Windows XP running on a virtual machine, so I can cover these two operating systems and the main browsers with relative ease. But what about testing multiple versions of the same browser?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Testing multiple Internet Explorer versions in Windows: IE Tester&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Up until recently my favourite tool for testing multiple IEs was the aptly named &lt;a href=&quot;http://tredosoft.com/Multiple_IE&quot; shape=&quot;rect&quot;&gt;Multiple IE&lt;/a&gt;. However, when I ran into problems with testing browser specific styles (via conditional comments) I went looking for an alternative and found &lt;a href=&quot;http://www.my-debugbar.com/wiki/IETester/HomePage&quot; shape=&quot;rect&quot;&gt;IE Tester&lt;/a&gt;. This one is working flawlessly so far and even includes a IE8 beta engine for pretesting, if you're so inclined.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Testing multiple Firefox versions: MultiFirefox&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Since Firefox is Firefox you'd guess it's fairly easy to set up two parallel installations, right? Well, it's not quite that simple, since FF has a tendency to overwrite itself and/or its user profiles when you install a second version.&lt;/p&gt;&lt;p&gt;For Mac users there's a pretty straightforward solution called &lt;a href=&quot;http://codecontortionist.com/software/mac-osx-software/multifirefox/&quot; shape=&quot;rect&quot;&gt;MultiFirefox&lt;/a&gt; that handles profile management for you. Install FF3 and FF2 and the application will take your hand and help you set yourself up.&lt;/p&gt;&lt;p&gt;Windows users have to go through a bit more manual tuning work, which is &lt;a href=&quot;http://www.command-tab.com/2008/06/18/how-to-run-firefox-2-and-3-simultaneously/&quot; shape=&quot;rect&quot;&gt;nicely covered by Command-Tab.com&lt;/a&gt;. They also mention MultiFirefox as the tool for MacOS.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;If you have better solutions for browser testing, or just found these recommendations to be helpful, don't be shy and drop us a comment!&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/browser-testing-can-be-fun.html</guid>
	  <pubDate>Mon, 18 Aug 2008 00:00:00 +0200</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>PHP Namespaces Explained</title>
	  <link>http://inside.webfactory.de/en/blog/php-namespaces-explained.html</link>
	  <description>&lt;p&gt;Namespaces are one of top &lt;a href=&quot;http://www.php.net/~derick/meeting-notes.html&quot; shape=&quot;rect&quot;&gt;new features&lt;/a&gt; you can expect from the upcoming major PHP versions. There's still a lot of discussion and &lt;a href=&quot;http://news.gmane.org/find-root.php?message_id=%3c4739B26D.6040807%40velum.net%3e&quot; shape=&quot;rect&quot;&gt;confusion&lt;/a&gt; about how it's going to work in detail, especially because &lt;a href=&quot;http://cvs.php.net/viewvc.cgi/php-src/README.namespaces?view=markup&quot; shape=&quot;rect&quot;&gt;official documentation&lt;/a&gt; is scarce and behaviour is subject to change. That being said, in this article I will try to sum up what I could observe playing around with a fresh checkout from PHP's PHP_5_3 CVS branch.&lt;/p&gt;
&lt;h2&gt;Namespaces Really Are Packages&lt;/h2&gt;
&lt;p&gt;PHP 5.3 brings the new &quot;namespace&quot; statement. When present, this statement must be the first one in a file. Thus, you cannot use multiple namespace statements per file :-) or even nest the statements. This is why PHP namespaces are more like Java's packages than the namespace concept as in, for example, C++. Anyway, I will use the term &quot;namespace&quot; here. Now what does happen?&lt;/p&gt;
&lt;h3 id=&quot;test1&quot;&gt;test1.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;namespace webfactory::NS1;
class X {}
print get_class(new X()) . &quot;\n&quot;;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Basically, the namespace statement declares that all class names you define in that very file belong to the namespace. Namespaces also work for function names, but I won't cover functions any further here. The above example will print &quot;webfactory::NS1::X&quot; as that is what the class X is &lt;em&gt;really&lt;/em&gt; called. This is said to be the &lt;em&gt;fully qualified name&lt;/em&gt; of the class.&lt;/p&gt;
&lt;p id=&quot;defining-class-names&quot;&gt;&quot;Defining&quot; a class name means actually providing a class definition. If you just require() a class definition from another file, that class won't end up in your file's namespace. It will be in the namespace set for the file where the class is defined (if any is set).&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;#test1&quot; shape=&quot;rect&quot;&gt;test1.php&lt;/a&gt;, &quot;webfactory::NS1&quot; is a compound name. You may use &quot;webfactory&quot; as well as &quot;webfactory::NS2&quot; or even &quot;webfactory::NS1::Sub1&quot; as namespaces in other files. In all these files, you can define classes named X and they all will be discriminable because their fully qualified names differ. If you declare a class X in a file without a namespace statement, the fully qualified class name will be &quot;::X&quot; (however, get_class() will just return &quot;X&quot; in that case).&lt;/p&gt;
&lt;p&gt;For the rest of this article, let's assume we've got the following two files using the two namespaces webfactory::NS1 and webfactory::NS2:&lt;/p&gt;
&lt;h3 id=&quot;ns1x&quot;&gt;ns1_x.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;namespace webfactory::NS1;
class X {}
&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;ns2x&quot;&gt;ns2_x.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;namespace webfactory::NS2;
class X {}
&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Attention Attention...&lt;/h2&gt;
&lt;p&gt;Before we proceed, understand that the entire namespace thing is just about naming and referring to classes in a convenient way. It has &lt;em&gt;nothing&lt;/em&gt; to do with packaging or loading classes for you. You still will have to use require() and its friends to load your classes. If __autoload() does that job for you, you can probably benefit from tweaking your handler to make use of the namespace names, but basically that changes nothing.&lt;/p&gt;
&lt;h2&gt;Fully Qualified Names&lt;/h2&gt;
&lt;p&gt;The most straightforward way of telling PHP what you mean is to refer to classes by their fully qualified names. You can always do that regardless of the namespace you're in or the namespaces you use. Example:&lt;/p&gt;
&lt;h3 id=&quot;test2&quot;&gt;test2.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;require(&quot;ns1_x.php&quot;);
require(&quot;ns2_x.php&quot;);
print get_class(new webfactory::NS1::X()) . &quot;\n&quot;;
print get_class(new webfactory::NS2::X()) . &quot;\n&quot;;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;No surpriseses here. This will print &quot;webfactory::NS1::X&quot; and &quot;webfactory::NS2::X&quot;, the fully qualified names of the classes.&lt;/p&gt;
&lt;p&gt;Prior to having namespaces, this example would have caused an error on the second line as the class name X was already taken. With namespaces, both classes can coexist and by using fully qualified names you are able to tell both apart.&lt;/p&gt;
&lt;p&gt;Now that was not all &lt;a href=&quot;http://new.petitiononline.com/mod_perl/signed.cgi?phpns&quot; shape=&quot;rect&quot;&gt;many people&lt;/a&gt; have been waiting for so long... You could always have prefixed your class names and have them called webfactory_NS1_X and webfactory_NS2_X respectively to avoid &lt;a href=&quot;http://marc.info/?l=php-internals&amp;amp;m=113288671222369&amp;amp;w=2&quot; shape=&quot;rect&quot;&gt;such kind of trouble&lt;/a&gt;. But that was often too clumsy to type and read, so many people simply ignored the problem. Namespaces to the rescue!&lt;/p&gt;
&lt;h2&gt;Using Namespaces&lt;/h2&gt;
&lt;p&gt;Namespace support also brings the new &quot;use&quot; statement. It takes the form of &quot;use A::B::C::D&quot; or &quot;use A::B::C::D as Z&quot;. If you omit the &quot;as&quot; part, the last name part will be used instead, so &quot;use A::B::C::D&quot; is equivalent to &quot;use A::B::C::D as D&quot;. The use statement may be placed anywhere in the global scope (that is, not inside classes or functions) and takes effect from that point on to the rest of the file &amp;ndash; but only in that file!&lt;/p&gt;
&lt;p&gt;Think of &quot;use&quot; as a statement to create a per-file shorthand or alias map. When writing &quot;use A::B::C::D as Z&quot;, an entry will be made for your current file that maps Z to A::B::C::D. Think of an associative array like array(&quot;Z&quot; =&amp;gt; &quot;A::B::C::D&quot;)!&lt;/p&gt;
&lt;p&gt;From that point on, whenever you use Z somewhere in your file to qualify a name, Z will be looked up in the map and A::B::C::D will be used instead, eventually adding further qualifications that followed Z.&lt;/p&gt;
&lt;p&gt;You can use that to &lt;a href=&quot;#test3&quot; shape=&quot;rect&quot;&gt;refer to classes from other namespaces&lt;/a&gt;, to &lt;a href=&quot;#test4&quot; shape=&quot;rect&quot;&gt;simply shorten qualifications&lt;/a&gt; or to &lt;a href=&quot;#test5&quot; shape=&quot;rect&quot;&gt;resolve name clashes&lt;/a&gt; at the point where you bring conflicting names together. Here are some examples for each case:&lt;/p&gt;
&lt;h3 id=&quot;test3&quot;&gt;test3.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;use webfactory::NS1::X;
require(&quot;ns1_x.php&quot;);
print get_class(new X()) . &quot;\n&quot;;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;When creating a new X instance, this will first look up &quot;X&quot; in the alias map and find &quot;webfactory::NS1::X&quot; which is the fully qualified name for the class defined in &lt;a href=&quot;#ns1x&quot; shape=&quot;rect&quot;&gt;ns1_x.php&lt;/a&gt;. Whether or not there is a namespace statement in &lt;a href=&quot;#test3&quot; shape=&quot;rect&quot;&gt;test3.php&lt;/a&gt; is of no relevance here. Cases like this one always have a fully qualified class name on the use statement.&lt;/p&gt;
&lt;p&gt;It would also not make a difference if you changed the order of the first two lines. Remember, name aliasing is independant of loading class definitions and it's not unless the third line (the &quot;new&quot; statement) that both must have been taken care of.&lt;/p&gt;
&lt;h3 id=&quot;test4&quot;&gt;test4.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;use webfactory::NS1;
use webfactory::NS2;
require(&quot;ns1_x.php&quot;);
require(&quot;ns2_x.php&quot;);
print get_class(new NS1::X()) . &quot;\n&quot;;
print get_class(new NS2::X()) . &quot;\n&quot;;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This will put two mappings into the alias table. &quot;NS1&quot; maps to &quot;webfactory::NS1&quot;, so &quot;new NS1::X&quot; is just shorthand for &quot;new webfactory::NS1::X&quot;. The same applies for NS2.&lt;/p&gt;
&lt;p&gt;If a use statement refers to a namespace name and creates an alias for it, you will always have to use an additional qualification like &quot;alias::classname&quot; to refer to a class. In the last example it was obvious that a qualification through &quot;NS1::&quot; or &quot;NS2::&quot; was necessary to make clear which class is meant.&lt;/p&gt;
&lt;p&gt;Please note that &quot;use webfactory::NS1&quot; does &lt;em&gt;not&lt;/em&gt; make all classes defined in the webfactory::NS1 namespace available. As said above, PHP has no idea of your codebase and the classes you might have defined in any given namespace. So you cannot import all classes from a given namespace with a single use statement.&lt;/p&gt;
&lt;h3 id=&quot;test5&quot;&gt;test5.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;use webfactory::NS1::X;
use webfactory::NS2::X as AnotherX;
require(&quot;ns1_x.php&quot;);
require(&quot;ns2_x.php&quot;);
print get_class(new X()) . &quot;\n&quot;;
print get_class(new AnotherX()) . &quot;\n&quot;;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is the pattern to locally resolve name clashes. Assume you need to work with two external libraries you have no control over and both define a class X you want to use. Before namespaces, you were lost. Now, both libraries hopefully will use different namespaces (webfactory::NS1 and webfactory::NS2 in this case). The use statements now declare that X is the class X from the webfactory::NS1 namespace and that AnotherX is X from webfactory::NS2. If you understood the aliasing mechanism, you're probably not much surprised. &lt;/p&gt;
&lt;p&gt;The resolution is &quot;local&quot; in that it only applies to the &lt;a href=&quot;#test5&quot; shape=&quot;rect&quot;&gt;test5.php&lt;/a&gt; file. Other files won't be affected and if you just need to use (for example) the webfactory::NS2::X class somewhere else, it is perfectly ok to just &quot;use webfactory::NS2::X&quot; and create a &quot;new X&quot; there (or simply use the fully qualified name, of course).&lt;/p&gt;
&lt;h2&gt;Clashing Aliases&lt;/h2&gt;
&lt;p&gt;When you try to put something into the alias table and the key is already given, you get a name conflict. The lookup key must be unique because otherwise when using it it would not be clear which definition is to be used. Some examples:&lt;/p&gt;
&lt;h3 id=&quot;test6&quot;&gt;test6.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;use foo::NS1;
use bar::NS1;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You will get an fatal errror &quot;Cannot use bar::NS1 as NS1 because the name is already in use&quot;. In this case the ambiguity even is in finding the NS1 namespace: &quot;NS1::X&quot; might refer to foo::NS1::X or bar::NS1::X. Similar one:&lt;/p&gt;
&lt;h3 id=&quot;test7&quot;&gt;test7.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;use foo::NS1::X;
use bar::NS2::X;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In this case, X refers to a class but it is unclear to which one. Remember, using namespaces has nothing to do with loading class definitions. You could require() both files that define X in the foo::NS1 and bar::NS1 namespaces and it would be no problem at all because both definitions differ in their fully qualified names. It's the use statement itself that creates the conflict as both statements want to use the same key in the alias map. In &lt;a href=&quot;#test6&quot; shape=&quot;rect&quot;&gt;test6.php&lt;/a&gt; and &lt;a href=&quot;test7&quot; shape=&quot;rect&quot;&gt;test7.php&lt;/a&gt;, I do not even require the class definitions and the alias map is never looked at for name resolutions.&lt;/p&gt;
&lt;h2 id=&quot;extra-rule&quot;&gt;Names in Namespaces&lt;/h2&gt;
&lt;p&gt;Now here comes an extra rule. Maybe it is not what really happens under the hood, but the explanation closely matches what can be observed.&lt;/p&gt;
&lt;p&gt;When you put a &quot;namespace A::B&quot; statement on top of your file and define a name Z in it (remember my &lt;a href=&quot;#defining-class-names&quot; shape=&quot;rect&quot;&gt;definition&lt;/a&gt; of &quot;defining&quot; from above), an alias &quot;Z&quot; for &quot;A::B::Z&quot; will be put into your file-local alias table. That allows you to use the new name right away &amp;ndash; and that is how my example &lt;a href=&quot;#test1&quot; shape=&quot;rect&quot;&gt;test1.php&lt;/a&gt; way up worked: By defining class X in namespace webfactory::NS1, we implicitly ended up with a X-to-webfactory::NS1::X mapping in that file.&lt;/p&gt;
&lt;p&gt;Together with the preceding section, you should understand that the following will cause a fatal error on the third line because the &quot;extra rule&quot; tries to add an alias for a name that is taken.&lt;/p&gt;
&lt;h3 id=&quot;test8&quot;&gt;test8.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;namespace webfactory::NS1;
use webfactory::NS2::X;
class X {}
&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;The Edge Cases&lt;/h2&gt;
&lt;p&gt;Re-read the extra rule and take it to the limits: The alias is made up when you define a name and it is put into the alias table for the file the definition takes place in. So what happens when the definition is sourced out to another file? Consider:&lt;/p&gt;
&lt;h3 id=&quot;test9&quot;&gt;test9.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;namespace webfactory::NS1;
require(&quot;ns1_x.php&quot;);
print get_class(new X()) . &quot;\n&quot;;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For the &lt;a href=&quot;#ns1x&quot; shape=&quot;rect&quot;&gt;ns1_x.php&lt;/a&gt; file, the extra rule will create an alias. But as the alias table is per-file, in &lt;a href=&quot;#test9&quot; shape=&quot;rect&quot;&gt;test9.php&lt;/a&gt; there is no X entry.&lt;/p&gt;
&lt;p&gt;Now what happens when a new X is created? Blurring the difference between defining a class and requiring() the definition, the following extra-extra rule kicks in:&lt;/p&gt;
&lt;p id=&quot;extra-extra-rule&quot;&gt;First, the engine checks if X is a known alias &amp;ndash; here it isn't. It then considers X as part of the current namespace. That is, it checks if a class with the fully qualified name &quot;webfactory::NS1::X&quot; has been defined somewhere. This time, it will find and use the definition from &lt;a href=&quot;#ns1x&quot; shape=&quot;rect&quot;&gt;ns1_x.php&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;A Kind Of Magic*&lt;/h2&gt;
&lt;p&gt;I hope that the following will be a pathological case in practice, but the result may be surprising enough to be documented.&lt;/p&gt;
&lt;h3 id=&quot;test10&quot;&gt;test10.php&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;php&quot;&gt;namespace webfactory::NS1;
use webfactory::NS2::X;
require(&quot;ns1_x.php&quot;);
require(&quot;ns2_x.php&quot;);
print get_class(new X()) . &quot;\n&quot;;
print get_class(new webfactory::NS1::X()) . &quot;\n&quot;;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is basically the same as &lt;a href=&quot;#test9&quot; shape=&quot;rect&quot;&gt;test9.php&lt;/a&gt;, with one subtle difference. This time we &quot;use webfactory::NS2::X&quot; to make up an alias table entry for X. In this case, the &lt;a href=&quot;#extra-extra-rule&quot; shape=&quot;rect&quot;&gt;extra-extra rule&lt;/a&gt; does not trigger and you will get &quot;webfactory::NS2::X&quot; for the first print. Creating aliases with &quot;use&quot; takes precedence over using names from the same namespace when these are defined in another file.&lt;/p&gt;
&lt;p&gt;If you had written &quot;class X {}&quot; instead of require(&quot;ns1_x.php&quot;) &amp;ndash; and &lt;a href=&quot;ns1x&quot; shape=&quot;rect&quot;&gt;ns1_x.php&lt;/a&gt; does no more than that in the same namespace as &lt;a href=&quot;#test10&quot; shape=&quot;rect&quot;&gt;test10.php&lt;/a&gt; &amp;ndash; you'd get a fatal error because then the extra-rule would try to create the alias for X and finds that name taken by webfactory::NS2::X.&lt;/p&gt;
&lt;h2&gt;Final Remarks&lt;/h2&gt;
&lt;p&gt;When you got used to using __autoload() or the SPL equivalents to load in your class definitions, regardless of the namespaces defined or used in your files you will be passed the fully qualified names of the classes you need to load. For all the examples I provided here that is always what get_class() returned. If you omitted the require() calls from &lt;a href=&quot;#test10&quot; shape=&quot;rect&quot;&gt;test10.php&lt;/a&gt; and had set up an __autoload handler instead, it would have been called for webfactory::NS2::X and webfactory::NS1::X on the first and second print line, respectively.&lt;/p&gt;
&lt;p&gt;When using variable class names as in &quot;$foo = new $bar()&quot;, where $bar holds the name of the class you want, name resolution rules don't apply so you will have to work with fully qualified names. &lt;a href=&quot;http://php100.wordpress.com/2007/07/05/namespaces-can-we-keep-it-simple/&quot; shape=&quot;rect&quot;&gt;Stanislav Malyshev is unsure&lt;/a&gt; if that is a shortcoming. (A short sidenote on this pattern: Interestingly, your __autoload() handler will be passed the value of $bar, no matter if it's a syntactically valid class name. That might be an interesting remote code inclusion vector if your handler implementation is too naïve &amp;gt;:-)).&lt;/p&gt;
&lt;p&gt;Although I always used the &quot;new&quot; operator for demonstration purposes in this article, the same rules for resolving names apply in other cases where you refer to class names &amp;ndash; think of type hints in method signatures, for example. The serialize() function will use the fully qualified class name as well to allow for correct de-serialization later on.&lt;/p&gt;
&lt;p&gt;I hope this article helped you to understand how or why things work as they work. If you found it helpful or have any remarks, I'd be glad if you leave a comment.&lt;/p&gt;
&lt;h2&gt;Update 2007-12-06&lt;/h2&gt;
&lt;p&gt;Currently, there's a lot of &lt;a href=&quot;http://news.php.net/php.internals/33694&quot; shape=&quot;rect&quot;&gt;discussion on the PHP Internals Mailing List&lt;/a&gt; about wheter or not the current namespace implementation makes sense and solves the problems people have in practice or if it would be wise not to ship it at all. So before you start updating your codebase, relax and wait how things evolve - you still have plenty of time before PHP 5.3 will be available and used at a large scale. At last, the &lt;a href=&quot;http://www.php.net/manual/en/language.namespaces.php&quot; shape=&quot;rect&quot;&gt;first official documentation&lt;/a&gt; is available.&lt;/p&gt;
&lt;p&gt;(* Courtesy of Queen, 1986)&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/php-namespaces-explained.html</guid>
	  <pubDate>Sat, 17 Nov 2007 00:00:00 +0100</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>Dokumentenmanagement in einem Tag</title>
	  <link>http://inside.webfactory.de/en/blog/dokumentenmanagement-in-einem-tag.html</link>
	  <description>&lt;p&gt;Nach 10 Jahren hatten wir genug von der Papierflut. Jede Eingangsrechnung kopieren und in verschiedene Ordner sortieren, das gleiche mit Ausgangsrechnungen. Umlaufmappen, Kürzel, Chaos auf dem Schreibtisch. Das muss doch besser gehen, dachten wir uns.&lt;/p&gt;&lt;p&gt;Zunächst war klar: Ein Scanner muss her. Denn Post kommt ja nach wie vor auf Papier. Nach kurzer Recherche in der c’t stießen wir auf den Canon ScanFront 220. Ein Standalone-Gerät mit integriertem Touch-Screen, das auf Knopfdruck Scans gemäß vordefinierten Jobs über Netzwerk als E-Mail verschicken oder auf FTP- oder SMB-Ordnern ablegen kann – als durchsuchbare PDF-Datei.&lt;/p&gt;&lt;p&gt;Und plötzlich kam die Erkenntnis: Wir haben eigentlich alles, was wir brauchen, um loszulegen. Ein bisschen Risiko war dabei, denn der Scanner kostet an die 2000 €. Doch die Aussicht war einfach zu verlockend.&lt;/p&gt;&lt;p&gt;Der Plan: Der Scanner steht da, wo die Post ankommt. Jedes Dokument wird sofort gescannt und in einen FTP-Ordner auf einem Linux-Server abgelegt. Dort findet ein Cronjob die PDF-Datei, verschiebt sie ins Archiv und legt einen Eintrag in einer Datenbank an. In diesem Eintrag werden alle Meta- und Verarbeitungsinformationen zum Dokument abgelegt. Das Papierdokument kann sofort in einem Schuhkarton für den Aktenkeller abgelegt werden, denn es wird nicht mehr benötigt.&lt;/p&gt;&lt;p&gt;Für die weitere Verarbeitung des elektronischen Vorgangs in der Datenbank setzen wir wfDynamic ein. Es kann von Haus aus mit unterschiedlichen Typen von Datensätzen umgehen (Multi Table Inheritance). Werden zu einem Basisdokument z. B. im Wesentlichen das Datum des Dokuments, der Scanzeitpunkt, eine Bezeichnung und die Zuordnung zu einem Absender/Empfänger (Kunden, Lieferanten, Behörde, …) gespeichert, so enthält eine Eingangsrechnung zusätzlich die Rechnungsnummer, den Rechnungsbetrag und Angaben zur Buchungsart (kreditorisch, Kasse, Kreditkarte).&lt;/p&gt;&lt;p&gt;Spätestens an dieser Stelle fing es an, Spaß zu machen. Wir haben bereits den Absender der Rechnung, das Datum, einen Beschreibungstext, den Betrag erfasst – was läge näher, als diese Angaben direkt in der Buchhaltung weiterzuverwenden? Die Adressen, zu denen wir die Dokumente zuordnen, stammen direkt aus unserer Buchhaltungssoftware. Wir kennen also zur Adresse auch das Kreditorenkonto. Nichts einfacher, als alle Daten in eine CSV-Datei zu packen und in die Buchhaltung (in unserem Falle Lexware Professional) zu importieren…&lt;/p&gt;&lt;p&gt;Es ist 21:30 Uhr. Um 11 Uhr morgens ist der Scanner gekommen. Der erste Stapel Eingangsrechnungen hat seinen Weg vom Scanner über die wfDynamic-Datenbank in die Buchhaltung gemacht und ist dort erfolgreich verbucht worden. Morgen müssen erstmal wieder die Kunden bedient werden – aber die Lösung ist bereits funktionsfähig und im produktiven Einsatz.&lt;/p&gt;&lt;p&gt;Jetzt werden wir Erfahrungen sammeln – und dann an dieser Stelle wieder darüber berichten.&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/dokumentenmanagement-in-einem-tag.html</guid>
	  <pubDate>Thu, 08 Nov 2007 00:00:00 +0100</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>What 64 bits can do for you</title>
	  <link>http://inside.webfactory.de/en/blog/what-64-bit-can-do-for-you.html</link>
	  <description>&lt;p&gt;Recently we bought a &lt;a href=&quot;http://www.dell.com/content/products/featuresdetails.aspx/pedge_2950?c=us&amp;amp;cs=04&amp;amp;l=en&amp;amp;s=bsd&amp;amp;~lt=popup&quot; shape=&quot;rect&quot;&gt;DELL PowerEdge 2950&lt;/a&gt; and meanwhile deployed it for our &lt;a href=&quot;http://www.webfactory.de/de/leistungen/webhosting/&quot; shape=&quot;rect&quot;&gt;web hosting service&lt;/a&gt;. We installed &lt;a href=&quot;http://www.debian.org/releases/stable/&quot; shape=&quot;rect&quot;&gt;Debian Etch&lt;/a&gt;, the first Debian release that &lt;a href=&quot;http://www.debian.org/ports/amd64/index.de.html&quot; shape=&quot;rect&quot;&gt;officially and fully supports AMD64&lt;/a&gt;. So we &lt;span class=&quot;strike&quot;&gt;had to decide&lt;/span&gt; were able to choose between installing a 32 or 64-bit version of our favourite OS. Now what is that decision about?&lt;/p&gt;&lt;h2&gt;Intel vs. AMD &lt;/h2&gt;&lt;p&gt;As you might know, already a few years ago Intel tried (with the help of Hewlett Packard) to develop a new &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/IA64&quot; shape=&quot;rect&quot;&gt;Intel 64-bit Architecture&lt;/a&gt;&quot; (IA64), specifically for their customers asking for more computation power and more memory. However, the problem with IA64 is that it is incompatible with the &quot;traditional&quot; architecture and instruction set known as &lt;a href=&quot;http://en.wikipedia.org/wiki/X86&quot; shape=&quot;rect&quot;&gt;x86&lt;/a&gt;, requiring vast changes to make operating systems, compilers and applications work with it. Maybe not surprisingly, IA64 never gained the importance Intel hoped. &lt;/p&gt;&lt;p&gt;AMD, on the other hand, carefully chose to extend the established x86 architecture to make it 64-bit capable. They made registers 64-bit wide, added a few more of them to the processor and came up with some new CPU instructions to leverage 64-bit computation operations. Contrary to IA64, this architecture named &lt;a href=&quot;http://en.wikipedia.org/wiki/AMD64&quot; shape=&quot;rect&quot;&gt;AMD64&lt;/a&gt; still supports the x86 instruction set which basically means that it is capable of falling back into 32-bit mode and run &quot;old&quot; code without modifications. AMD64 was rewarded with a lot of acceptance in the market Intel aimed at and eventually Intel chose to license some of AMD's ideas. Now more recent Xeon processors are &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Em64t&quot; shape=&quot;rect&quot;&gt;EM64T&lt;/a&gt;&quot; capable where EM64T is the &quot;extended memory 64-bit technology&quot; which basically is Intel's name for the same thing.&lt;/p&gt;&lt;p&gt;If you're unsure whether your machine supports EM64T, &lt;code&gt;cat /proc/cpuinfo&lt;/code&gt; and look for the &quot;lm&quot; flag. Now what difference does that all make?&lt;/p&gt;&lt;h2&gt;64 &amp;gt; 2 * 32 ?&lt;/h2&gt;&lt;p&gt;Switching to a 64-bit OS doesn't magically make your applications faster. Most probably you will benefit if you're doing complex numerical calculations or simulations and your software is capable of (has been optimized for) using the 64-bit instructions, allowing it to calculate or transport &quot;more&quot; data per CPU cycle.&lt;/p&gt;&lt;p&gt;Often the more interesting aspect of running a 64-bit OS is address space. With 32-bit registers, you can only store 2&lt;sup&gt;32&lt;/sup&gt; distinct values. If these values are memory addresses, you will end up with a 4 GB address space a single process can use. Once upon a time, &quot;&lt;a href=&quot;http://www.wired.com/politics/law/news/1997/01/1484&quot; shape=&quot;rect&quot;&gt;640 k ought to be enough for anyone&lt;/a&gt;&quot;, but nowadays, especially with large databases you want to be able to access more than 4GB of memory — mainly to cache data in memory instead of reading it from disk when needed. So 64-bit is a good thing, right?&lt;/p&gt;&lt;h2&gt;But...&lt;/h2&gt;&lt;p&gt;Now here's the &quot;but&quot;: There are some details that should not hinder you from switching over to 64-bit, but you can save yourself (or your &lt;a href=&quot;http://www.sysadminday.com/&quot; shape=&quot;rect&quot;&gt;overworked sysadmin&lt;/a&gt;) some time and headaches if you consider them first. As you will see, these are merely practical aspects that will vanish as 64-bit systems are getting more and more commonplace. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;An application must (of course) be compiled for 64-bit to make use of it. The same holds for all the libraries your application depends upon - when the app is 64-bit, the lib must be it as well. Now that may be a problem if either of them is not available for the AMD64 platform, maybe because it's closed-source or a vendor-provided device driver that has not yet been 64-bit-proofed.&lt;/p&gt;&lt;p&gt;Debian provides x86 and amd64 versions of a package and puts 64-bit libraries into /lib64 which /lib is a symlink to.&lt;/p&gt;&lt;p&gt;Now when you've got a 32-bit application binary, you can run it on an amd64 arch system (Surprised? Scroll up!) as long as you got the 32-bit versions of all the libraries it depends on installed as well. On Debian, you can install the &lt;a href=&quot;http://packages.debian.org/etch/ia32-libs&quot; shape=&quot;rect&quot;&gt;ia32-libs package&lt;/a&gt; that contains 32-bit versions of some often-used libraries. The dynamic loader will figure out that you're trying to run a 32-bit application and load the libraries from /lib32 which is a symlink to /emul/ia32-linux.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.debian-administration.org/articles/531&quot; shape=&quot;rect&quot;&gt;Trouble starts&lt;/a&gt; when you need to install the 32-bit version of a certain Debian package on an amd64 arch system or even need to add 32-bit versions of some libraries yourself. At that point you're pretty much lost because all that will no longer work under the control of the APT package management system, so you will have to care for dependencies and upgrade tracking yourself.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The other way round, 64-bit binaries do not work on 32-bit (x86) systems. So what?! Why am I telling this?&lt;/p&gt;&lt;p&gt;Maybe you have been using Debian long enough so you learned that the versions of software packages you &quot;officially&quot; get are somewhat... err... older. Debian &quot;stable&quot; means stability in version numbers, not stability through most recent versions. And basically, this is a good thing because you don't really want to change library versions too often on a production system as every such change brings the risk of regressions in behaviour.&lt;/p&gt;&lt;p&gt;However, in the past we had a few situations where we absolutely needed to get a certain bug fixed in the libc, libxml2, MySQL or just had to &lt;a href=&quot;http://www.php.net/releases/&quot; shape=&quot;rect&quot;&gt;keep up with the current PHP&lt;/a&gt; versions. So we started to maintain some variants of the Debian packages ourselves and set up a server to deploy these variants to all our machines leveraging the APT package system. (Maybe interesting enough for another article?) Now running amd64 on some machines means having to build all these packages twice, once on x86 and once on amd64 (did anyone say &quot;cross-compile&quot;?) and manage both architectures in our package repository — quite some extra work.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It may be that application developers made assumptions about the size of some structures (pointers or ints) that held true on the x86 platform but are wrong in the general case. That may lead to bugs that suddenly surface in applications and libraries you have been using for a long time without problems on x86. Sara Golemon told such stories at the &lt;a href=&quot;http://flickr.com/photos/tags/internationalphpconference2006/&quot; shape=&quot;rect&quot;&gt;PHP conference 2006&lt;/a&gt; code camp: It was a single wrong data type declaration in the PHP innards that caused days of tracing and debugging when they moved some apps to 64-bit at &lt;a href=&quot;http://www.yahoo.com&quot; shape=&quot;rect&quot;&gt;Yahoo!&lt;/a&gt;&lt;/p&gt;&lt;p&gt;It may take some time for applications to become as mature as they are on x86, so keep this in mind.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;64-bit applications tend to be somewhat larger and have a bigger memory footprint, especially because pointers are larger (finally, this is what it's all about :-)). While size on disk should not really be an issue, the in-memory size may adversely affect the efficiency of your precious level-2 cache.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Clearly, the future will belong to 64-bit systems. But it's up to you to decide whether you want to start the transition right now — operating systems support it — or still wait a little. Before you step up, be aware of the differences and the problems you might get.&lt;/p&gt;&lt;p&gt;Especially, save yourself some grief and don't change just for sake of change. Find out what your applications need — are you number-crunching or just serving files? Can you leverage 64-bit power? Need much more memory per process?&lt;/p&gt;&lt;p&gt;If you are unsure about it, the best thing you can do is go and figure it out! We took ourselves the time and tried various options, conducting a lot of IO- and especially MySQL benchmarks. But benchmarking is a complex matter that deserves an article on its own — hopefully coming up soon on this website.&lt;/p&gt;&lt;p&gt;So what did we finally choose and does it work for us? See yourself:&lt;/p&gt;&lt;p&gt;&lt;code&gt;mp:~$ uname -r ; uptime&lt;br /&gt;2.6.18-4-amd64&lt;br /&gt; 19:35:07 up 72 days, 7:37, 1 user, load average: 0.06, 0.08, 0.08&lt;/code&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/what-64-bit-can-do-for-you.html</guid>
	  <pubDate>Fri, 28 Sep 2007 00:00:00 +0200</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>The End is The Beginning is The End*</title>
	  <link>http://inside.webfactory.de/en/blog/the-end-is-the-beginning-is-the-end.html</link>
	  <description>&lt;p&gt;Web design has come a long way. We strive to play the game in adherence to &lt;a href=&quot;http://webstandards.org/&quot; title=&quot;The Web Standards Project&quot; shape=&quot;rect&quot;&gt;Standards&lt;/a&gt;, we &lt;a href=&quot;http://www.alistapart.com/articles/separationdilemma&quot; title=&quot;&amp;quot;Separation: The Web Designer’s Dilemma&amp;quot; on A List Apart&quot; shape=&quot;rect&quot;&gt;separate structure from presentation&lt;/a&gt; as much as possible and we have taken into our hearts the fact that indeed the &lt;a href=&quot;http://www.core77.com/reactor/06.07_merholz.asp&quot; title=&quot;&amp;quot;Experience IS the Product... and the only thing users care about&amp;quot; by Peter Merholz&quot; shape=&quot;rect&quot;&gt;Experience is the Product&lt;/a&gt;. Or have we?&lt;/p&gt;&lt;p&gt;A core ambition of website designers is to keep visitors on a site, get them to consume the content and perhaps even interact with it. Why then are users still left to themselves after they have done what should bring joy to every site owner: after they have read all of the content? Too often they are fobbed off with just a copyright info, a legal notice or a claim to W3C validity at the end of the page. They are met with bland place holders where they should in fact be rewarded for their effort. &lt;/p&gt;&lt;p&gt;Let us imagine a user that has just devoured all of the beautifully laid out information on a page. He is a most wanted user: he made the effort to scroll down all the way. He might have gotten engaged in an interesting train of thought, or become convinced of a certain product’s advantages – in any case, he is entertained, even excited to a point. Now the user has arrived at the bottom of the page and is looking for more to read, to absorb, to engage with. Ideally, we would want him to stay and navigate to another part of the website. Ideally, he would find recommendations where to go next. Unfortunately for both of us, he is usually faced with nothing helpful and left to himself.&lt;/p&gt;&lt;p&gt;Footers are in serious need of some love. We have to pay more attention to what is going on (literally) “down under”. Just like Europeans acknowledge the existence of Australia but rarely know what is going on there at any given time, footers still are a bit of a hazy area in web design.&lt;/p&gt;&lt;h2&gt;Carpe Pedem&lt;/h2&gt;&lt;p&gt;What are possible solutions then? To be honest, we (as designers) are only bound by our imagination. That is the beauty of it: once footers are understood not as a point of probable departure but as a point of pending decision, the possibilities are endless, as long as they stay in line with the context of the website.&lt;/p&gt;&lt;p&gt;One of the most common uses of the footer area is the placement of a feedback form. Gaining immediate feedback can be immensely valuable, and is most famously used in blogs. Bloggers have almost unanimously included comments at the bottom of every article, but news and corporate sites also are slowly beginning to embrace this opportunity for user feedback.&lt;/p&gt;&lt;p&gt;Other pages, like &lt;a href=&quot;http://last.fm&quot; shape=&quot;rect&quot;&gt;last.fm&lt;/a&gt; or &lt;a href=&quot;http://skype.com&quot; shape=&quot;rect&quot;&gt;skype.com&lt;/a&gt; put almost their complete navigation or sitemaps beneath the content area. Whereas this certainly offers the user ideas about where to go next, the sheer amount of options may cause the opposite effect of what is intended.&lt;/p&gt;&lt;p&gt;E-commerce pages may want to display related products to the one described on the respective page (a feature promoted by &lt;a href=&quot;http://amazon.com&quot; shape=&quot;rect&quot;&gt;Amazon&lt;/a&gt;, for example), a link to an order tracking form or to their support area, and possibly customer reviews.&lt;/p&gt;&lt;p&gt;A company providing services might offer links to other services than the one highlighted on the page and showcase excerpts of their portfolio to complement the description of their work.&lt;/p&gt;&lt;p&gt;Footers could also include links to partner organisations, contact information, promotional elements, recent news – again, there are endless possibilities.&lt;/p&gt;&lt;p&gt;Just as long as we comprehend our footers’ potential as beginnings instead of mere endings.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;(* Courtesy of Smashing Pumpkins, 1997)&lt;/p&gt;&lt;h2&gt;References and Further Reading&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;http://www.nixonmcinnes.co.uk/about-us/blog/document-149-30.php&quot; shape=&quot;rect&quot;&gt;&quot;WEB 2.0 Footers - How to keep people’s flow&quot;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://tutorialblog.org/web-design-elements-footers/&quot; shape=&quot;rect&quot;&gt;&quot;Web Design Elements : Footers&quot;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://www.boxesandarrows.com/view/blasting-the-myth-of&quot; shape=&quot;rect&quot;&gt;&quot;Blasting the Myth of the Fold&quot;&lt;/a&gt;&lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/the-end-is-the-beginning-is-the-end.html</guid>
	  <pubDate>Thu, 27 Sep 2007 00:00:00 +0200</pubDate>
	  <source></source>
	</item>

	<item>
	  <title>Meeting Alistair Cockburn: The Secret of Effective Teams</title>
	  <link>http://inside.webfactory.de/en/blog/alistair-cockburn-the-secret-of-effective-teams.html</link>
	  <description>&lt;p&gt;Alistair Cockburn is a well-known author and consultant on software methodology. I was particularly impressed by his books &lt;em&gt;Surviving Object Oriented Projects&lt;/em&gt; and &lt;em&gt;Agile Software Development&lt;/em&gt;. Recently, Alistair gave a workshop in Bonn titled “The Secret of Effective Teams – Agility, Discipline, Focus”, so three of webfactory (Per, Matthias and Sebastian) took the chance to meet him and learn about his newest insights.&lt;/p&gt;&lt;p&gt;Alistair started the day with a talk summarizing some of the most important ideas (in my opinion) from his book &lt;em&gt;Agile Software Development&lt;/em&gt;, such as&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Three stages of learning a skill (Shu-ha-ri), one of my favourites&lt;/li&gt;&lt;li&gt;The cooperative game, swamp game example&lt;/li&gt;&lt;li&gt;Programming as theory building – great paper by Peter Naur (1986), reprinted in the Agile Software Development book&lt;/li&gt;&lt;li&gt;The role of the project manager&lt;/li&gt;&lt;li&gt;Agility and discipline&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This part of the day was a nice, relaxed refresh of what I had already learned from the book. Nothing really new so far, but still the ideas are very good and the book is my strong recommendation.&lt;/p&gt;&lt;p&gt;The rest of the day was made up of group assignments. We did the “draw a drawing” communication game (one group has to draw a drawing based on textual instructions from the other group) in an agile version, meaning that there were three drawing rounds with reflection sessions after each round on how to do better next time. Alistair put a special emphasis on “cheating legally”, which means breaking assumed rules (as opposed to real rules) to improve project success. In fact, most of the improvement between the drawing sessions resulted from breaking assumed rules. Also the reflection workshops proved to be an important technique for success, which inspired us to do more of them in upcoming projects. In fact, reflection workshops are a technique we already used at webfactory for past projects, but not as regularly and often as we could have.&lt;/p&gt;&lt;p&gt;There were two more group assignments related to project management (Information Radiators, tracking project process)  and concurrent development in the mid afternoon, and a “goldfish bowl” discussion at the end. Goldfish bowl meant there were a maximum of 5 persons discussing at a time, and the rest of the participants listening. Everyone wanting to join the discussion could take the place of one of the people discussing. The goldfish bowl discussion was there on special request of the workshop organizer, as Alistair stressed, and in fact neither he nor the participants had a good idea of what to use this discussion for. So we tried our best finding topics to discuss, but nonetheless the discussion was at no time really vivid. It ended with Alistair and two of webfactory, Per and Matthias, sitting on the discussion chairs, my colleagues trying to get Alistair to talk about agility topics.&lt;/p&gt;&lt;p&gt;To summarize the day: The morning was quite interesting and energetic. Maybe because of the lenghty three-course lunch, the workshop somehow lost drive in the afternoon. Especially after the drawing sessions, one game/group assignment seemed to follow the other and the workshop speeded up noticeably due to the fact that weekend was approaching.&lt;/p&gt;&lt;p&gt;After all, what did we get out of this workshop? Most importantly, the reassuring feeling that we’re on the right track with our approaches to agile software development here at webfactory. It was particularly great to learn that agile development and fixed-price contracts are not only compatible with each other, but that Alistair is even convinced that fixed-price contracts are the only reasonable contract model for software development and – the other way round – that agile development is the best way to cope with fixed-price contracts with tight budgets. This is the opposite of what most speakers on the OOP 2007 conference in January argued for. To us, it seems to be a more realistic view of project reality and encourages us to continue working the way we have always worked. &lt;/p&gt;</description>
	  <author>webfactory GmbH</author>
	  <category></category>
	  <comments></comments>
	  <guid>http://inside.webfactory.de/en/blog/alistair-cockburn-the-secret-of-effective-teams.html</guid>
	  <pubDate>Sat, 08 Sep 2007 00:00:00 +0200</pubDate>
	  <source></source>
	</item>

  </channel>
</rss>
