<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-23170963</id><updated>2011-08-17T05:04:36.094+02:00</updated><category term='Python'/><category term='Sensei'/><category term='Information Management'/><category term='Lucene'/><category term='JSP'/><category term='admin'/><category term='C'/><category term='RAID'/><category term='Heroes'/><category term='Review'/><category term='Hibernate'/><category term='Semantic Web'/><category term='AJAX'/><category term='Philosophy'/><category term='UI'/><category term='jads'/><category term='ePen'/><category term='Palm'/><category term='Tutorial'/><category term='TV Show'/><category term='Security'/><category term='Movie'/><category term='OSS'/><category term='Testing'/><category term='Swing'/><category term='3ware'/><category term='jMaki'/><category term='TurboGears'/><category term='Jazoon'/><category term='TDD'/><category term='GIT'/><category term='Blender'/><category term='MQSeries'/><category term='JCR'/><category term='Writing'/><category term='Humor'/><category term='Documentation'/><category term='JUnit'/><category term='Traits'/><category term='SciFi'/><category term='Violence'/><category term='Good Bye'/><category term='Gaming'/><category term='Modelling'/><category term='Neuro-Science'/><category term='Project Management'/><category term='Copyright'/><category term='CSS'/><category term='Generative Art'/><category term='Surveillance'/><category term='Version Control'/><category term='Software Development'/><category term='Teleportation'/><category term='SharePoint'/><category term='Maven2'/><category term='Comics'/><category term='XML'/><category term='Climate'/><category term='Quantum Physics'/><category term='Vuze'/><category term='Java'/><category term='Fun'/><category term='DecentXML'/><category term='Groovy'/><category term='Tool'/><category term='Reflection'/><category term='Mockup'/><category term='PovRay'/><category term='Firefox'/><category term='TAURUS'/><category term='Amiga'/><category term='VMware'/><category term='Published Story'/><category term='Linux'/><category term='upcscan'/><category term='Eclipse'/><category term='HTML'/><category term='Qt'/><category term='Hardware'/><category term='IE'/><category term='PyQt4'/><category term='Recommendation'/><category term='Agile Development'/><category term='JavaScript'/><category term='PC Building'/><category term='Education'/><category term='Text Editor'/><category term='Axis2'/><category term='BIRT'/><title type='text'>Dark Views</title><subtitle type='html'>This blog has moved to http://blog.pdark.de/</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default?start-index=101&amp;max-results=100'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>175</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-23170963.post-1991074946798096785</id><published>2009-02-25T11:24:00.000+01:00</published><updated>2009-02-25T11:25:12.051+01:00</updated><title type='text'>Goodbye</title><content type='html'>I've moved. You can find my new blog under &lt;a href="http://blog.pdark.de/"&gt;http://blog.pdark.de/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1991074946798096785?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1991074946798096785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1991074946798096785' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1991074946798096785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1991074946798096785'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/02/goodbye.html' title='Goodbye'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-161277655106117119</id><published>2009-02-17T21:48:00.003+01:00</published><updated>2009-02-17T21:50:23.710+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Good Bye'/><title type='text'>I'm Moving</title><content type='html'>Blogger was nice for the time being. It's a simple interface, easy to use but ... well ... I need a bit more. I'd especially like to know if anyone is ever reading my blog. So I'm moving my blog over to WordPress. They have a nice dashboard with daily access figures.

I'll post the new URL here as soon as the move is completed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-161277655106117119?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/161277655106117119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=161277655106117119' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/161277655106117119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/161277655106117119'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/02/im-moving.html' title='I&apos;m Moving'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5835552575659448395</id><published>2009-01-30T10:32:00.002+01:00</published><updated>2009-01-30T10:36:05.513+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>A Different View on Exceptions</title><content type='html'>&lt;p&gt;The discussion about checked/unchecked exceptions is almost as old as Java. While we all have a point in your stance towards this, maybe we are looking at the problem from the wrong angle. Manuel Woelker wrote an article which concentrates on the receiver of the exception, the user, and how exceptions should behave to help the user: &lt;a href="http://eclipsesource.com/blogs/2009/01/29/exceptions-from-a-users- perspective/"&gt;Exceptions From a User’s Perspective&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5835552575659448395?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5835552575659448395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5835552575659448395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5835552575659448395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5835552575659448395'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/01/different-view-on-exceptions.html' title='A Different View on Exceptions'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5126321394754779424</id><published>2009-01-28T10:15:00.001+01:00</published><updated>2009-01-28T10:19:43.291+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><title type='text'>How to Hide a Virus in Source Code</title><content type='html'>&lt;p&gt;I've been looking for quite some time for this article: How can you hide a virus in the source code? Basically, you create a binary of a compiler which contains the virus and which is patched to infect other programs as it compiles them.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://cm.bell-labs.com/who/ken/trust.html"&gt;Reflections on Trusting Trust&lt;/a&gt; by Ken Thompson.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5126321394754779424?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5126321394754779424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5126321394754779424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5126321394754779424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5126321394754779424'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/01/how-to-hide-virus-in-source-code.html' title='How to Hide a Virus in Source Code'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-8289690583979604044</id><published>2009-01-27T15:53:00.000+01:00</published><updated>2009-01-27T15:54:16.529+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>One Word: Cute</title><content type='html'>&lt;p&gt;&lt;a href="http://lostgarden.com/2007/05/dancs-miraculously-flexible-game.html"&gt;Danc's Miraculously Flexible Game Prototyping Tiles&lt;/a&gt; Enjoy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-8289690583979604044?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/8289690583979604044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=8289690583979604044' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8289690583979604044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8289690583979604044'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/01/one-word-cute.html' title='One Word: Cute'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-857827801784512007</id><published>2009-01-23T14:16:00.001+01:00</published><updated>2009-01-23T14:17:30.142+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>Another Lesson on Performance</title><content type='html'>&lt;p&gt;Just another story you can tell someone who fears that "XYZ might be too slow":&lt;/p&gt;

&lt;p&gt;I'm toying with the idea to write a new text editor. I mean, I've written &lt;a href="http://www.aros.org/"&gt;my own OS&lt;/a&gt;, my own &lt;a href="http://code.google.com/p/decentxml/"&gt;XML parser&lt;/a&gt; and I once maintained XDME, an editor written originally by Matthew Dillon. XDME has a couple of bugs and major design flaws that I always wanted to fix but never really got to it. Anyway.&lt;/p&gt;

&lt;p&gt;So what is the best data structure for a text editor in 2008? List of lines? Gap-Buffer? Multi-Gap-Buffer?&lt;/p&gt;

&lt;p&gt;XDME would keep the text in a list of lines and each line would point to a character array with the actual data. When editing, the characters would be copied into an edit buffer, the changes made and after the edit, the changed characters would be copied back, allocation a new character array if necessary.&lt;/p&gt;

&lt;p&gt;This worked, it was a simple design but it had a flaw: it didn't scale. The length of a line was limited to the max size of the edit buffer and loading a huge file took ages because each line was read, analyzed, memory was allocated ... you get the idea.&lt;/p&gt;

&lt;p&gt;So I wanted to make it better. Much better. I'd start with reading the file into a big buffer, chopped into evenly sized chunks to make reading both fast and memory efficient (imagine loading a 46MB file into a single memory chunk - after a couple of changes, I'd need to allocate a second 46MB chunk, copy the whole stuff over, etc, needing twice the amount of RAM for a short time).&lt;/p&gt;

&lt;p&gt;During the weekend, I mulled the various ideas over, planned, started with a complex red-black tree structure for markers (positions in the text that move when you insert before them). It's huge, complex. It screams "wrong way!"&lt;/p&gt;

&lt;p&gt;So today, I sat back and did what I should have done first: Get some figures. How much does it really cost to copy 4MB of RAM? Make a guess. Here is the code to check:&lt;/p&gt;

&lt;pre&gt;    public static void main (String[] args)
    {
        long start = System.currentTimeMillis ();
        
        int N = 10000;
        for (int i=0; i&amp;lt;N; i++)
        {
            int[] buffer = new int[1024*1024];
            System.arraycopy (buffer, 0, buffer, 1, buffer.length-1);
        }
        
        long duration = System.currentTimeMillis () - start;
        System.out.println (duration);
        System.out.println (duration / N);
    }&lt;/pre&gt;

&lt;p&gt;On my machine, this prints "135223" and "13". That's &lt;b&gt;thirteen milliseconds&lt;/b&gt; to copy 4MB of RAM. Okay. It's obviously not worth to spend a second to think about the cost of moving data around in a big block of bytes.&lt;/p&gt;

&lt;p&gt;That leaves the memory issue. I would really like to be able to load and edit a 40MB file in a VM which has 64MB heap. Also, I would like to be effective loading a file with 40MB worth of line-feeds as well as a file which contains just a single line with 40MB data in it.&lt;/p&gt;

&lt;p&gt;But this simple test has solved one problem for me: I can keep the lines in an ArrayList for fast access and need not worry too much about performance. The actual character data needs to go into a chunked memory structure, though.&lt;/p&gt;

&lt;p&gt;Morale: There is no way to tell the performance of a piece of code by looking at it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-857827801784512007?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/857827801784512007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=857827801784512007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/857827801784512007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/857827801784512007'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/01/another-lesson-on-performance.html' title='Another Lesson on Performance'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4664525508767461979</id><published>2009-01-23T14:11:00.000+01:00</published><updated>2009-01-23T14:12:27.185+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>25 Most Dangerous Programming Errors</title><content type='html'>&lt;p&gt;If you want to improve your l33t [0d|ng skillz, especially keeping script kiddies off your back, here is a list of the 25 most common coding errors: &lt;a href="http://www.sans.org/top25errors/"&gt;http://www.sans.org/top25errors/&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4664525508767461979?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4664525508767461979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4664525508767461979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4664525508767461979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4664525508767461979'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/01/25-most-dangerous-programming-errors.html' title='25 Most Dangerous Programming Errors'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5864316973423733798</id><published>2009-01-22T13:58:00.002+01:00</published><updated>2009-01-22T14:01:42.545+01:00</updated><title type='text'>Sorting for Humans: Natural Sort Order</title><content type='html'>&lt;p&gt;Kate Rhodes sums it up nicely:&lt;/p&gt;

&lt;blockquote&gt;Silly me, I just figured that alphabetical sorting was such a common need (judging by the number of people asking how to do it I'm not wrong either) that I wouldn't have to write the damn thing. But I didn't count on the stupid factor. Jesus Christ people. You're programmers. You're almost all college graduates and none of you know what the f**k "Alphabetical" means. You should all be ashamed. If any of you are using your language's default sort algorithm, which is almost guaranteed to be ASCIIbetical (for good reason) to get alphabetical sorting you proceed to the nearest mirror and slap yourself repeatedly before returning to your desks and fixing your unit tests that didn't catch this problem. &lt;/blockquote&gt;

&lt;p&gt;So if you want to sort your lists the right way (instead of the ASCII way), &lt;a href="http://www.codinghorror.com/blog/archives/001018.html"&gt;read this&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5864316973423733798?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5864316973423733798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5864316973423733798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5864316973423733798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5864316973423733798'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/01/sorting-for-humans-natural-sort-order.html' title='Sorting for Humans: Natural Sort Order'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-106561548365869840</id><published>2009-01-03T14:49:00.003+01:00</published><updated>2009-01-03T14:57:30.360+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='SciFi'/><title type='text'>The Temporal Void</title><content type='html'>&lt;p&gt;Holidays. The only time where I can read or "dream with open eyes" (text from a bookmark). This year, it was "The Temporal Void" by &lt;a href="http://www.peterfhamilton.co.uk/"&gt;Peter F. Hamilton&lt;/a&gt;. It's the sequel to "The Dreaming Void" (&lt;a href="http://darkviews.blogspot.com/2008/01/dreaming-void.html"&gt;my review&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Again, the series is coming along great (which Peter can probably see on your bank account :) Well deserved if you ask me). I like the rich characters, the story is sound and believable. Recommendation: Buy. Now.&lt;/p&gt;

&lt;p&gt;There were three spots which I didn't "buy" in "The Temporal Void", places where I dropped from the story and thought "WTF?" &lt;b&gt;Note: Only mild spoilers below; you can read on even if you haven't read the book, yet.&lt;/b&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;So Aaron is stranded on Hanko, the planet is about to blow up and the Navy scout is about to pick him up. After being warned that he's dangerous, having the best sensors military money can buy, they let him simply walk on their ship battle ready and kill them. I mean, OK, shit happens and maybe these was the Omega ship with the best morons the Navy could find and such ... but ... nah, really :) With instant comm available at all times, no one is watching this important operation? There isn't even a recording? Didn't buy that one.&lt;/p&gt;

&lt;p&gt;The same happened in the first part when Aaron broke into the storage vault to claim Inigos memories. Why did you place the guards *inside* (where all that delicate stuff will break if they ever would have to engage someone)? Why not place them on the other side of the vault door where they can pummel any intruder against a foot or two of solid steel, without any cover?&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;Edeard finds his childhood friend Salrana in the clutches of Ranalee and leaves her there. I never thought he would be the character to leave someone behind. He knows only bad can come from this; I mean it's only the tenth time this happens, he got to learn something, right? If he dragged Salrana away, the girl would be mad but he could leave her with the Pythia and look for a solution if she doesn't know one. If all else fails, he could simply blackmail Ranalee into fixing what she did. So I accept that he's tired and worn out and all that but this just didn't fit.&lt;/li&gt;

&lt;li&gt;Paula and the quantumbuster. So this thing really distorts spacetime to wreak havoc with matter. How can she get away when space is so twisted? How about just nailing her in place using the ships in orbit and blowing up the station the traditional way?&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Other than that, the story is the usual perfect piece of work from Peter. I've posted the text above in Peter's inbox; should I get a reply, I'll post it here.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-106561548365869840?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/106561548365869840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=106561548365869840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/106561548365869840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/106561548365869840'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2009/01/temporal-void.html' title='The Temporal Void'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2154951812586056773</id><published>2008-12-23T11:20:00.005+01:00</published><updated>2008-12-23T11:47:57.280+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Hit Them Harder Until They Learn</title><content type='html'>&lt;p&gt;Do you believe that hitting people harder will make them learn? No? Do you believe that prison will turn a bad person into a good citizen? If not, why don't you do something about it?&lt;/p&gt;

&lt;p&gt;People like simple solutions. Out of the eyes, problem solved. Lock someone up, it will turn them into a nice fellow. Because you don't like to be locked up, you believe that others feel the same. The question remains: Why should locking up someone turn them into a better person?&lt;/p&gt;

&lt;p&gt;Well, it does work ... for monks. They willingly lock themselves up somewhere to be able to concentrate on those things that are dear to them and where they want to improve. But there is a big difference between locking up yourself (like a hermit) and locking up someone with a bunch of criminals and guards. Just make a wild guess where most criminals learn their trade ...&lt;/p&gt;

&lt;p&gt;The relapse rates vary a lot (by age, type of crime, prison, treatment). Still, I'm more astonished by the fact that not all of the inmates become criminal again rather than the fact that some do.&lt;/p&gt;

&lt;p&gt;That said, it is refreshing when you meet people who don't fall for the temptation of retribution. The guys at &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt; recently discovered that some people gamed the system to hurt other members or to increase their status. Instead of punishing them, they decided to just take away any advantage of trying to game the system. Problem really solved. Carry on, commander!&lt;/p&gt;

&lt;p&gt;Links: &lt;a href="http://blog.stackoverflow.com/2008/12/vote-fraud-and-you/"&gt;Vote Fraud And You&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.welt.de/politik/article1521293/Ein_Gefaengnisersatz_mit_Rueckfallquote_null.html"&gt;Ein Gefängnisersatz mit Rückfallquote null&lt;/a&gt; (German)&lt;br /&gt;
&lt;a href="http://www.planet-wissen.de/pw/Artikel,,,,,,,07B8F3BC8E716730E0440003BA5E08D7,,,,,,,,,,,,,,,.html"&gt;GEFÄNGNIS - LEBEN HINTER GITTERN&lt;/a&gt; (German)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2154951812586056773?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2154951812586056773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2154951812586056773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2154951812586056773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2154951812586056773'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/12/hit-them-harder-until-they-learn.html' title='Hit Them Harder Until They Learn'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4213283345541476214</id><published>2008-12-18T11:50:00.001+01:00</published><updated>2008-12-18T11:52:29.533+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>Holding a Program in One's Head</title><content type='html'>&lt;p&gt;In my perpetual search for brain food for programmers, I've found this article: &lt;a href="http://www.paulgraham.com/head.html"&gt;Holding a Program in One's Head&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4213283345541476214?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4213283345541476214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4213283345541476214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4213283345541476214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4213283345541476214'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/12/holding-program-in-ones-head.html' title='Holding a Program in One&apos;s Head'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6620684613655345717</id><published>2008-12-02T17:37:00.004+01:00</published><updated>2008-12-02T17:48:11.569+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Copyright'/><title type='text'>Obama Goes Creative Commons</title><content type='html'>&lt;p&gt;If you've been living under a stone for the past few months, the next president of the USA, Barack Obama, had his team build a &lt;a href="http://change.gov/"&gt;web site where he shares his thoughts, ideas and plans&lt;/a&gt;. That is itself probably constitutes a revolution but it gets better: You can talk to these guys. Or rather &lt;a href="http://change.gov/page/content/americanmoment"&gt;send them your ideas, hopes and worries&lt;/a&gt;. And it seems these really count. I mean, how much better can it get?&lt;/p&gt;

&lt;p&gt;It can: &lt;a href="http://change.gov/about/copyright_policy"&gt;The site and all content is under the Create Commons license CC-BY&lt;/a&gt; which basically means the content is free as long as you say where you got it from (&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;read the license for details&lt;/a&gt;). Amazing :)&lt;/p&gt;

&lt;p&gt;Thanks for the nice Christmas present, Mr. Soon-President! It really makes me happy to know that there is finally someone who gets the Internet.&lt;/p&gt;

&lt;p&gt;Links: &lt;a href="http://lessig.org/mt/mt-tb.cgi/2359"&gt;Lawrence Lessig's Blob&lt;/a&gt; (he's the inventor of CC, just in case).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6620684613655345717?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6620684613655345717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6620684613655345717' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6620684613655345717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6620684613655345717'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/12/obama-goes-creative-commons.html' title='Obama Goes Creative Commons'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7273671527097890856</id><published>2008-12-02T14:36:00.001+01:00</published><updated>2008-12-02T14:37:56.076+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Stackoverflow: Reputation over 1000 :)</title><content type='html'>&lt;p&gt;Just a tiny post to cheer the fact that my reputation on &lt;a href="http://stackoverflow.com/"&gt;Stackoverflow.com&lt;/a&gt; has transcended 1,000. Yay!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7273671527097890856?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7273671527097890856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7273671527097890856' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7273671527097890856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7273671527097890856'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/12/stackoverflow-reputation-over-1000.html' title='Stackoverflow: Reputation over 1000 :)'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5353428274306434433</id><published>2008-12-01T17:21:00.002+01:00</published><updated>2008-12-01T17:23:20.238+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Writing Testable Code</title><content type='html'>&lt;p&gt;Just stumbled over this article: "&lt;a href="http://misko.hevery.com/code-reviewers-guide/"&gt;Writing Testable Code&lt;/a&gt;". Apparently, it's a set of rules which &lt;a href="http://google.com/"&gt;Google&lt;/a&gt; uses. While I'm not a 100% fan of Google, this is something every developer should read and understand.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5353428274306434433?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5353428274306434433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5353428274306434433' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5353428274306434433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5353428274306434433'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/12/writing-testable-code.html' title='Writing Testable Code'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2455292004868907869</id><published>2008-11-29T10:40:00.000+01:00</published><updated>2008-11-29T10:41:22.883+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile Development'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>How To Be Agile</title><content type='html'>&lt;p&gt;The article "&lt;a href="http://www.cio.com/article/464169/When_Agile_Projects_Go_Bad"&gt;When Agile Projects Go Bad&lt;/a&gt;" got me thinking. I've talked to many people about &lt;a href="http://www.extremeprogramming.org/"&gt;XP&lt;/a&gt; and &lt;a href="http://agilemanifesto.org/"&gt;Agile Development&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; and the usual question is: "How do we make it work?" And the next sentence is: "This won't work with us because we can't do this or that.".&lt;/p&gt;

&lt;p&gt;This is a general misconception which comes from the ... uh ... "great" methodologies which you were taught in school: the waterfall model, the V model, the old dinosaurs. They told you: "You must follow the rules to the letter or doom will rain on your head!" Since you could never follow all the rules, they could easily say "Told you so!" when things didn't work out.&lt;/p&gt;

&lt;p&gt;Agile development is quite different in this respect. First of all, it assumes that you're an adult. That you have a brain and can actually use it. It also assumes that you want to improve your situation. It also assumes nothing else.&lt;/p&gt;

&lt;p&gt;When a company is in trouble, it will call for help. Expensive external advisers will be called, they will think about the situation for a long time (= more money for them). After a while (when the new yacht is in the dry), they will come up with what's wrong and how to fix it. Did you know that in most companies in trouble, the external advisers will just repeat what they heard form the people working there?&lt;/p&gt;

&lt;p&gt;It's not that people &lt;em&gt;don't know what's wrong&lt;/em&gt;, it's just &lt;em&gt;not healthy to mention it&lt;/em&gt; ... at least if you want to work there. So people walk around, with the anger in their hearts and the fist in the pocket and nothing will happen until someone from the outside comes in and states the obvious. Can't happen any other way because if it could, you wouldn't be in this situation in the first place.&lt;/p&gt;

&lt;p&gt;Agile Development is similar. It acknowledges that you're smart and that you know what's wrong and that you don't have the power to call in help. What it does is it offers you a set of tools, things that have worked for other people in the past and &lt;em&gt;some&lt;/em&gt; of them might apply to you. Maybe all. Probably not. Most likely, you will be able to use one or two. That doesn't sound like much but the old methodologies are pretty useless if you can't implement 90%+. Agile is agile. It can bend and twist and fit in your routine.&lt;/p&gt;

&lt;p&gt;So you're thinking about doing TDD. Do you have to ask your boss? No. Do you have to get permission from anyone? No. Do you have to tell anyone? No. Can you do it any time you like, as often as you like, stop at will? Yes. If it doesn't work for you in your situation, for the current project, then don't use it. No harm done, nothing gained either.&lt;/p&gt;

&lt;p&gt;But if you can use it, every little bit will help. Suddenly, you will find yourself to be able to deliver on time. Your code will work and it will be much more solid than before. You will be able to do more work in less time. People will notice. Your reputation will increase. And eventually, they will be curious: How do you do it? "TDD." What's that?&lt;/p&gt;

&lt;p&gt;You win.&lt;/p&gt;

&lt;p&gt;Be agile. Pick and choose. Pick what you think will work, try it, drop it if it doesn't deliver. And if it works, try the next thing. Evolve. Become the better you.&lt;/p&gt;

&lt;p&gt;Agile is not a silver bullet. It won't miraculously solve all your issues. You still have to think and be an adult about your work. It's meant to be that way. I don't do every Agile practice every day. Sometimes, I don't even TDD (and I regret every time). But I always return because life is just so much more simple.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2455292004868907869?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2455292004868907869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2455292004868907869' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2455292004868907869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2455292004868907869'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/how-to-be-agile.html' title='How To Be Agile'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-8936090821278721726</id><published>2008-11-28T14:41:00.001+01:00</published><updated>2008-11-28T14:43:07.207+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Space: Not So Black And Empty After All</title><content type='html'>&lt;p&gt;If you always wanted to know what &lt;a href="http://www.nasa.gov/"&gt;NASA&lt;/a&gt; does with all the billions of dollars spent, &lt;a href="http://www.nasaimages.org/index.html"&gt;here are some images&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-8936090821278721726?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/8936090821278721726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=8936090821278721726' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8936090821278721726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8936090821278721726'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/space-not-so-black-and-empty-after-all.html' title='Space: Not So Black And Empty After All'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5775316691378303733</id><published>2008-11-26T15:02:00.006+01:00</published><updated>2008-11-26T16:23:18.736+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Axis2'/><title type='text'>Navigating SharePoint Folders With Axis2</title><content type='html'>&lt;p&gt;I've just written some test code to get a list of items in a SharePoint folder with &lt;a href="http://ws.apache.org/axis2/index.html"&gt;Apache Axis2&lt;/a&gt; and since this was "not so easy", I'll share my insights here.&lt;/p&gt;

&lt;p&gt;First, you need Axis2. If you're using &lt;a href="http://maven.apache.org/"&gt;Maven2&lt;/a&gt;, put this in your pom.xml:&lt;/p&gt;

&lt;pre&gt;    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.axis2&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;axis2-kernel&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.4.1&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.axis2&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;axis2-adb&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.4.1&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Next stop: Setting up NTLM authorization.&lt;/p&gt;

&lt;pre&gt;import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.commons.httpclient.auth.AuthPolicy;

        HttpTransportProperties.Authenticator auth = new
            HttpTransportProperties.Authenticator();
        auth.setUsername ("username");
        auth.setPassword "password");
        auth.setDomain ("ntdom");
        auth.setHost ("host.domain.com");

        List&lt;String&gt; authPrefs = new ArrayList&lt;String&gt; (1);
        authPrefs.add (AuthPolicy.NTLM);
        auth.setAuthSchemes (authPrefs);
&lt;/pre&gt;

&lt;p&gt;This should be the username/password you're using to login to the NT domain "ntdom" on the NT domain server "host.domain.com". Often, this server is the same as the SharePoint server you want to connect to.&lt;/p&gt;

&lt;p&gt;If the SharePoint server is somewhere outside your intranet, you may need to specify a proxy:&lt;/p&gt;

&lt;pre&gt;        HttpTransportProperties.ProxyProperties proxyProperties =
            new HttpTransportProperties.ProxyProperties();
        proxyProperties.setProxyName ("your.proxy.com");
        proxyProperties.setProxyPort (8888);
&lt;/pre&gt;

&lt;p&gt;You can get these values from your Internet browser.&lt;/p&gt;

&lt;p&gt;If there are several SharePoint "sites" on the server, set &lt;tt&gt;site&lt;/tt&gt; to the relative URL of the site you want to connect to. Otherwise, leave &lt;tt&gt;site&lt;/tt&gt; empty. If you have no idea what I'm talking about, browse the SharePoint server in Internet Explorer. In the location bar, you'll see an URL like this: &lt;tt&gt;https://sp.company.com/projects/demo/Documents2/Forms/AllItems.aspx?RootFolder=%2fprojects%2fdemo%2fDocument2%2f&amp;FolderCTID=&amp;View=%7b18698D80%2dE081%2d4BBE%2d96EB%2d73BA839230B9%7d&lt;/tt&gt;. Scary, huh? Let's take it apart:&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;https://&lt;/tt&gt; = the protocol,&lt;br /&gt;
&lt;tt&gt;sp.company.com&lt;/tt&gt; = The server name (with domain),&lt;br /&gt;
&lt;tt&gt;projects/demo&lt;/tt&gt; = The "site" name&lt;br /&gt;
&lt;tt&gt;Documents2&lt;/tt&gt; = A "list" stored on the site "projects/demo"&lt;br /&gt;
&lt;tt&gt;/Forms/AllItems.aspx?RootFolder=...&lt;/tt&gt; is stuff to make IE happy. Ignore it.&lt;/p&gt;

&lt;p&gt;So in out example, we have to set site to:&lt;/p&gt;

&lt;pre&gt;        String site = "/projects/demo";
&lt;/pre&gt;

&lt;p&gt;Mind the leading slash!&lt;/p&gt;

&lt;p&gt;To verify that this is correct, replace "/Documents2/Forms/" and anything beyond with "/_vti_bin/Lists.asmx?WSDL". That should return the WSDL definition for this site. Save the result as "sharepoint.wsdl" (File menu, "Save as..."). &lt;a href="http://ws.apache.org/axis2/1_4_1/installationguide.html"&gt;Install Axis2&lt;/a&gt;, open a command prompt in the directory where you saved the WSDL file and &lt;a href="http://ws.apache.org/axis2/1_4_1/quickstartguide.html#clientadb"&gt;run this command&lt;/a&gt; (don't forget to replace the Java package name):&lt;/p&gt;

&lt;pre&gt;%AXIS2_HOME%\bin\WSDL2Java -uri sharepoint.wsdl -p java.package.name -d adb -s
&lt;/pre&gt;

&lt;p&gt;This will create a "src" directory with the Java package and a single file "ListsStub.java". Copy it into your Maven2 project.&lt;/p&gt;

&lt;p&gt;Now, we can get a list of the lists on the site:&lt;/p&gt;

&lt;pre&gt;        ListsStub lists = new ListsStub
            ("https://sp.company.com"+site+"/_vti_bin/Lists.asmx");
        lists._getServiceClient ().getOptions ()
            .setProperty (HTTPConstants.AUTHENTICATE, auth);
&lt;/pre&gt;

&lt;p&gt;If you need a proxy, specify it here:&lt;/p&gt;

&lt;pre&gt;        options.setProperty (HTTPConstants.HTTP_PROTOCOL_VERSION,
            HTTPConstants.HEADER_PROTOCOL_10);
        options.setProperty (HTTPConstants.PROXY, proxyProperties);
&lt;/pre&gt;

&lt;p&gt;We need to reduce the HTTP protocol version to 1.0 because most proxies don't allow to send multiple requests over a single connection. If you want to speed things up, you can try to comment out this line but be prepared to see it fail afterwards.&lt;/p&gt;

&lt;p&gt;Okay. The plumbing is in place. Now we query the server for the lists it has:&lt;/p&gt;

&lt;pre&gt;        String liste = "Documents2";
        String document2ID;
        {
            ListsStub.GetListCollection req = new ListsStub.GetListCollection();
            ListsStub.GetListCollectionResponse res = lists.GetListCollection (req);
            displayResult (req, res);
            
            document2ID = getIDByTitle (res, liste);
        }
&lt;/pre&gt;

&lt;p&gt;This downloads all lists defined on the server and searches for the one we need. If you're in doubt what the name of the list might be: Check the bread crumbs in the blue part in the intern explorer. The first two items are the title of the site and the list you're currently in.&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;displayResult()&lt;/tt&gt; is the usual XML dump code:&lt;/p&gt;

&lt;div style="width=100%; height=25em; overflow=scroll;"&gt;
&lt;pre&gt;    private void displayResult (GetListCollection req,
            GetListCollectionResponse res)
    {
        System.out.println ("Result OK: "
                +res.localGetListCollectionResultTracker);
        OMElement root = res.getGetListCollectionResult ()
                .getExtraElement ();
        dump (System.out, root, 0);
    }

    private void dump (PrintStream out, OMElement e, int indent)
    {
        indent(out, indent);
        out.print (e.getLocalName ());
        for (Iterator iter = e.getAllAttributes (); iter.hasNext (); )
        {
            OMAttribute attr = (OMAttribute)iter.next ();
            out.print (" ");
            out.print (attr.getLocalName ());
            out.print ("=\"");
            out.print (attr.getAttributeValue ());
            out.print ("\"");
        }
        out.println ();
        
        for (Iterator iter = e.getChildElements (); iter.hasNext (); )
        {
            OMElement child = (OMElement)iter.next ();
            dump (out, child, indent+1);
        }
    }

    private void indent (PrintStream out, int indent)
    {
        for (int i=0; i&amp;lt;indent; i++)
            out.print ("    ");
    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;We also need &lt;tt&gt;getIDByTitle()&lt;/tt&gt; to search for the ID of a SparePoint list:&lt;/p&gt;

&lt;div style="width=100%; height=25em; overflow=scroll;"&gt;
&lt;pre&gt;
    private String getIDByTitle (GetListCollectionResponse res, String title)
    {
        OMElement root = res.getGetListCollectionResult ().getExtraElement ();
        QName qnameTitle = new QName ("Title");
        QName qnameID = new QName ("ID");
        for (Iterator iter = root.getChildrenWithLocalName ("List"); iter.hasNext (); )
        {
            OMElement list = (OMElement)iter.next ();
            if (title.equals (list.getAttributeValue (qnameTitle)))
                return list.getAttributeValue (qnameID);
        }
        return null;
    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With that, we can finally list the items in a folder:&lt;/p&gt;

&lt;div style="width=100%; height=25em; overflow=scroll;"&gt;
&lt;pre&gt;        {
            String dir = "folder/subfolder";

            ListsStub.GetListItems req
                = new ListsStub.GetListItems ();
            req.setListName (document2ID);
            QueryOptions_type1 query
                = new QueryOptions_type1 ();
            OMFactory fac = OMAbstractFactory.getOMFactory();
            OMElement root = fac.createOMElement (
                new QName("", "QueryOptions"));
            query.setExtraElement (root);

            OMElement folder = fac.createOMElement (
                new QName("", "Folder"));
            root.addChild (folder);
            folder.setText (liste+"/"+dir); // &lt;--!!

            req.setQueryOptions (query);
            GetListItemsResponse res = lists.GetListItems (req);
            displayResult (req, res);
        }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The important bits here are: To list the items in a folder, you must include the name of the list in the "Folder" element! For reference, this is the XML which actually sent to the server:&lt;/p&gt;

&lt;div style="width=100%; height=25em; overflow=scroll;"&gt;
&lt;pre&gt;&amp;lt;?xml version='1.0' encoding='UTF-8'?&amp;gt;
&amp;lt;soapenv:Envelope xmlns:soapenv=&amp;quot;http://www.w3.org/2003/05/soap-envelope&amp;quot;&amp;gt;
    &amp;lt;soapenv:Body&amp;gt;
        &amp;lt;ns1:GetListItems xmlns:ns1=&amp;quot;http://schemas.microsoft.com/sharepoint/soap/&amp;quot;&amp;gt;
            &amp;lt;ns1:listName&amp;gt;{12AF2346-CCA1-486D-BE3C-82223DEC3F42}&amp;lt;/ns1:listName&amp;gt;
            &amp;lt;ns1:queryOptions&amp;gt;
                &amp;lt;QueryOptions&amp;gt;
                    &amp;lt;Folder&amp;gt;Documents2/folder/subfolder&amp;lt;/Folder&amp;gt;
                &amp;lt;/QueryOptions&amp;gt;
            &amp;lt;/ns1:queryOptions&amp;gt;
        &amp;lt;/ns1:GetListItems&amp;gt;
    &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If the folder name is not correct, you'll get a list of &lt;b&gt;all&lt;/b&gt; files and folders that the SharePoint server can find anywhere. The folder names can be found in the bread crumbs. The first two items are the site and the list name, respectively, followed by the folder names.&lt;/p&gt;

&lt;p&gt;The last missing piece is &lt;tt&gt;displayResult()&lt;/tt&gt; for the items:&lt;/p&gt;

&lt;pre&gt;    private void displayResult (GetListItems req,
         GetListItemsResponse res)
    {
        System.out.println ("Result OK: "
                +res.localGetListItemsResultTracker);
        OMElement root = res.getGetListItemsResult ()
                .getExtraElement ();
        dump (System.out, root, 0);
    }
&lt;/pre&gt;

&lt;p&gt;If you run this code and you see the exception "unable to find valid certification path to requested target", &lt;a href="http://blogs.sun.com/andreas/entry/no_more_unable_to_find"&gt;this article&lt;/a&gt; will help.&lt;/p&gt;

&lt;p&gt;If the SharePoint server returns an error, you'll see "detail unsupported element in SOAPFault element". I haven't found a way to work around this bug in Axis2. Try to set the log level of "org.apache.axis2" to "DEBUG" and you'll see what the SharePoint server sent back (not that it will help in most of the cases ...)&lt;/p&gt;

&lt;p&gt;Links: &lt;a href="http://msdn.microsoft.com/en-us/library/lists.lists.getlistitems.aspx"&gt;GetListItems&lt;/a&gt; on MSDN, &lt;a href="http://wso2.org/library/161"&gt;How to configure Axis2 to support Basic, NTLM and Proxy authentication?&lt;/a&gt;, &lt;a href="http://derekjmiller.spaces.live.com/blog/cns!A77124B9D0EE317F!142.entry#category"&gt;Java to SharePoint Integration - Part I&lt;/a&gt; (old, for Java 1.4)&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5775316691378303733?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5775316691378303733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5775316691378303733' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5775316691378303733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5775316691378303733'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/navigating-sharepoint-folders-with.html' title='Navigating SharePoint Folders With Axis2'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7307228200102381496</id><published>2008-11-19T21:38:00.003+01:00</published><updated>2008-11-25T21:20:16.252+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writing'/><category scheme='http://www.blogger.com/atom/ns#' term='Published Story'/><title type='text'>"Hunderte von Milliarden" auf Perry-Rhodan.net</title><content type='html'>&lt;p&gt;I've published a story :) Since the story is in German, this post is, too.&lt;/p&gt;

&lt;p&gt;Ich gebe es zu, ich bin ein Perry Rhodan Fan. Nicht nur, weil es die grösste SciFi-Serie der Welt ist (mit inzwischen 2466 Heften à 64 Seiten jede Woche, seit nunmehr fast 50 Jahren! Die aktuellen Ereignisse um Roi Danton und Dantyren haben mich so lange beschäftigt, bis ich eine Geschichte zu Papier (oder in diesem Fall zu PDF) bringen musste.&lt;/p&gt;

&lt;p&gt;Arndt Ellmer war so freundlich sie in der &lt;a href="http://perry-rhodan.net/entertainment/galerie/index.html"&gt;LKS Galerie&lt;/a&gt; auf der &lt;a href="http://perry-rhodan.net/"&gt;Homepage von Perry Rhodan&lt;/a&gt; zu platzieren. Der Titel ist "Hunderte von Milliarden" und enthält meine Interpretation von Aussagen wie "Der Erbe des Universums".&lt;/p&gt;

&lt;p&gt;Viel Vergnügen!&lt;/p&gt;

&lt;p&gt;Feedback ist erwünscht. Entweder als Kommentar anhängen oder per eine Mail (digulla at hepe dot com bzw. dark at pdark dot de).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7307228200102381496?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7307228200102381496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7307228200102381496' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7307228200102381496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7307228200102381496'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/hunderte-von-milliarden-auf-perry.html' title='&quot;Hunderte von Milliarden&quot; auf Perry-Rhodan.net'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2459190266948501563</id><published>2008-11-19T17:22:00.002+01:00</published><updated>2008-11-19T17:25:17.176+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>Stuck? Ask Stack Overflow</title><content type='html'>&lt;p&gt;Stuck with a hard programming problem? Just solved an impossible problem and want to show the world your genius? Don't know how to solve a problem with your favorite OS or programming language? Check out &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2459190266948501563?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2459190266948501563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2459190266948501563' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2459190266948501563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2459190266948501563'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/stuck-ask-stack-overflow.html' title='Stuck? Ask Stack Overflow'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-586799575569482879</id><published>2008-11-19T14:46:00.003+01:00</published><updated>2008-11-19T15:30:58.404+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Testing the Impossible: Rules of Thumb</title><content type='html'>&lt;p&gt;When people say "we can't test that", they usually mean "... with a reasonable effort". They say "we can't test that because it's using a database" or "we can't test the layout of the UI" or "to test this, we need information which is buried in private fields of that class".&lt;/p&gt;

&lt;p&gt;And they are always wrong. You can test everything. Usually with a reasonable effort. But often, you need to take a step back and do the unusual. Some examples.&lt;/p&gt;

&lt;p&gt;So your app is pumping lots of data into a database. You can't test the database. You'd need to scrap it for every test run and build it from scratch which would take hours or at least ages. Okay. Don't test the database. Test &lt;em&gt;how you use it&lt;/em&gt;. You're not looking for bugs in the database, you're looking for bugs in your code. Saying "but some bugs might get away" is just a lame excuse.&lt;/p&gt;

&lt;p&gt;Here is what you need to do: Identify independent objects (which need no other objects stored in the database). Write tests for those. Put the test data for them in an in-memory database. &lt;a href="http://hsqldb.org/"&gt;HSQLDB&lt;/a&gt; and &lt;a href="http://db.apache.org/derby/"&gt;Derby&lt;/a&gt; are your friends. If you must, use your production database but make the schema configurable. Scrap the tables before the test and load them from clean template tables.&lt;/p&gt;

&lt;p&gt;So you need some really spiffy SQL extensions? Put them in an isolated place and test them without everything else against the real database. You need to test that searching a huge amount of data works? Put that data in a static test database. Switch database connections during the tests. Can't? Make that damn connection provider configurable at runtime! Can't? Sure you can. If everything else fails, get the source with &lt;a href="http://www.kpdus.com/jad.html"&gt;JAD&lt;/a&gt;, compile that into an independent jar and force that as the first thing into the classpath when you run your tests. Use a custom classloader if you must.&lt;/p&gt;

&lt;p&gt;While this is not perfect, it will allow you to learn how to test. How to test &lt;b&gt;your&lt;/b&gt; work. Testing is always different just like every program is different. Allow yourself to make mistakes and to learn from them. Tackle the harder problems after the easier ones. Make the tests help you learn.&lt;/p&gt;

&lt;p&gt;So you have this very complex user interface. Which you can't test. Let alone starting the app takes ten minutes and the UI changes all the time and ... Okay. Stop the whining. Your program is running on a computer and for same inputs, a computer should return the same outputs, right? Or did you just build a big random number generator? Something to challenge the &lt;a href="http://en.wikipedia.org/wiki/Heart_of_Gold_(spaceship)#Infinite_Improbability_Drive"&gt;Infinite Improbability Drive&lt;/a&gt;? No? Then you can test it. Follow me.&lt;/p&gt;

&lt;p&gt;First, cut the code that &lt;b&gt;does&lt;/b&gt; something from the code that &lt;b&gt;connects&lt;/b&gt; said code to the UI. As a first simple step, we'll just assume that pressing a button will actually invoke your method. If this fails for some reason, that reason can't be very hard to find, so we can safely ignore these simple bugs for now.&lt;/p&gt;

&lt;p&gt;After this change, you have the code that does stuff at the scruff. Now, you can write tests for it. Reduce entanglement. Keep separate issues separate. A friend of mine builds all his code around a central event service. Service providers register themselves and other parts of the code send events to do stuff. It costs a bit performance but it makes testing as easy as overwriting an existing service provider with a &lt;a href="http://en.wikipedia.org/wiki/Mockup"&gt;mock up&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your software needs an insanely complex remote server? How about replacing this with a small proxy that always returns the same answers? Or at least fakes something that looks close enough to a real answer to make your code work (or fail when you're testing the error handling).&lt;/p&gt;

&lt;p&gt;And if you need data that some stubborn object won't reveal, use the source, Luke (download the source and edit the offender to make the field public, remove "final" from all files, add a getter or make it protected and extend the class in the tests). If everything else fails, turn to &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible(java.lang.reflect.AccessibleObject[],%20boolean)"&gt;java.lang.reflect.Field.setAccessible&lt;/a&gt;(true).&lt;/p&gt;

&lt;p&gt;If you're using C/C++, always invoke methods via a trampoline: Put a pointer somewhere which contains the function to call and always use that pointer instead of the real function. Use header files and macros so no human can tell the difference. In your tests, bend those pointers. The &lt;a href="http://en.wikipedia.org/wiki/Amiga"&gt;Amiga&lt;/a&gt; did it in 1985. &lt;tt&gt;#ifdef&lt;/tt&gt; is your friend.&lt;/p&gt;

&lt;p&gt;If you're using some other language, put the test code in comments and have a self-written preprocessor create two versions that you can compile and run.&lt;/p&gt;

&lt;p&gt;If all else fails, switch to &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-586799575569482879?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/586799575569482879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=586799575569482879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/586799575569482879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/586799575569482879'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/testing-impossible-rules-of-thumb.html' title='Testing the Impossible: Rules of Thumb'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5327235565084889960</id><published>2008-11-18T11:15:00.006+01:00</published><updated>2008-11-18T11:41:25.399+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Testing the Impossible: JavaScript in a Web Page</title><content type='html'>&lt;p&gt;How do you run JUnit tests on JavaScript in a web page? Impossible?&lt;/p&gt;

&lt;p&gt;Here is what you need: First, get a copy of &lt;a href="http://www.mozilla.org/rhino/"&gt;Rhino&lt;/a&gt; (at least 1.6R7). Then, save a copy of the JavaScript code at the bottom as "&lt;tt&gt;env.js&lt;/tt&gt;". And here is the setup code for the &lt;a href="http://www.junit.org/"&gt;JUnit test&lt;/a&gt;:&lt;/p&gt;

&lt;div style="width: 100%; overflow: scroll"&gt;
&lt;pre&gt;
    Context cx;
    Global scope;

    public void setupContext () throws IllegalAccessException,
            InstantiationException, InvocationTargetException
    {
        cx = Context.enter();
        scope = new Global();
        scope.init (cx);

        addScript(cx, scope, new File ("html/env.js"));

        File f = new File ("html/demo.html");
        cx.evaluateString(scope, 
                "window.location = '"+f.toURL()+"';\n" +
      "", "&lt;"+getName ()+"&gt;", 1, null);
    }

    public void addScript (Context cx, Scriptable scope, File file) throws IOException
    {
        Reader in = new FileReader (file);
        cx.evaluateReader(scope, in, file.getAbsolutePath(), 1, null);
    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will load "demo.html" into the browser simulation. The problem here: The loading is asynchronous (just like in a real browser). Now what? We need synchronization:&lt;/p&gt;

&lt;div style="width: 100%; height: 30em; overflow: scroll"&gt;
&lt;pre&gt;import org.mozilla.javascript.ScriptableObject;

public class JSJSynchronize extends ScriptableObject
{
    public Object data;
    public Object lock = new Object ();
    
    public JSJSynchronize()
    {
    }
    
    @Override
    public String getClassName ()
    {
        return "JSJSynchronize";
    }
    
    public Object jsGet_data()
    {
        synchronized (lock)
        {
            try
            {
                lock.wait ();
            }
            catch (InterruptedException e)
            {
                throw new RuntimeException ("Should not happen", e);
            }
            
            return data;
        }
    }

    public void jsSet_data(Object data)
    {
        synchronized (lock)
        {
            this.data = data;
            lock.notify ();
        }
    }
    
    public Object getData()
    {
        synchronized (lock)
        {
            try
            {
                lock.wait ();
            }
            catch (InterruptedException e)
            {
                throw new RuntimeException ("Should not happen", e);
            }
            
            return data;
        }
    }

    public void setData(Object data)
    {
        synchronized (lock)
        {
            this.data = data;
            lock.notify ();
        }
    }
    
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With this code and "window.onload", we can wait for the html to load:&lt;/p&gt;

&lt;div style="width: 100%; overflow: scroll"&gt;
&lt;pre&gt;
        JSJSynchronize jsjSynchronize;
        ScriptableObject.defineClass(scope, JSJSynchronize.class);
        
        jsjSynchronize = (JSJSynchronize)cx.newObject (scope, "JSJSynchronize");
        scope.put("jsjSynchronize", scope, jsjSynchronize);

        cx.evaluateString(scope, 
                "window.location = '"+f.toURL()+"';\n" +
      "window.onload = function(){\n" +
      "    print('Window loaded');\n" +
      "    jsjSynchronize.data = window;\n" +
      "};\n" +
      "", "&lt;"+getName ()+"&gt;", 1, null);

        ScriptableObject window = (ScriptableObject)jsjSynchronize.getData();
        System.out.println ("window="+window);
        ScriptableObject document = (ScriptableObject)scope.get ("document", scope);
        System.out.println ("document="+document);
        System.out.println ("document.forms="+document.get ("forms", document));
        ScriptableObject navigator = (ScriptableObject)scope.get ("navigator", scope);
        System.out.println ("navigator="+navigator);
        System.out.println ("navigator.location="+navigator.get ("location", navigator));

        // I've been too lazy to parse the HTML for the scripts:
        addScript(cx, scope, new File ("src/main/webapp/script/prototype.js"));
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Slightly modified version of env.js, original by John Resig (&lt;a href="http://jqueryjs.googlecode.com/svn/trunk/jquery/build/runtest/env.js"&gt;original code&lt;/a&gt;):&lt;/p&gt;

&lt;div style="width: 100%; height: 30em; overflow: scroll"&gt;
&lt;pre&gt;/*
 * Simulated browser environment for Rhino
 *   By John Resig &amp;lt;http://ejohn.org/&amp;gt;
 * Copyright 2007 John Resig, under the MIT License
 * http://jqueryjs.googlecode.com/svn/trunk/jquery/build/runtest/
 * Revision 5251
 */

// The window Object
var window = this;

// generic enumeration
Function.prototype.forEach = function(object, block, context) {
 for (var key in object) {
  if (typeof this.prototype[key] == "undefined") {
   block.call(context, object[key], key, object);
  }
 }
};

// globally resolve forEach enumeration
var forEach = function(object, block, context) {
 if (object) {
  var resolve = Object; // default
  if (object instanceof Function) {
   // functions have a "length" property
   resolve = Function;
  } else if (object.forEach instanceof Function) {
   // the object implements a custom forEach method so use that
   object.forEach(block, context);
   return;
  } else if (typeof object.length == "number") {
   // the object is array-like
   resolve = Array;
  }
  resolve.forEach(object, block, context);
 }
};

function collectForms(document) {
 var result = document.body.getElementsByTagName('form');
 //print('collectForms');
 document.forms = result;
  
 for (var i=0; i&amp;lt;result.length; i++) {
     var f = result[i];
     f.name = f.attributes['name'];
     //print('Form '+f.name);
     document[f.name] = f;
     f.elements = f.getElementsByTagName('input');
     
     for(var j=0; j&amp;lt;f.elements.length; j++) {
         var e = f.elements[j];
         var attr = e.attributes;
         
         //forEach(attr, print);
         e.type = attr['type'];
         e.name = attr['name'];
         e.className = attr['class'];
         
         f[e.name] = e;
  //print('    Input '+e.name);
     }
 }
}

(function(){

 // Browser Navigator

 window.navigator = {
  get userAgent(){
   return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";
  },
  get appVersion(){
   return "Mozilla/5.0";
  }
 };
 
 var curLocation = (new java.io.File("./")).toURL();
 
 window.__defineSetter__("location", function(url){
  var xhr = new XMLHttpRequest();
  xhr.open("GET", url);
  xhr.onreadystatechange = function(){
   curLocation = new java.net.URL( curLocation, url );
   window.document = xhr.responseXML;
   collectForms(window.document);

   var event = document.createEvent();
   event.initEvent("load");
   window.dispatchEvent( event );
  };
  xhr.send();
 });
 
 window.__defineGetter__("location", function(url){
  return {
   get protocol(){
    return curLocation.getProtocol() + ":";
   },
   get href(){
    return curLocation.toString();
   },
   toString: function(){
    return this.href;
   }
  };
 });
 
 // Timers

 var timers = [];
 
 window.setTimeout = function(fn, time){
  var num;
  return num = setInterval(function(){
   fn();
   clearInterval(num);
  }, time);
 };
 
 window.setInterval = function(fn, time){
  var num = timers.length;
  
  timers[num] = new java.lang.Thread(new java.lang.Runnable({
   run: function(){
    while (true){
     java.lang.Thread.currentThread().sleep(time);
     fn();
    }
   }
  }));
  
  timers[num].start();
 
  return num;
 };
 
 window.clearInterval = function(num){
  if ( timers[num] ) {
   timers[num].stop();
   delete timers[num];
  }
 };
 
 // Window Events
 
 var events = [{}];

 window.addEventListener = function(type, fn){
  if ( !this.uuid || this == window ) {
   this.uuid = events.length;
   events[this.uuid] = {};
  }
    
  if ( !events[this.uuid][type] )
   events[this.uuid][type] = [];
  
  if ( events[this.uuid][type].indexOf( fn ) &amp;lt; 0 )
   events[this.uuid][type].push( fn );
 };
 
 window.removeEventListener = function(type, fn){
    if ( !this.uuid || this == window ) {
        this.uuid = events.length;
        events[this.uuid] = {};
    }
    
    if ( !events[this.uuid][type] )
   events[this.uuid][type] = [];
   
  events[this.uuid][type] =
   events[this.uuid][type].filter(function(f){
    return f != fn;
   });
 };
 
 window.dispatchEvent = function(event){
  if ( event.type ) {
   if ( this.uuid &amp;amp;&amp;amp; events[this.uuid][event.type] ) {
    var self = this;
   
    events[this.uuid][event.type].forEach(function(fn){
     fn.call( self, event );
    });
   }
   
   if ( this["on" + event.type] )
    this["on" + event.type].call( self, event );
  }
 };
 
 // DOM Document
 
 window.DOMDocument = function(file){
  this._file = file;
  var factory = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance();
  factory.setValidating(false);
  this._dom = factory.newDocumentBuilder().parse(file);
  
  if ( !obj_nodes.containsKey( this._dom ) )
   obj_nodes.put( this._dom, this );
 };
 
 DOMDocument.prototype = {
  createTextNode: function(text){
   return makeNode( this._dom.createTextNode(
    text.replace(/&amp;amp;/g, "&amp;amp;amp;").replace(/&amp;lt;/g, "&amp;amp;lt;").replace(/&amp;gt;/g, "&amp;amp;gt;")) );
  },
  createElement: function(name){
   return makeNode( this._dom.createElement(name.toLowerCase()) );
  },
  getElementsByTagName: function(name){
   return new DOMNodeList( this._dom.getElementsByTagName(
    name.toLowerCase()) );
  },
  getElementById: function(id){
   var elems = this._dom.getElementsByTagName("*");
   
   for ( var i = 0; i &amp;lt; elems.length; i++ ) {
    var elem = elems.item(i);
    if ( elem.getAttribute("id") == id )
     return makeNode(elem);
   }
   
   return null;
  },
  get body(){
   return this.getElementsByTagName("body")[0];
  },
  get documentElement(){
   return makeNode( this._dom.getDocumentElement() );
  },
  get ownerDocument(){
   return null;
  },
  addEventListener: window.addEventListener,
  removeEventListener: window.removeEventListener,
  dispatchEvent: window.dispatchEvent,
  get nodeName() {
   return "#document";
  },
  importNode: function(node, deep){
   return makeNode( this._dom.importNode(node._dom, deep) );
  },
  toString: function(){
   return "Document" + (typeof this._file == "string" ?
    ": " + this._file : "");
  },
  get innerHTML(){
   return this.documentElement.outerHTML;
  },
  
  get defaultView(){
   return {
    getComputedStyle: function(elem){
     return {
      getPropertyValue: function(prop){
       prop = prop.replace(/\-(\w)/g,function(m,c){
        return c.toUpperCase();
       });
       var val = elem.style[prop];
       
       if ( prop == "opacity" &amp;amp;&amp;amp; val == "" )
        val = "1";
        
       return val;
      }
     };
    }
   };
  },
  
  createEvent: function(){
   return {
    type: "",
    initEvent: function(type){
     this.type = type;
    }
   };
  }
 };
 
 function getDocument(node){
  return obj_nodes.get(node);
 }
 
 // DOM NodeList
 
 window.DOMNodeList = function(list){
  this._dom = list;
  this.length = list.getLength();
  
  for ( var i = 0; i &amp;lt; this.length; i++ ) {
   var node = list.item(i);
   this[i] = makeNode( node );
  }
 };
 
 DOMNodeList.prototype = {
  toString: function(){
   return "[ " +
    Array.prototype.join.call( this, ", " ) + " ]";
  },
  get outerHTML(){
   return Array.prototype.map.call(
    this, function(node){return node.outerHTML;}).join('');
  }
 };
 
 // DOM Node
 
 window.DOMNode = function(node){
  this._dom = node;
 };
 
 DOMNode.prototype = {
  get nodeType(){
   return this._dom.getNodeType();
  },
  get nodeValue(){
   return this._dom.getNodeValue();
  },
  get nodeName() {
   return this._dom.getNodeName();
  },
  cloneNode: function(deep){
   return makeNode( this._dom.cloneNode(deep) );
  },
  get ownerDocument(){
   return getDocument( this._dom.ownerDocument );
  },
  get documentElement(){
   return makeNode( this._dom.documentElement );
  },
  get parentNode() {
   return makeNode( this._dom.getParentNode() );
  },
  get nextSibling() {
   return makeNode( this._dom.getNextSibling() );
  },
  get previousSibling() {
   return makeNode( this._dom.getPreviousSibling() );
  },
  toString: function(){
   return '"' + this.nodeValue + '"';
  },
  get outerHTML(){
   return this.nodeValue;
  }
 };

 // DOM Element

 window.DOMElement = function(elem){
  this._dom = elem;
  this.style = {
   get opacity(){ return this._opacity; },
   set opacity(val){ this._opacity = val + ""; }
  };
  
  // Load CSS info
  var styles = (this.getAttribute("style") || "").split(/\s*;\s*/);
  
  for ( var i = 0; i &amp;lt; styles.length; i++ ) {
   var style = styles[i].split(/\s*:\s*/);
   if ( style.length == 2 )
    this.style[ style[0] ] = style[1];
  }
 };
 
 DOMElement.prototype = extend( new DOMNode(), {
  get nodeName(){
   return this.tagName.toUpperCase();
  },
  get tagName(){
   return this._dom.getTagName();
  },
  toString: function(){
   return "&amp;lt;" + this.tagName + (this.id ? "#" + this.id : "" ) + "&amp;gt;";
  },
  get outerHTML(){
   var ret = "&amp;lt;" + this.tagName, attr = this.attributes;
   
   for ( var i in attr )
    ret += " " + i + "='" + attr[i] + "'";
    
   if ( this.childNodes.length || this.nodeName == "SCRIPT" )
    ret += "&amp;gt;" + this.childNodes.outerHTML + 
     "&amp;lt;/" + this.tagName + "&amp;gt;";
   else
    ret += "/&amp;gt;";
   
   return ret;
  },
  
  get attributes(){
   var attr = {}, attrs = this._dom.getAttributes();
   
   for ( var i = 0; i &amp;lt; attrs.getLength(); i++ )
    attr[ attrs.item(i).nodeName ] = attrs.item(i).nodeValue;
    
   return attr;
  },
  
  get innerHTML(){
   return this.childNodes.outerHTML; 
  },
  set innerHTML(html){
   html = html.replace(/&amp;lt;\/?([A-Z]+)/g, function(m){
    return m.toLowerCase();
   });
   
   var nodes = this.ownerDocument.importNode(
    new DOMDocument( new java.io.ByteArrayInputStream(
     (new java.lang.String("&amp;lt;wrap&amp;gt;" + html + "&amp;lt;/wrap&amp;gt;"))
      .getBytes("UTF8"))).documentElement, true).childNodes;
    
   while (this.firstChild)
    this.removeChild( this.firstChild );
   
   for ( var i = 0; i &amp;lt; nodes.length; i++ )
    this.appendChild( nodes[i] );
  },
  
  get textContent(){
   return nav(this.childNodes);
   
   function nav(nodes){
    var str = "";
    for ( var i = 0; i &amp;lt; nodes.length; i++ )
     if ( nodes[i].nodeType == 3 )
      str += nodes[i].nodeValue;
     else if ( nodes[i].nodeType == 1 )
      str += nav(nodes[i].childNodes);
    return str;
   }
  },
  set textContent(text){
   while (this.firstChild)
    this.removeChild( this.firstChild );
   this.appendChild( this.ownerDocument.createTextNode(text));
  },
  
  style: {},
  clientHeight: 0,
  clientWidth: 0,
  offsetHeight: 0,
  offsetWidth: 0,
  
  get disabled() {
   var val = this.getAttribute("disabled");
   return val != "false" &amp;amp;&amp;amp; !!val;
  },
  set disabled(val) { return this.setAttribute("disabled",val); },
  
  get checked() {
   var val = this.getAttribute("checked");
   return val != "false" &amp;amp;&amp;amp; !!val;
  },
  set checked(val) { return this.setAttribute("checked",val); },
  
  get selected() {
   if ( !this._selectDone ) {
    this._selectDone = true;
    
    if ( this.nodeName == "OPTION" &amp;amp;&amp;amp; !this.parentNode.getAttribute("multiple") ) {
     var opt = this.parentNode.getElementsByTagName("option");
     
     if ( this == opt[0] ) {
      var select = true;
      
      for ( var i = 1; i &amp;lt; opt.length; i++ )
       if ( opt[i].selected ) {
        select = false;
        break;
       }
       
      if ( select )
       this.selected = true;
     }
    }
   }
   
   var val = this.getAttribute("selected");
   return val != "false" &amp;amp;&amp;amp; !!val;
  },
  set selected(val) { return this.setAttribute("selected",val); },

  get className() { return this.getAttribute("class") || ""; },
  set className(val) {
   if (typeof val != 'string') { val = "" + val; }
   return this.setAttribute("class",
    val.replace(/(^\s*|\s*$)/g,""));
  },
  
  get type() { return this.getAttribute("type") || ""; },
  set type(val) { return this.setAttribute("type",val); },
  
  get value() { return this.getAttribute("value") || ""; },
  set value(val) { return this.setAttribute("value",val); },
  
  get src() { return this.getAttribute("src") || ""; },
  set src(val) { return this.setAttribute("src",val); },
  
  get id() { return this.getAttribute("id") || ""; },
  set id(val) { return this.setAttribute("id",val); },
  
  getAttribute: function(name){
   return this._dom.hasAttribute(name) ?
    new String( this._dom.getAttribute(name) ) :
    null;
  },
  setAttribute: function(name,value){
   this._dom.setAttribute(name,value);
  },
  removeAttribute: function(name){
   this._dom.removeAttribute(name);
  },
  
  get childNodes(){
   return new DOMNodeList( this._dom.getChildNodes() );
  },
  get firstChild(){
   return makeNode( this._dom.getFirstChild() );
  },
  get lastChild(){
   return makeNode( this._dom.getLastChild() );
  },
  appendChild: function(node){
   this._dom.appendChild( node._dom );
  },
  insertBefore: function(node,before){
   this._dom.insertBefore( node._dom, before ? before._dom : before );
  },
  removeChild: function(node){
   this._dom.removeChild( node._dom );
  },

  getElementsByTagName: DOMDocument.prototype.getElementsByTagName,
  
  addEventListener: window.addEventListener,
  removeEventListener: window.removeEventListener,
  dispatchEvent: window.dispatchEvent,
  
  click: function(){
   var event = document.createEvent();
   event.initEvent("click");
   this.dispatchEvent(event);
  },
  submit: function(){
   var event = document.createEvent();
   event.initEvent("submit");
   this.dispatchEvent(event);
  },
  focus: function(){
   var event = document.createEvent();
   event.initEvent("focus");
   this.dispatchEvent(event);
  },
  blur: function(){
   var event = document.createEvent();
   event.initEvent("blur");
   this.dispatchEvent(event);
  },
  get elements(){
   return this.getElementsByTagName("*");
  },
  get contentWindow(){
   return this.nodeName == "IFRAME" ? {
    document: this.contentDocument
   } : null;
  },
  get contentDocument(){
   if ( this.nodeName == "IFRAME" ) {
    if ( !this._doc )
     this._doc = new DOMDocument(
      new java.io.ByteArrayInputStream((new java.lang.String(
      "&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;"))
      .getBytes("UTF8")));
    return this._doc;
   } else
    return null;
  }
 });
 
 // Helper method for extending one object with another
 
 function extend(a,b) {
  for ( var i in b ) {
   var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
   
   if ( g || s ) {
    if ( g )
     a.__defineGetter__(i, g);
    if ( s )
     a.__defineSetter__(i, s);
   } else
    a[i] = b[i];
  }
  return a;
 }
 
 // Helper method for generating the right
 // DOM objects based upon the type
 
 var obj_nodes = new java.util.HashMap();
 
 function makeNode(node){
  if ( node ) {
   if ( !obj_nodes.containsKey( node ) )
    obj_nodes.put( node, node.getNodeType() == 
     Packages.org.w3c.dom.Node.ELEMENT_NODE ?
      new DOMElement( node ) : new DOMNode( node ) );
   
   return obj_nodes.get(node);
  } else
   return null;
 }
 
 // XMLHttpRequest
 // Originally implemented by Yehuda Katz

 window.XMLHttpRequest = function(){
  this.headers = {};
  this.responseHeaders = {};
 };
 
 XMLHttpRequest.prototype = {
  open: function(method, url, async, user, password){ 
   this.readyState = 1;
   if (async)
    this.async = true;
   this.method = method || "GET";
   this.url = url;
   this.onreadystatechange();
  },
  setRequestHeader: function(header, value){
   this.headers[header] = value;
  },
  getResponseHeader: function(header){ },
  send: function(data){
   var self = this;
   
   function makeRequest(){
    var url = new java.net.URL(curLocation, self.url);
    
    if ( url.getProtocol() == "file" ) {
     if ( self.method == "PUT" ) {
      var out = new java.io.FileWriter( 
        new java.io.File( new java.net.URI( url.toString() ) ) ),
       text = new java.lang.String( data || "" );
      
      out.write( text, 0, text.length() );
      out.flush();
      out.close();
     } else if ( self.method == "DELETE" ) {
      var file = new java.io.File( new java.net.URI( url.toString() ) );
      file["delete"]();
     } else {
      var connection = url.openConnection();
      connection.connect();
      handleResponse();
     }
    } else { 
     var connection = url.openConnection();
     
     connection.setRequestMethod( self.method );
     
     // Add headers to Java connection
     for (var header in self.headers)
      connection.addRequestProperty(header, self.headers[header]);
    
     connection.connect();
     
     // Stick the response headers into responseHeaders
     for (var i = 0; ; i++) { 
      var headerName = connection.getHeaderFieldKey(i); 
      var headerValue = connection.getHeaderField(i); 
      if (!headerName &amp;amp;&amp;amp; !headerValue) break; 
      if (headerName)
       self.responseHeaders[headerName] = headerValue;
     }
     
     handleResponse();
    }
    
    function handleResponse(){
     self.readyState = 4;
     self.status = parseInt(connection.responseCode) || undefined;
     self.statusText = connection.responseMessage || "";
     
     var stream = new java.io.InputStreamReader(connection.getInputStream()),
      buffer = new java.io.BufferedReader(stream), line;
     
     while ((line = buffer.readLine()) != null)
      self.responseText += line;
      
     self.responseXML = null;
     
     if ( self.responseText.match(/^\s*&amp;lt;/) ) {
      //try {
       self.responseXML = new DOMDocument(
        new java.io.ByteArrayInputStream(
         (new java.lang.String(
          self.responseText)).getBytes("UTF8")));
      //} catch(e) {
      //}
     }
    }
    
    self.onreadystatechange();
   }

   if (this.async)
    (new java.lang.Thread(new java.lang.Runnable({
     run: makeRequest
    }))).start();
   else
    makeRequest();
  },
  abort: function(){},
  onreadystatechange: function(){},
  getResponseHeader: function(header){
   if (this.readyState &amp;lt; 3)
    throw new Error("INVALID_STATE_ERR");
   else {
    var returnedHeaders = [];
    for (var rHeader in this.responseHeaders) {
     if (rHeader.match(new Regexp(header, "i")))
      returnedHeaders.push(this.responseHeaders[rHeader]);
    }
   
    if (returnedHeaders.length)
     return returnedHeaders.join(", ");
   }
   
   return null;
  },
  getAllResponseHeaders: function(header){
   if (this.readyState &amp;lt; 3)
    throw new Error("INVALID_STATE_ERR");
   else {
    var returnedHeaders = [];
    
    for (var header in this.responseHeaders)
     returnedHeaders.push( header + ": " + this.responseHeaders[header] );
    
    return returnedHeaders.join("\r\n");
   }
  },
  async: true,
  readyState: 0,
  responseText: "",
  status: 0
 };
})();
&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5327235565084889960?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5327235565084889960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5327235565084889960' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5327235565084889960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5327235565084889960'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/testing-impossible-javascript-in-web.html' title='Testing the Impossible: JavaScript in a Web Page'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3211136481640505175</id><published>2008-11-16T20:39:00.003+01:00</published><updated>2008-11-16T20:51:46.091+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='upcscan'/><category scheme='http://www.blogger.com/atom/ns#' term='PyQt4'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>UPCScan 0.7: Where is my stuff?</title><content type='html'>&lt;p&gt;UPCScan 0.7 is released. New features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UPCScan can now find music CDs&lt;/li&gt;

&lt;li&gt;If UPCScan can't find something on Amazon, it will still create an entry which you can then edit to fill in the details.&lt;/li&gt;

&lt;li&gt;Entries can be deleted.&lt;/li&gt;

&lt;li&gt;I've added lending information so you can quickly figure out who your new "ex-friends" should be.&lt;/li&gt;

&lt;li&gt;I'm working on a series/issue information system to make it more simple to complete your collection. With this version, you'll need to edit the database directly to add series/issue information but the user interface can already display this data.&lt;/li&gt;

&lt;li&gt;I'm working on a feature to create an OpenOffice document with the locations. This would allow you to print this out and then scan the locations in as you scan your collection to tell UPCScan under which location to file the items. If you can't wait, then you can use the barcode.py script to generate PNG images with barcodes which you can import in OpenOffice to achieve the same effect.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Download: &lt;a href="http://www.pdark.de/upcscan-0.7.tar.gz"&gt;upcscan-0.7.tar.gz&lt;/a&gt; (26,921 Bytes, &lt;a href="http://www.pdark.de/upcscan-0.7.md5sum"&gt;MD5&lt;/a&gt;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3211136481640505175?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3211136481640505175/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3211136481640505175' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3211136481640505175'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3211136481640505175'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/upcscan-07-where-is-my-stuff.html' title='UPCScan 0.7: Where is my stuff?'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6507452035074763483</id><published>2008-11-11T11:26:00.004+01:00</published><updated>2008-11-11T11:36:35.713+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Testing the Impossible: User Dialogs</title><content type='html'>&lt;p&gt;How do you test a user dialog like "Do you really want to quit?"&lt;/p&gt;

&lt;p&gt;This code usually looks like this:&lt;/p&gt;

&lt;pre&gt;    public void quit () {
        if (!MessageDialog.ask (getShell(),
            "Really quit?",
            "Do you really want to quit?"
        ))
            return;

        ... quit ...
    }&lt;/pre&gt;

&lt;p&gt;The solution is simple:&lt;/p&gt;

&lt;pre&gt;    public void quit () {
        if (askToQuit ())
            return;

        ... quit ...
    }

    /** For tests */
    protected boolean askToQuit () {
        ... ask your question here ...
    }&lt;/pre&gt;

&lt;p&gt;In test cases, you can now extend the class, and override &lt;tt&gt;askToQuit&lt;/tt&gt;:&lt;/p&gt;

&lt;pre&gt;
    public boolean askToQuitWasCalled = false;
    public boolean askToQuitResult = true;

    protected boolean askToQuit () {
        askToQuitWasCalled = true;
        return askToQuitResult;
    }&lt;/pre&gt;

&lt;p&gt;Now, you can find out if the question would be asked and you can verify that the code behaves correctly depending on the answer. Tests that just want to quit won't need to do anything special to get the desired behavior.&lt;/p&gt;

&lt;p&gt;The same applies to more complex dialogs: Refactor them to put their data into an intermediate structure which you can mock during the tests. That means to copy the data if the dialog is a black box but that's a small price to be paid for being able to test modal user dialogs.&lt;/p&gt;

&lt;p&gt;Lesson: You don't want to test the dialog, you want to test whether it is opened at the right place, under the right circumstances and if the result is processes correctly.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6507452035074763483?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6507452035074763483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6507452035074763483' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6507452035074763483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6507452035074763483'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/testing-impossible-user-dialogs.html' title='Testing the Impossible: User Dialogs'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5811003345522473238</id><published>2008-11-10T16:54:00.002+01:00</published><updated>2008-11-10T17:09:18.510+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Surveillance'/><title type='text'>I Have Nothing to Hide ... I Think</title><content type='html'>&lt;p&gt;So it has &lt;a href="http://www.linux-magazin.de/heft_abo/ausgaben/2008/12/botenstoff"&gt;happened again&lt;/a&gt;. Someone put a nice web site online and when it came to pick and chose between security and comfort, guess who won. Alas, those who do as you shouldn't still server as a bad example. What has happened?&lt;/p&gt;

&lt;p&gt;DHL, a German parcel delivery service, offers a web site where you can track where your brand new gadget is now so you can guess how long it will take until you rip the wrapping off it. That good.&lt;/p&gt;

&lt;p&gt;Not so good is that all customers of DHL get the same default password.&lt;/p&gt;

&lt;p&gt;Bad is that DHL reuses the tracking numbers after roughly six months (depending on the amount of parcels that go through the system; if there are less, you can look further into the past).&lt;/p&gt;

&lt;p&gt;Really bad is that part of DHL's tracking number of fixed. It's based on the DHL customer number. That's not &lt;b&gt;you&lt;/b&gt;, this "customer" is the guy or company you ordered from (DHL renders a service for them).&lt;/p&gt;

&lt;p&gt;So this leaves us with a convenient way to check who else has ordered anything from those that shop.&lt;/p&gt;

&lt;p&gt;Now imagine you ordered something innocent ... oh, maybe porn or "adult toys" or something from company B which is the arch enemy of company A which incidentally pays your wage. All of a sudden, a couple of innocent bits of information have turned ugly.&lt;/p&gt;

&lt;p&gt;Whenever you put something out to the world, step away for a few moments from your dreams how much good someone could do with your service and think how much bad someone could do with it. And if you can't think of anything, you should be very, very worried.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5811003345522473238?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5811003345522473238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5811003345522473238' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5811003345522473238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5811003345522473238'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/11/i-have-nothing-to-hide-i-think.html' title='I Have Nothing to Hide ... I Think'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4041353534795822179</id><published>2008-10-30T14:47:00.001+01:00</published><updated>2008-10-30T14:48:57.609+01:00</updated><title type='text'>Multi-line String Literals in Java</title><content type='html'>&lt;p&gt;You want multi-line string literals in Java which work in Java 1.4 and up? Can't be done, you say?&lt;/p&gt;

&lt;p&gt;Sven Efftinge &lt;a href="http://blog.efftinge.de/2008/10/multi-line-string-literals-in-java.html"&gt;found a way&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4041353534795822179?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4041353534795822179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4041353534795822179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4041353534795822179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4041353534795822179'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/multi-line-string-literals-in-java.html' title='Multi-line String Literals in Java'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4483365654005147730</id><published>2008-10-27T11:09:00.002+01:00</published><updated>2008-10-27T11:13:02.436+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VMware'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Compile VMware tools on openSUSE 10.3</title><content type='html'>&lt;p&gt;I just tried to install the VMware tools on openSUSE 10.3 (Linux kernel 2.6.22.18) so the virtual machine would survive more than 10 days on an ESX server and failed. If you have the same problem, &lt;a href="http://tuxx-home.at/archives/2007/06/29/T12_33_53/"&gt;the solution is here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Errors you'll see during the installation otherwise:&lt;/p&gt;

&lt;p&gt;The directory of kernel headers (version @@VMWARE@@ UTS_RELEASE) does not match your running kernel (version 2.6.22.18-0.2-default). Even if the module were to compile successfully, it would not load into the running kernel.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4483365654005147730?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4483365654005147730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4483365654005147730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4483365654005147730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4483365654005147730'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/compile-vmware-tools-on-opensuse-103.html' title='Compile VMware tools on openSUSE 10.3'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3675967705445492811</id><published>2008-10-22T20:01:00.003+02:00</published><updated>2008-10-22T20:25:04.868+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Failure is not an Option</title><content type='html'>&lt;p&gt;Everyone loves war stories. Here is one of mine. I need a special diet, especially bread. So one Friday evening, I was taking the train home after buying a couple of custom made loafs of bread. In Dübendorf, I left the train and walked home.&lt;/p&gt;

&lt;p&gt;About halfway home, I noticed that I had my head, my arms, my bag ... but not my bread! ARGH! Stupid, stupid, stupid! I knew I should have stuffed them in my rucksack but didn't because it was so full and ... yeah ... okay. My baker needs three days to make these breads so that meant about a week without any for me.&lt;/p&gt;

&lt;p&gt;Arriving home, an idea struck me and I fired up the &lt;a href="http://www.vbz.ch/"&gt;VBZ online service&lt;/a&gt; to find out where the train was and when the driver would make the next break. A few moments later, the SBB Train Police got a really strange call by me: "I need my bread. It's in this train and can you please, please ask the driver to check if the white plastic bag with the bread is still there?"&lt;/p&gt;

&lt;p&gt;The woman on the other end was surprised and promised to call me back.&lt;/p&gt;

&lt;p&gt;Ten minutes can be sooo long.&lt;/p&gt;

&lt;p&gt;From the timetable, I knew that my train would probably come through my town in about twenty minutes when I got the call. Yes, they found it and the driver would take the plastic bag into his cabin and she told me where to wait on the platform so he could hand it over.&lt;/p&gt;

&lt;p&gt;Try train was on time (as usual), the driver handed me my bag (and it really was mine and all the bread was still there) and I was really relieved. After thanking him, I went home to have my dinner. Thanks to the SBB train police, a train driver and an unknown person who put my bread in the overhead compartment when I left it behind, I didn't go hungry that weekend.&lt;/p&gt;

&lt;p&gt;Lesson: If all seems lost, take a step back, do something else and you might have the idea which will save the day.&lt;/p&gt;

&lt;p&gt;Train related joke: The SBB (Schweizer Bundesbahn - Swiss federation train company) and the German Bundesbahn (the counterpart of the SBB in Germany) wanted to save some money and decided to buy the same information system to inform about arriving trains on the platform. After a longer evaluation, the plan was dropped. The SBB needed signs which said "Train is 1, 2, 3, 4, 5 minutes late" and the German Bundesbahn needed "Train is half an hour, 1 hour, 2 hours, 3 hours, 4 hours, Train Cancelled."&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3675967705445492811?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3675967705445492811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3675967705445492811' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3675967705445492811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3675967705445492811'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/failure-is-not-option.html' title='Failure is not an Option'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1861241969098026038</id><published>2008-10-14T17:56:00.003+02:00</published><updated>2008-10-14T17:58:04.113+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>So... You want your code to be maintainable.</title><content type='html'>&lt;p&gt;A great post if you're interested in TDD or testing in general: &lt;a href="http://blog.objectmentor.com/articles/2008/06/24/so-you-want-your-code-to-be-maintainable"&gt;So... You want your code to be maintainable.&lt;/a&gt; by Uncle Bob. Thanks, Bob!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1861241969098026038?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1861241969098026038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1861241969098026038' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1861241969098026038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1861241969098026038'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/so-you-want-your-code-to-be.html' title='So... You want your code to be maintainable.'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-8126972178315724795</id><published>2008-10-11T22:58:00.002+02:00</published><updated>2008-10-11T23:28:06.212+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Good Games for the PS3</title><content type='html'>&lt;p&gt;I've recently upgraded to a PlayStation 3. I kept my old PS2, though, since the new PS3 can't emulate the PS2. I wonder why that is ... maybe it's because Sony is still selling so many PS2's? Ah, rumors :) Easy to create and hard to kill.&lt;/p&gt;

&lt;p&gt;So what good games are there? Here is my list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Burnout Paradise City&lt;/li&gt;
&lt;li&gt;PixelJunk Eden&lt;/li&gt;
&lt;li&gt;Ratchet &amp;amp; Clank - Tools of Destruction&lt;/li&gt;
&lt;li&gt;Flow&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Burnout Paradise City&lt;/h3&gt;

&lt;p&gt;Mindless street racing with a high adrenaline level. Ideal to waste a couple of minutes or an hour. Great graphics, no blood, no violence (it's more like auto scooter) and nice ideas like smashing ads or the super jumps. If you don't like some events (haven't managed to win a single race, yet. I excel at kicking other cars off the street), you can simply ignore them and still complete enough of the game to have fun.&lt;/p&gt;

&lt;h3&gt;PixelJunk Eden&lt;/h3&gt;

&lt;p&gt;A definitive feel of Tarzan or Spiderman when you want to relax a bit. Simple, fitting graphics, no violence, no agression. All that and at the price it's a steal.&lt;/p&gt;

&lt;h3&gt;Ratchet &amp;amp; Clank - Tools of Destruction&lt;/h3&gt;

&lt;p&gt;My favorite jump'n'run. Lots of insane weapons, Ratchet's ears look great on the PS3, the story has more depth than usual; not sure I like the depressive realization at the end, though. Judge for yourself.&lt;/p&gt;

&lt;h3&gt;Flow&lt;/h3&gt;

&lt;p&gt;Like Eden, it's a brand new kind of game. One of a kind. I play that when I want to come down from all the stress in my life. Go get it!&lt;/p&gt;

&lt;h1&gt;Bad games&lt;/h1&gt;

&lt;p&gt;I've got a couple of other games. First, we have the Orange Box with Half Life 2, two of the extra episodes, Portal and Team Fortress. I liked the puzzles in Portal. That games was much too short. I didn't like Half Life 2 much and I hate the episodes.  The story was great, the levels gigantic and intelligent. You could almost always find a way around without getting killed. But the handling ... Freeman feels like a block of wood when you move him through the levels: You'll get stuck all the time at hand rails and stuff like that. Sometimes, he'll be able to jump on something, sometimes not. Sometimes, he'll stay on top of a barrel, sometimes not. This sucks. And then those stupid zombie levels. Yeah, I'm stuck in the elevator scene in the first episode. Got killed five times in the dark and now, the games goes where it belongs: The trash.&lt;/p&gt;

&lt;p&gt;Resistance - Fall of Man. I like the other games by Insomniac and I like this one, too. It's just too violent for my taste. I like shooting pixels or push empty cars off the street or zoom down a highway at break-neck speed. I don't like shooting at people. I finished the game but it left me asking: Is that all? Running around, shooting people, blow up stuff? Is that the result of many years of game evolution? Better graphics?&lt;/p&gt;

&lt;p&gt;Uncharted: Drake's Fortune. Oh well. Okay, the levels look great. When you scale the wall of the castle, there is a sense of vertigo. It's breath taking. The jeep escape is a lot of fun. Smart story (mostly). The game character moves smart. You press a button and he takes cover. He's smart, not a dead puppet like Freeman. He moves as if he was real. Again the violence cooled me off quickly. Too much killing, not enough puzzles.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-8126972178315724795?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/8126972178315724795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=8126972178315724795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8126972178315724795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8126972178315724795'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/good-games-for-ps3.html' title='Good Games for the PS3'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7017939649167308358</id><published>2008-10-09T15:21:00.003+02:00</published><updated>2008-10-09T16:15:23.670+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Traits'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Enthought Traits</title><content type='html'>&lt;p&gt;I'm always looking for more simple ways to build applications. Let's face it, it's 2008 and after roughly 50 years, writing something that collects a few bits of data and presents them in a nice way is still several days of work. And that's without Undo/Redo, a way to persist the data, a way to evolve the storage format, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; was always promising and with the &lt;a href="http://wiki.python.org/moin/TkInter"&gt;tkinter&lt;/a&gt; module, they set a rather high watermark on how you easily could build UIs ... alas Tk is not the most powerful UI framework out there and ... well ... let's just leave it at that.&lt;/p&gt;

&lt;p&gt;With &lt;a href="http://code.enthought.com/projects/traits/"&gt;Traits&lt;/a&gt;, we have a new contender and I have to admit that I like it ... a lot. The traits framework solves a lot of the standard issues out of the box while leaving all the hooks and bolts available between a very thin polish so you can still get at them when you have to.&lt;/p&gt;

&lt;p&gt;For example, you have a list of persons and you want to assign each person a gender. Here is the model:&lt;/p&gt;

&lt;pre&gt;class Gender(HasTraits):
    name = Str
    
    def __repr__(self):
        return 'Gender %s' % self.name

class Person(HasTraits):
    name = Str
    gender = Instance(Gender)
    
    def __repr__(self):
        return 'Person %s' % self.name

class Model(HasTraits):
    genderList = List(Gender)
    persons = List(Person)
&lt;/pre&gt;

&lt;p&gt;Here is how you use this model:&lt;/p&gt;

&lt;pre&gt;female = Gender(name='Female')
male = Gender(name='Male')
undefined = Gender(name='Undefined')

aMale = Person(name='a male', gender=male)
aFemale = Person(name='a female', gender=female)

model = Model()
model.genderList.append(female)
model.genderList.append(male)
model.genderList.append(undefined)
model.persons.append(aFemale)
model.persons.append(aMale)
&lt;/pre&gt;

&lt;p&gt;Nothing fancy so far. Unlike the rest of Python, with Traits, you can make sure that an attribute of an instance has the correct type. For example, "aMale.gender = aFemale" would throw an exception in the assignment.&lt;/p&gt;

&lt;p&gt;The nice stuff is that the UI components honor the information you use to build your model. So if you want to show a tree with all persons and genders, you use code like this:&lt;/p&gt;

&lt;div style='width:100%;overflow:auto;'&gt;
&lt;pre&gt;class Model(HasTraits):
    genderList = List(Gender)
    persons = List(Person)
    tree = Property
    
    def _get_tree(self):
        return self

class ModelView(View):
    def __init__(self):
        super(ModelView, self).__init__(
            Item('tree',
                editor=TreeEditor(
                    nodes = [
                       TreeNode(node_for = [ Model ],
                           children = 'persons',
                           label = '=Persons',
                           view = View(),
                       ),
                       TreeNode(node_for = [ Person ],
                           children = '',
                           label = 'name',
                           view = View(
                               Item('name'),
                               Item('gender',
                                  editor=EnumEditor(values=genderList,)
                               ),
                           ),
                       ),
                       TreeNode(node_for = [ Model ],
                           children = 'genderList',
                           label = '=Persons by Gender',
                           view = View(),
                       ),
                       TreeNode(node_for = [ Gender ],
                           children = '',
                           label = 'name',
                           view = View(),
                       ),
                    ],
                ),
            ),
            Item('genderList', style='custom'),
            title = 'Tree Test',
            resizable = True,
            width = .5,
            height = .5,
        )

model.configure_traits(view=ModelView())
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;First of all, I needed to add a property "tree" to my "Model" class. This is a calculated field which just returns "self" and I need this to be able to reference it in my tree editor. The tree editor defines nodes by defining their properties. So a "Model" node has "persons" and "genderList" as children. The tree view is smart enough to figure out that these are in fact lists of elements and it will try to turn each element into a node if it can find a definition for it.&lt;/p&gt;

&lt;p&gt;That's it. Everything else has already been defined in your model and what would be the point in doing that again?&lt;/p&gt;

&lt;p&gt;But there is more. With just a few more lines of code, we can get a list of all persons from a Gender instance and with just a single change in the tree view, we can see them in the view. If you select a person and change its name, all nodes in the tree will update. Without any additional wiring. Sounds too good to be true?&lt;/p&gt;

&lt;p&gt;First, we must be able to find all persons with a certain sex in Gender. To do that, we add a property which gives us access to the model and then query the model for all persons, filter this list by gender and that's it. Sounds complex? Have a look:&lt;/p&gt;

&lt;pre&gt;class Gender(HasTraits):
    name = Str
    persons = Property
    
    def _get_persons(self):
        return [p for p in self.model.persons
                if p.gender == self]
&lt;/pre&gt;

&lt;p&gt;But how do I define the attribute "model" in Gender? This is a hen-and-egg problem. Gender references Model and vice versa. Python to the rescue. Add this line after the definition of Model:&lt;/p&gt;

&lt;pre&gt;Gender.model = Instance(Model)
&lt;/pre&gt;

&lt;p&gt;That's it. Now we need to assign this new field in Gender. We could do this manually but Traits offers a much better way: You can listen for changes on genderList!&lt;/p&gt;

&lt;pre&gt;    def _genderList_items_changed(self, new):
        for child in new.added:
            child.model = self
&lt;/pre&gt;

&lt;p&gt;This code will be executed for every change to the list. I walk over the list of new children and assign "model".&lt;/p&gt;

&lt;p&gt;Does that work? Let's check: Append this line at the end of the file:&lt;/p&gt;

&lt;pre&gt;assert male.persons == [aMale], male.persons&lt;/pre&gt;

&lt;p&gt;And the icing of the cake: The tree. Just change the argument "children=''" to "children = 'persons'" in the TreeNode for Gender. Run and enjoy!&lt;/p&gt;

&lt;p&gt;One last polish: The editor for genders looks a bit ugly. To suppress the persons list, add this to the Gender class:&lt;/p&gt;

&lt;pre&gt;    traits_view = View(
        Item('name')
    )
&lt;/pre&gt;

&lt;p&gt;There is one minor issue: You can't assign a type to the property "persons" in Gender. If you do, you'll get strange exceptions and bugs. Other than that, this is probably the most simple way to build a tree of objects in your model that I've seen so far.&lt;/p&gt;

&lt;p&gt;To make things easier for you to try, here is the complete source again in one big block. You can download the &lt;a href="http://www.enthought.com/products/epd.php"&gt;Enthought Python Distribution&lt;/a&gt; which &lt;a href="http://www.enthought.com/products/epdlibraries.php"&gt;contains all and everything&lt;/a&gt; on the &lt;a href="http://www.enthought.com/"&gt;Enthought website&lt;/a&gt;.&lt;/p&gt;

&lt;div style='width:100%;overflow:auto;'&gt;
&lt;pre&gt;
from enthought.traits.api import \
        HasTraits, Str, Instance, List, Property, This

from enthought.traits.ui.api import \
        TreeEditor, TreeNode, View, Item, EnumEditor

class Gender(HasTraits):
    name = Str
    # Bug1: This works
    persons = Property
    # This corrupts the UI:
    # wx._core.PyDeadObjectError: The C++ part of the ScrolledPanel object has been 
    # deleted, attribute access no longer allowed.
    #persons = Property(List)
    
    traits_view = View(
        Item('name')
    )
    
    def _get_persons(self):
        return [p for p in self.model.persons if p.gender == self]
    
    def __repr__(self):
        return 'Gender %s' % self.name

class Person(HasTraits):
    name = Str
    gender = Instance(Gender)
    
    def __repr__(self):
        return 'Person %s' % self.name

# Bug1: This doesn't work; you'll get ForwardProperty instead of a list when
# you access the property "persons"!
#Gender.persons = Property(fget=Gender._get_persons, trait=List(Person),)
# Same
#Gender.persons = Property(trait=List(Person),)
# Same
#Gender.persons = Property()
# Same, except it's now a TraitFactory
#Gender.persons = Property

class Model(HasTraits):
    genderList = List(Gender)
    persons = List(Person)
    tree = Property
    
    def _get_tree(self):
        return self
    
    def _genderList_items_changed(self, new):
        for child in new.added:
            child.model = self

Person.model = Instance(Model)
Gender.model = Instance(Model)

female = Gender(name='Female')
male = Gender(name='Male')
undefined = Gender(name='Undefined')

aMale = Person(name='a male', gender=male)
aFemale = Person(name='a female', gender=female)

model = Model()
model.genderList.append(female)
model.genderList.append(male)
model.genderList.append(undefined)
model.persons.append(aFemale)
model.persons.append(aMale)

assert male.persons == [aMale], male.persons

# This must be extenal because it references "Model"
# Usually, you would define this in the class to edit
# as a class field called "traits_view".
class ModelView(View):
    def __init__(self):
        super(ModelView, self).__init__(
            Item('tree',
                editor=TreeEditor(
                    nodes = [
                       TreeNode(node_for = [ Model ],
                           children = 'persons',
                           label = '=Persons',
                           view = View(),
                       ),
                       TreeNode(node_for = [ Person ],
                           children = '',
                           label = 'name',
                           view = View(
                               Item('name'),
                               Item('gender',
                                  editor=EnumEditor(
                                      values=model.genderList,
                                  )
                               ),
                           ),
                       ),
                       TreeNode(node_for = [ Model ],
                           children = 'genderList',
                           label = '=Persons by Gender',
                           view = View(),
                       ),
                       TreeNode(node_for = [ Gender ],
                           children = 'persons',
                           label = 'name',
                           view = View(),
                       ),
                    ],
                ),
            ),
            Item('genderList', style='custom'),
            title = 'Tree Test',
            resizable = True,
            width = .5,
            height = .5,
        )

model.configure_traits(view=ModelView())
&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7017939649167308358?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7017939649167308358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7017939649167308358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7017939649167308358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7017939649167308358'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/enthought-traits.html' title='Enthought Traits'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4909218400046255723</id><published>2008-10-08T21:20:00.006+02:00</published><updated>2008-11-16T20:54:52.390+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='upcscan'/><category scheme='http://www.blogger.com/atom/ns#' term='PyQt4'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>UPCScan 0.6: It's Qt, Man!</title><content type='html'>&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; &lt;a href="http://darkviews.blogspot.com/2008/11/upcscan-07-where-is-my-stuff.html"&gt;Version 0.7 released&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Getting drowned in your ever growing CD, DVD, book or comic collection? Then UPCScan might be for you.&lt;/p&gt;

&lt;p&gt;UPCScan 0.6 is ready for download. There are many fixed and improvements. The biggest one is probably the live PyQt4 user interface (live means that the UI saves all your changes instantly, so no data loss if your computer crashes because of some other program ;-)).&lt;/p&gt;

&lt;p&gt;The search field accepts barcodes (from a barcode laser scanner) and ISBN numbers. There is a nice cover image dialog where you can download and assign images if Amazon doesn't have one. Note: Amazon sometimes has an image but it's marked as "customer image". Use the "Visit" button on the UI to check if an image is missing and click on the "No Cover" button to open the "Cover Image" dialog where you can download and assign images. I haven't checked if the result of the search query contains anything useful in this case.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.pdark.de/upcscan-0.6.tar.gz"&gt;UPCScan 0.6&lt;/a&gt; - 24,055 bytes, &lt;a href="http://www.pdark.de/upcscan-0.6.md5sum"&gt;MD5 Checksum&lt;/a&gt;. Needs &lt;a href="http://www.python.org/download/releases/2.5.2/"&gt;Python 2.5&lt;/a&gt;. &lt;a href="http://www.riverbankcomputing.co.uk/software/pyqt/download"&gt;PyQt4 4.4.3&lt;/a&gt; is optional.&lt;/p&gt;

&lt;p&gt;Security notice: You need an Amazon Web Service Account (get one &lt;a href="http://aws.amazon.com/"&gt;here&lt;/a&gt;). When you run the program for the first time, it will tell you what to do. This means two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your queries will be logged. So if you don't want Amazon to know what you own, this program is not very useful for you.&lt;/li&gt;

&lt;li&gt;Your account ID will be stored in the article database at various places. I'm working on an export function which filters all private data out. Until then, don't give this file to your friends unless you know what that means (and frankly, I don't). You have been warned.&lt;/li&gt;

&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4909218400046255723?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4909218400046255723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4909218400046255723' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4909218400046255723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4909218400046255723'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/upcscan-06-its-qt-man.html' title='UPCScan 0.6: It&apos;s Qt, Man!'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2510057929924319565</id><published>2008-10-07T09:34:00.001+02:00</published><updated>2008-10-07T09:35:43.083+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Name of the Longest Distance Between Two Points</title><content type='html'>&lt;p&gt;Q: What's the name of the shortest distance between two points?&lt;/p&gt;
&lt;p&gt;A: The straight line.&lt;/p&gt;

&lt;p&gt;Q: What's the name of the &lt;b&gt;longest&lt;/b&gt; distance between two points?&lt;/p&gt;
&lt;p&gt;A: The shortcut.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2510057929924319565?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2510057929924319565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2510057929924319565' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2510057929924319565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2510057929924319565'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/name-of-longest-distance-between-two.html' title='Name of the Longest Distance Between Two Points'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-9032659432029857455</id><published>2008-10-06T10:15:00.003+02:00</published><updated>2008-10-06T10:28:37.913+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>You Can't Stop OOXML!? Watch Me :-)</title><content type='html'>&lt;p&gt;MicroSoft is the de-facto standard on the desktop. Despite all the efforts to break the monopoly, the average user still doesn't want to switch. Alas, the average user is not an expert and when MicroSoft tries its way with the experts, that usually backfires. Unlike the Average Joe, geeks and nerds are no cattle and they find creative ways to get even when they are served what MicroSoft dishes out.&lt;/p&gt;

&lt;p&gt;So in Norway, 21 of 23 experts voted &lt;b&gt;against&lt;/b&gt; OOXML as a new ISO standard. That didn't stop the ca...administration of &lt;a href="http://www.standard.no/"&gt;Standard Norge&lt;/a&gt; to embrace this great work from Seattle (which has eaten thousands, maybe millions, of dissertations over the years) and so they announced that Norway votes "Yes". Every geek out there knows what it means when your management has stopped listening to you: Get a new job. And &lt;a href="http://www.heise.de/newsticker/OOXML-Standardisierung-Norwegische-Experten-treten-zurueck--/meldung/116944"&gt;they did&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Right on, commander!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-9032659432029857455?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/9032659432029857455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=9032659432029857455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/9032659432029857455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/9032659432029857455'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/you-cant-stop-ooxml-watch-me.html' title='You Can&apos;t Stop OOXML!? Watch Me :-)'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5373318331222704060</id><published>2008-10-06T10:10:00.002+02:00</published><updated>2008-10-06T10:28:52.324+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Somebody is Playing Pong With Two Elevators and the Floorlights...</title><content type='html'>&lt;p&gt;Once, it was just a &lt;a href="http://ars.userfriendly.org/cartoons/?id=19990203"&gt;joke in the UserFriendly comic strip&lt;/a&gt;. Now, it's real: &lt;a href="http://www.blinkenlights.net/"&gt;Welcome to Project Blinkenlights&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5373318331222704060?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5373318331222704060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5373318331222704060' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5373318331222704060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5373318331222704060'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/somebody-is-playing-pong-with-two.html' title='Somebody is Playing Pong With Two Elevators and the Floorlights...'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-55527990242902788</id><published>2008-10-04T22:59:00.004+02:00</published><updated>2008-10-08T22:25:02.860+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='upcscan'/><category scheme='http://www.blogger.com/atom/ns#' term='Tool'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Scanning Your DVD, Book, Comic, ... Collection</title><content type='html'>&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; &lt;a href="http://darkviews.blogspot.com/2008/10/upcscan-06-its-qt-man.html"&gt;Version 0.6 released&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're like me, you have a lot of DVDs, books, comics, whatever ... and a few years ago, you kind of lost your grip on your collection. Whenever there is a DVD sale, you invariantly come home with a movie you already have.&lt;/p&gt;

&lt;p&gt;After the German Linux Magazin published an &lt;a href="http://www.linux-magazin.de/heft_abo/ausgaben/2008/10/kein_etikettenschwindel"&gt;article how to setup a laser scanner with Amazon&lt;/a&gt;, I decided to get me one and give it a try. Unfortunately, the Perl script has a few problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's written in Perl.&lt;/li&gt;

&lt;li&gt;It's written in Perl.&lt;/li&gt;

&lt;li&gt;It's written in Perl.&lt;/li&gt;

&lt;li&gt;There is no download link for the script without line numbers.&lt;/li&gt;

&lt;li&gt;The DB setup script is missing.&lt;/li&gt;

&lt;li&gt;The script uses POE.&lt;/li&gt;

&lt;li&gt;It's hard to add new services.&lt;/li&gt;

&lt;li&gt;Did I mention that it's written in Perl? Right.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;So I wrote a &lt;a href="http://www.pdark.de/upcscan-0.1.tgz"&gt;new version in Python&lt;/a&gt;. You can find the docs how to use it in the header of each file. Additionally, I've included a file "Location codes.odt". You can edit it with OpenOffice and put the names of the places where you store your stuff in there. Before you start to scan in the EAN/UPC codes of the stuff in a new place, scan the location code and upcscan.py will make the link for you. It will also ask you for a nice name of the location when you scan a location code for the first time.&lt;/p&gt;

&lt;p&gt;If you need more location codes, you can generate them yourself. The codes starting with "200" are for private use, so there is no risk of a collision. I'm using this &lt;a href="http://www.dlr.de/jupex/barcode/barcode.html"&gt;Python script to generate the GIF images&lt;/a&gt;. Just put this at the end of the script:&lt;/p&gt;

&lt;pre&gt;if __name__=='__main__':
    import sys
    s = checksum(sys.argv[1])
    img = genbarcode(s, 1)
    img.save('EAN13-%s.gif' % s, 'GIF')
    print error
&lt;/pre&gt;

&lt;p&gt;There is a primitive tool to generate a HTML page from your goods and a small tool to push your own cover images into the database if Amazon doesn't provide one.&lt;/p&gt;

&lt;p&gt;Note: You'll need an &lt;a href="http://aws.amazon.com/"&gt;AWS account&lt;/a&gt; for the script to work. The script will tell you where to get your account ID and where you need to put the ID when you start it for the first time.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.pdark.de/upcscan-0.1.tgz"&gt;Download upscan-0.1.tar.gz&lt;/a&gt; (54KB, &lt;a href="http://www.pdark.de/upcscan-0.1.md5sum"&gt;MD5 Checksum&lt;/a&gt;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-55527990242902788?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/55527990242902788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=55527990242902788' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/55527990242902788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/55527990242902788'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/10/scanning-your-dvd-book-comic-collection.html' title='Scanning Your DVD, Book, Comic, ... Collection'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-8383629960056354431</id><published>2008-09-29T10:22:00.002+02:00</published><updated>2008-10-14T17:31:20.852+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Firefox 3.0.1 and GMail: Gray Background???</title><content type='html'>&lt;p&gt;Am I the only one who gets a gray background on many websites after the update to Firefox 3.0.1?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; Apparently so. If not, browse to &lt;a href="about:config"&gt;about:config&lt;/a&gt; and search for "browser.display.background_color". In my version of FF, that was set to #C0C0C0 for some reason (when it should have been #FFFFFF).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-8383629960056354431?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/8383629960056354431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=8383629960056354431' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8383629960056354431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8383629960056354431'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/09/firefox-301-and-gmail-gray-background.html' title='Firefox 3.0.1 and GMail: Gray Background???'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5100217689411487293</id><published>2008-09-29T09:58:00.003+02:00</published><updated>2008-09-29T10:25:52.736+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Installing Eclipse 3.4.1 Despite p2</title><content type='html'>&lt;p&gt;If you're, like me, one of the unlucky ones that aren't on p2's friends list (translation: Eclipse p2 provisioning causes you an endless stream of pain and suffering), then you can't install the 3.4.1 patches because &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=248694"&gt;p2 won't let yo&lt;/a&gt;u.&lt;/p&gt;

&lt;p&gt;There are several ways to deal with this. &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=248693"&gt;One of them&lt;/a&gt; is to delete your workspace's .metadata, your Eclipse install and start from scratch, installing all plug-ins again, etc., always hoping that p2 doesn't mess up until you've installed everything.&lt;/p&gt;

&lt;p&gt;The other way is a workaround. It needs a bit of disk space and discipline. Do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Leave your original Eclipse install alone. Specifically, &lt;b&gt;never ever&lt;/b&gt; use the menu "Software updates..." again! &lt;b&gt;Never&lt;/b&gt;. I &lt;b&gt;mean&lt;/b&gt; it. Disable the entry if you can.&lt;/li&gt;

&lt;li&gt;Install eclipse again in a new place. This must be a standard install (not a shared one!!!)&lt;/li&gt;

&lt;li&gt;&lt;b&gt;Do not start this install! Specifically, do not attempt to add all your update sites to this base template!&lt;/b&gt; Just unpack it and rename the "eclipse" directory to "eclipse-template".&lt;/li&gt;

&lt;li&gt;Copy "eclipse-template" to "eclipse-install".&lt;/li&gt;

&lt;li&gt;Start eclipse-install. If you worry that you might accidentally start the template once in a while, rename "eclipse.exe" to "eclipse.exe Is this install".&lt;/li&gt;

&lt;li&gt;Download the 3.4.1 updates.&lt;/li&gt;

&lt;li&gt;Exit eclipse-install.&lt;/li&gt;

&lt;li&gt;Use your favorite file copy tool to copy all new files and directories in eclipse-install\plugins and eclipse-install\features to your working copy of eclipse.&lt;/li&gt;

&lt;li&gt;Start your working copy.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Installing and updating plug-ins works in a similar way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete eclipse-install and recreate it from eclipse-template.&lt;/li&gt;

&lt;li&gt;Start eclipse-install.&lt;/li&gt;

&lt;li&gt;Open the install software dialog. Add the update site. You may be tempted to add the update sites to eclipse-template. &lt;b&gt;Don't do this!&lt;/b&gt; As soon as p2 can see more than one update site, it will eventually mess up in the dependency calculation.&lt;/li&gt;

&lt;li&gt;Install the plug-in.&lt;/li&gt;

&lt;li&gt;Create a directory for your new plug-in in the driectory "dropins" of your working copy of Eclipse.&lt;/li&gt;

&lt;li&gt;Copy the new files and directories from eclipse-install\features and eclipse-install\plugins to the new directory below "dopins" in your working copy of Eclipse.&lt;/li&gt;

&lt;li&gt;If you need to install more than one plug-in, start with step 1. After you have installed anything in eclipse-install, the Eclipse instance is tainted and shouldn't be used again.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;That's all folks. At least until the p2 guys fix the many bugs in their code. Which will probably in the Eclipse release in 2010.&lt;/p&gt;

&lt;p&gt;That's not because I believe that the p2 guys are stupid or lazy but because this kind of product just takes three years to mature and they started in 2007, so the first working version can be expected in 20010.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5100217689411487293?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5100217689411487293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5100217689411487293' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5100217689411487293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5100217689411487293'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/09/installing-eclipse-341-despite-p2.html' title='Installing Eclipse 3.4.1 Despite p2'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2537670752803813676</id><published>2008-09-18T20:44:00.002+02:00</published><updated>2008-09-18T20:46:20.188+02:00</updated><title type='text'>Stack Overflow Launches</title><content type='html'>&lt;p&gt;&lt;a href="http://stackoverflow.com/"&gt;Stack Overflow&lt;/a&gt; is a Q&amp;A site for programmers. If you're looking for an answer to a question or if you know a lot and can't really fill your needs to help in your current position, have a go at it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2537670752803813676?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2537670752803813676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2537670752803813676' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2537670752803813676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2537670752803813676'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/09/stack-overflow-launches.html' title='Stack Overflow Launches'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-8096994721986779095</id><published>2008-09-08T10:26:00.002+02:00</published><updated>2008-09-08T10:33:26.464+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Amiga'/><title type='text'>Amiga Forever 2008</title><content type='html'>&lt;p&gt;I have the set for a while now (thanks Michele!) and after reading the announcement elsewhere, I'd like to remind all you Amiga fans out there that the 2008 release of &lt;a href="http://www.amigaforever.com/"&gt;Amiga Forever&lt;/a&gt; is ready. Did you know that &lt;a href="http://en.wikipedia.org/wiki/Andy_Warhol"&gt;Andy Warhol&lt;/a&gt; (yeah, &lt;b&gt;that&lt;/b&gt; Andy Warhol) gave a demo of the system when it was launched 1985? If not, grab the premium edition and watch him do his thing with &lt;a href="http://images.google.ch/images?q=marilyn+monroe"&gt;Marilyn Monroe&lt;/a&gt; (or rather a picture of her).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-8096994721986779095?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/8096994721986779095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=8096994721986779095' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8096994721986779095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8096994721986779095'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/09/amiga-forever-2008.html' title='Amiga Forever 2008'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6801692662625385253</id><published>2008-09-05T15:58:00.001+02:00</published><updated>2008-09-05T16:00:05.208+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>How To Launch Software</title><content type='html'>&lt;p&gt;If you're still wondering if "big bang" software releases are a good thing, &lt;a href="http://www.aaronsw.com/weblog/howtolaunch"&gt;read this&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6801692662625385253?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6801692662625385253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6801692662625385253' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6801692662625385253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6801692662625385253'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/09/how-to-launch-software.html' title='How To Launch Software'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-540327991558465726</id><published>2008-08-31T21:21:00.002+02:00</published><updated>2008-08-31T22:02:16.524+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Text Editor'/><title type='text'>The Space Between Two Characters</title><content type='html'>&lt;p&gt;&lt;i&gt;If you're claustrophobic, you're afraid of confined spaces. If you're a software developer, you can be afraid of non-existing space.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;When it comes to editing text, we usually don't think about the space between the characters. There simply isn't any. When you write a text editor, things start to look different. Suddenly, you have a caret or cursor which goes between the characters and that space between two characters can suddenly become uncomfortably tight.&lt;/p&gt;

&lt;p&gt;Fire up your favorite text editor, Word, Writer, whatever. It has to support character formatting, though. Now enter this:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Hello&lt;/b&gt;, &lt;i&gt;world!&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;If in doubt, the bold text ends before the comma and the italic part starts with the "w" and ends with "!" including both.&lt;/p&gt;

&lt;p&gt;Now move to the "e" and type "x". What do you get?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Hxello&lt;/b&gt;, &lt;i&gt;world!&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Piece of cake.&lt;/p&gt;

&lt;p&gt;Now move to the "H" and type "x". What do you get? Is the new x bold or not? Do you get "&lt;b&gt;xHxello&lt;/b&gt;" or "x&lt;b&gt;Hxello&lt;/b&gt;"? How about typing "x" after the "o" of our abused "Hello"? Is that new x bold or not? If it is, what is the most simple way to make it non-bold? Do you have to delete the comma, do you have to go through menus or toolbars or is there a simple, consistent way to add a character inside and outside of a formatted range of text?&lt;/p&gt;

&lt;p&gt;Let's go one step further. Add a character after the "!". Is it italic? If not, you're lucky. If it is ... what's the most simple way to you get rid of the italic? If you press Return now, will the italic leak to the next line? If not, how can you make it leak? If that italic is the last thing in your text, can you add non-italic text beyond without fumbling with the formatting options?&lt;/p&gt;

&lt;p&gt;There is no space between two characters and when you write a text editor, that non-existing space is biting you. Which is actually the problem: There is no consistent way to move in and out of a formatted range of characters.&lt;/p&gt;

&lt;p&gt;The naive attempt would be to say "depending on the side you came from, you're inside or outside." So, if we have this (| is the cursor or caret): "&lt;b&gt;Hello&lt;/b&gt; |&lt;i&gt;world&lt;/i&gt;" and you type something, the question is: How did the caret end there? Did it come from "w|o" and moved one to the left? Or from "o|&amp;nbsp;" and move one position right?&lt;/p&gt;

&lt;p&gt;That works somewhat but it fails at the beginning and the end of the text plus you're in trouble during deleting text. What should happen after the last character of "Hello" has been deleted? Should that also delete the character range or should there be an empty, invisible bold range left and when you type something now, it should appear again? If you keep the empty invisible range, when do you drop it? Do you keep it as long as the user stays "in" it? Or until the document is saved? Loaded again from disk?&lt;/p&gt;

&lt;p&gt;It's a mess and there is a reason why neither Word nor OpenOffice get it right: You can't. There is information in the head of the user (what she wants) but no way for her to tell the computer. Duh.&lt;/p&gt;

&lt;p&gt;That is, unless you start to give the user a visual cue what is going on. The problems we have is that there is no simple, obvious way for the user to say "I want ..." because there is no space on the screen reserved for this. We barely manage to squeeze a caret between the characters. There is just not enough room.&lt;/p&gt;

&lt;p&gt;Well, there could be. A simple solution might be to add a little hint to the cursor to show which way it is leaning right now. Right. How about "&lt;b&gt;A&lt;/b&gt;|&lt;i&gt;B&lt;/i&gt;"? Here, you have &lt;i&gt;three&lt;/i&gt; options. Add bold, italic and normal.&lt;/p&gt;

&lt;p&gt;In HTML, this is simple. I'm editing this text in Firefox using the standard text area. What looks fancy to you looks like this to me: "&amp;lt;b&amp;gt;A&amp;lt;/b&amp;gt;|&amp;lt;i&amp;gt;B&amp;lt;/i&amp;gt;"&lt;/p&gt;

&lt;p&gt;And this is the solution: I need to add a visual cue for the start and end of the format ranges. Maybe a simple U-shape which underlines the text for which the character format applies. Or an image (&amp;gt; and &amp;lt; in this example): "&amp;gt;&lt;b&gt;A&lt;/b&gt;&amp;lt;|&amp;gt;&lt;i&gt;B&lt;/i&gt;&amp;lt;". And suddenly, it's completely obvious on which side of the range start and end you are and what you want. You can delete the text in the range without losing it or you can delete both and you can move in and out of the range at will.&lt;/p&gt;

&lt;p&gt;The drawback is that you need to keep that information somewhere. It adds a pretty huge cost to the limits of a format range. I'll have to try and see how much that is and if I can get away with less by cleverly using the information I already have.&lt;/p&gt;

&lt;p&gt;Also, it clearly violates &lt;a href="http://en.wikipedia.org/wiki/WYSIWYG"&gt;WHYSIWYG&lt;/a&gt;. On the other hand, we get &lt;a href="http://en.wikipedia.org/wiki/WYSIWYW"&gt;WYSIWYW&lt;/a&gt; which is probably better for the user.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-540327991558465726?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/540327991558465726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=540327991558465726' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/540327991558465726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/540327991558465726'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/space-between-two-characters.html' title='The Space Between Two Characters'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6525924082717242354</id><published>2008-08-31T15:55:00.002+02:00</published><updated>2008-08-31T15:56:12.549+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='DecentXML'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>DecentXML 1.2</title><content type='html'>&lt;p&gt;DecentXML 1.2, my own XML 1.1-compliant parser, is &lt;a href="http://code.google.com/p/decentxml/downloads/list"&gt;now available&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6525924082717242354?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6525924082717242354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6525924082717242354' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6525924082717242354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6525924082717242354'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/decentxml-12.html' title='DecentXML 1.2'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5571720903337811656</id><published>2008-08-27T21:35:00.003+02:00</published><updated>2008-08-27T21:43:58.891+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jads'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Text Editor'/><title type='text'>Text Editor Component and JADS</title><content type='html'>&lt;p&gt;While working on &lt;a href="http://code.google.com/p/decentxml/"&gt;DecentXML&lt;/a&gt; (1.2 due this weekend), I've had those other two things that were bugging me. One is that there is no high-quality, open-source framework with algorithms and data structures. I'm not talking about java.lang.Collections, I'm talking about red-black trees, interval trees, gap buffers, things like that. Powerful data structures you need to build complex software.&lt;/p&gt;

&lt;p&gt;Welcome the "Java Algorithm and Data Structure" project - jads. I haven't started opened a project page on SourceForge or Google Code, yet, but I'll probably do that this weekend.&lt;/p&gt;

&lt;p&gt;Based on that, I'm working on a versatile text editor component for Java software. The final editor will work with user interfaces implemented in Swing, SWT and Qt. It's an extensible framework where you can easily replace parts with your own code to get the special features you need. I currently have a demo running which can display text, which allows scrolling and where you can do some basic editing. Nothing fancy but it's coming alone nicely.&lt;/p&gt;

&lt;p&gt;If you want to hear more about these projects, post a comment or drop me a mail.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5571720903337811656?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5571720903337811656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5571720903337811656' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5571720903337811656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5571720903337811656'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/text-editor-component-and-jads.html' title='Text Editor Component and JADS'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7364880705410381030</id><published>2008-08-19T14:30:00.003+02:00</published><updated>2008-08-21T14:22:24.041+02:00</updated><title type='text'>Death Star in EVE Online</title><content type='html'>&lt;p&gt;Apparently, a group of 4000 players of &lt;a href="http://www.heise.de/newsticker/Rollenspiel-Entwickler-Gudmundsson-Wir-sind-Goetter--/meldung/114431/from/rss09"&gt;EVE Online&lt;/a&gt; have built a kind of a "Death Star" (a "titan ship" in the language of the game) to rule the game galaxy. Assembly took 8 months in total secrecy and the result was destroyed completely within 3 months.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7364880705410381030?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7364880705410381030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7364880705410381030' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7364880705410381030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7364880705410381030'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/death-star-in-eve-online.html' title='Death Star in EVE Online'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5634935899124575122</id><published>2008-08-19T09:20:00.002+02:00</published><updated>2008-08-19T09:30:59.595+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>Another Lesson on Performance</title><content type='html'>&lt;p&gt;Just another story you can tell someone who fears that "XYZ might be too slow":&lt;/p&gt;

&lt;p&gt;I'm toying with the idea to write a new text editor. I mean, I've written &lt;a href="http://www.aros.org/"&gt;my own OS&lt;/a&gt;, my own &lt;a href="http://code.google.com/p/decentxml/"&gt;XML parser&lt;/a&gt; and I once maintained &lt;a href="http://aminet.net/search?query=xdme"&gt;XDME&lt;/a&gt;, an editor written originally by &lt;a href="http://apollo.backplane.com/"&gt;Matthew Dillon&lt;/a&gt;. XDME has a couple of bugs and major design flaws that I always wanted to fix but never really got to it. Anyway.&lt;/p&gt;

&lt;p&gt;There are various data structures which are suitable for a text editor and some of those depend on copying data around (see &lt;a href="http://en.wikipedia.org/wiki/Gap_buffer"&gt;gap buffers&lt;/a&gt;). The question is: How effective is that? The first instinct of a developer is to avoid copying large amounts data and to optimize the data structure instead.&lt;/p&gt;

&lt;p&gt;After years of training, I've yet to overcome this instinct and start to measure:&lt;/p&gt;

&lt;pre&gt;    public static void main (String[] args)
    {
        long start = System.currentTimeMillis ();
        
        int N = 10000;
        for (int i=0; i&amp;lt;N; i++)
        {
            int[] buffer = new int[1024*1024];
            System.arraycopy (buffer, 0, buffer, 1,
                buffer.length-1);
        }
        
        long duration = System.currentTimeMillis () - start;
        System.out.println (duration);
        System.out.println (duration / N);
    }&lt;/pre&gt;

&lt;p&gt;On my computer at work (which is pretty fast but not cutting edge), prints: "135223" and "13". That's &lt;b&gt;thirteen milliseconds&lt;/b&gt; to copy 4MB of RAM. Okay. It's obviously not worth to spend a second to think about the cost of moving data around in a big block of bytes.&lt;/p&gt;

&lt;p&gt;Lesson: If you're talking about performance and you didn't measure, you have no idea what you're talking about.&lt;/p&gt;

&lt;p&gt;Still not convinced? Read &lt;a href="http://ahmadsoft.org/articles/recursion/index.html"&gt;this&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5634935899124575122?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5634935899124575122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5634935899124575122' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5634935899124575122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5634935899124575122'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/another-lesson-on-performance.html' title='Another Lesson on Performance'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-193529989955668661</id><published>2008-08-04T17:38:00.001+02:00</published><updated>2008-08-04T17:40:05.727+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Quantity Always Trumps Quality</title><content type='html'>&lt;p&gt;While I wouldn't completely subscribe to that without a grain of salt, &lt;a href="http://www.codinghorror.com/blog/archives/001160.html"&gt;the story is nice&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-193529989955668661?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/193529989955668661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=193529989955668661' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/193529989955668661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/193529989955668661'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/quantity-always-trumps-quality.html' title='Quantity Always Trumps Quality'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2192608726064365762</id><published>2008-08-04T14:24:00.003+02:00</published><updated>2008-08-04T15:04:56.083+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Four harmful Java idioms, and how NOT to fix them</title><content type='html'>&lt;p&gt;In his article "&lt;a href="http://www.javaworld.com/javaworld/jw-07-2008/jw-07-harmful-idioms.html"&gt;Four harmful Java idioms, and how to fix them&lt;/a&gt;", John O'Hanley writes about how to make Java more maintainable. He picks four common patterns and gives tips how to fix them ... or not. Follow me.&lt;/p&gt;

&lt;h3&gt;Names&lt;/h3&gt;

&lt;p&gt;The first idea is to prefix names with a letter giving a hint what they mean: Is "start" a method? A field? A parameter? The goal is to make the code more readable to humans.&lt;/p&gt;

&lt;p&gt;Unfortunately, this doesn't work. The human brain doesn't read letters, it reads words. So "fStart" (meaning a field with the name "start") is rejected by the brain because it's not a word. This triggers the conscious analysis which John tries to avoid! Which is why modern IDEs use color to tell you what something is: The brain can decode color and words in independent parts - unconsciously.&lt;/p&gt;

&lt;h3&gt;Packaging Convention&lt;/h3&gt;

&lt;p&gt;Next, he moves on how to split code into packages. Currently, we use a "package by layer" scheme, meaning all DB code goes into one  package and the model code into another and UI layer in a third, etc. He proposes to use a "by-feature" packaging with the litmus test "you should be able to delete a feature by deleting a single directory, without leaving behind any cruft".&lt;/p&gt;

&lt;p&gt;Uhm. When have you ever written any code where you could remove a feature just by deleting a class? This &lt;em&gt;sounds&lt;/em&gt; nice and simple but it's fails Einstein's litmus test: "Make it as simple as possible but not more simple". Even if you have a plug-in based software like Eclipse, this doesn't work because there are still references outside (otherwise, your plug-in wouldn't be able to do anything).&lt;/p&gt;

&lt;p&gt;Also, to keep a feature as isolated from everything else as possible (which is a good thing), you need to copy a lot of code into the feature which would otherwise reside elsewhere, neatly packed up in its own package. Really just a limitation of Java where you can't tell the compiler to generate boiler plate code for you. Still, you need to cut code in such a way that it reduces dependencies, not increases them. Therefore, a general rule won't cut (or maybe it will cut: you).&lt;/p&gt;

&lt;h3&gt;Immutables&lt;/h3&gt;

&lt;p&gt;John quotes: "'Classes should be immutable unless there is a very good reason for making them mutable,' says Bloch.". And later: "From a practical perspective, many widely-used frameworks require application programmers to use JavaBeans (or something similar) to model database records. This is deeply unfortunate, because it doesn't allow programmers to take advantage of the many positive qualities of immutable objects."&lt;/p&gt;

&lt;p&gt;From a practical perspective, immutable objects are dead weight. Applications are all about changing something. I read data from the database, I modify it, I write it back. I rarely read, display and forget about something. Yes, immutables have advantages because they can be shared between threads but that's their only advantage.&lt;/p&gt;

&lt;p&gt;Just think about this: You must modify data from the database. So you read the data into an immutable. How to modify it, now? Obviously, you need a method to change it. If you prefer setters, the "setter" must return a copy. So you need to copy the object for &lt;em&gt;every single change&lt;/em&gt;. If you want to get a feeling for that, try to do math with &lt;tt&gt;BigDecimal&lt;/tt&gt;. Okay, after the copy you can write the copy back to the database. Question: How do you notify everyone else who might have a (now stale) copy of the old immutable? There are no listeners; immutables can't have listeners. Duh. Driving this to the extreme, lists wouldn't offer methods to add or remove items; or rather they would return new copies of themselves after every add/remove operation.&lt;/p&gt;

&lt;p&gt;Sorry, no sale. I can't add money to my cash register. It's immutable.&lt;/p&gt;

&lt;p&gt;And a colleague just introduced me to another great concept: Constructors which require values for all fields. The class in question has 95 fields. This idea has the following flaws: a) No matter how big your screen, you can't fit the call onto it. b) After argument #10, you lost track and you can't see anymore which value goes into which argument. Now imagine you have to remove a field. How do you find the right one in this mega-call?&lt;/p&gt;

&lt;p&gt;No, nothing beats the no-arg constructor plus a list of setters, all costs considered.&lt;/p&gt;

&lt;h3&gt;Private members&lt;/h3&gt;

&lt;p&gt;John proposes to move private members to the end of the class. Here, I agree. I'd even put them close to the getter and setter so that a lot of stuff that belongs together is together.&lt;/p&gt;

&lt;p&gt;In todays IDEs with their superb code navigation (I can't really believe there was a time before the F3 key), this doesn't matter much, though.&lt;/p&gt;

&lt;p&gt;Conclusion: Think about it, but don't bother.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2192608726064365762?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2192608726064365762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2192608726064365762' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2192608726064365762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2192608726064365762'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/four-harmful-java-idioms-and-how-not-to.html' title='Four harmful Java idioms, and how NOT to fix them'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3229959097485048979</id><published>2008-08-01T21:45:00.001+02:00</published><updated>2008-08-31T15:56:35.243+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='DecentXML'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>DecentXML 1.1</title><content type='html'>&lt;p&gt;I've just &lt;a href="http://code.google.com/p/decentxml/wiki/Changelog"&gt;released 1.1&lt;/a&gt; of &lt;a href="http://code.google.com/p/decentxml/"&gt;DecentXML&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3229959097485048979?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3229959097485048979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3229959097485048979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3229959097485048979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3229959097485048979'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/08/decentxml-11.html' title='DecentXML 1.1'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-182045763975338142</id><published>2008-07-30T21:50:00.004+02:00</published><updated>2008-07-30T23:08:27.506+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>Update to DecentXML</title><content type='html'>&lt;p&gt;I've updated my XML parser. The tests now cover 97.7% of the code (well, actually 100% of the code which can be executed; there are a couple of exceptions which will never be thrown but I still have to handle them) and there are classes to read XML from &lt;tt&gt;InputStream&lt;/tt&gt; and &lt;tt&gt;Reader&lt;/tt&gt; sources (including encoding detection).&lt;/p&gt;

&lt;p&gt;The &lt;tt&gt;XMLInputStreamReader&lt;/tt&gt; class can be used standalone, if you ever want to read an XML file with the correct encoding.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="http://code.google.com/p/decentxml/downloads/list"&gt;download&lt;/a&gt; the &lt;a href="http://code.google.com/p/decentxml/source/checkout"&gt;sources&lt;/a&gt; and &lt;a href="http://code.google.com/p/decentxml/issues/list"&gt;report issues&lt;/a&gt; in the new &lt;a href="http://code.google.com/p/decentxml/"&gt;Google Code project&lt;/a&gt; I've created.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-182045763975338142?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/182045763975338142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=182045763975338142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/182045763975338142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/182045763975338142'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/update-to-decentxml.html' title='Update to DecentXML'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-8013101832307904820</id><published>2008-07-30T13:41:00.003+02:00</published><updated>2008-07-30T13:47:27.613+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Information Management'/><title type='text'>Information Management With Zotero</title><content type='html'>&lt;p&gt;I've been long looking for a nice tool to manage my vast extra-brain information collection, i.e. the stuff that I don't want to save in my long term memory. Web snippets, notes, that kind of stuff. All the usual solutions didn't appeal to me. Either I was locked to Windows or to a single computer or the UI was bad or the feature list lacked some important points.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.zotero.org/"&gt;Zotero&lt;/a&gt; to the rescue. This beast is advertised as "Zotero [zoh-TAIR-oh] is a free, easy-to-use  Firefox extension to help you collect, manage, and cite your research sources. It lives right where you do your work — in the web browser itself."&lt;/p&gt;

&lt;p&gt;Which makes sense. I watch most of my information in my web browser, so why no collect it in there, too? The UI is nice, I'm just &lt;a href="http://forums.zotero.org/discussion/3652/working-with-website-snapshots/#Item_1"&gt;missing a few features&lt;/a&gt;. Also being able to &lt;a href="http://forums.zotero.org/discussion/3574/share-on-local-servers/#Item_0"&gt;sync with my own server&lt;/a&gt; would be nice. But I'm sure that will be fixed, soon. In the mean time, I can at least tag and order my snippets.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-8013101832307904820?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/8013101832307904820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=8013101832307904820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8013101832307904820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8013101832307904820'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/information-management-with-zotero.html' title='Information Management With Zotero'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7573527392209045568</id><published>2008-07-29T22:21:00.005+02:00</published><updated>2008-08-31T15:56:35.244+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='DecentXML'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>A Decent XML Parser</title><content type='html'>&lt;p&gt;Since there isn't one, I've started writing one myself. Main features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows 100% round-tripping, even for weird whitespace between attributes in elements&lt;/li&gt;

&lt;li&gt;Suitable for building editors and filters which want to preserve the original file layout&lt;/li&gt;

&lt;li&gt;Error messages have line and column information&lt;/li&gt;

&lt;li&gt;Easy to reuse&lt;/li&gt;

&lt;li&gt;XML 1.0 compatible&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;You can &lt;a href="http://www.pdark.de/decentxml-1.0-SNAPSHOT-src.tar.gz"&gt;download the latest sources here&lt;/a&gt; as a &lt;a href="http://maven.apache.org/"&gt;Maven 2&lt;/a&gt; project.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7573527392209045568?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7573527392209045568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7573527392209045568' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7573527392209045568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7573527392209045568'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/decent-xml-parser.html' title='A Decent XML Parser'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-76995518790926402</id><published>2008-07-28T17:29:00.003+02:00</published><updated>2008-07-28T17:35:57.320+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>DSLs: Introducing Slang</title><content type='html'>&lt;p&gt;Did you ever ask for a more compact way to express something in your favorite programming language? Say hello to DSL (Domain Specific Language). A DSL is a slang, a compact way to say what you want. When two astronauts talk, they use slang. They need to get information across and presto. "Over" instead of "I'll now clear the frequency so you can start talking." And when these guys do it, there's no reason for us not to.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.javaworld.com/javaworld/jw-07-2008/jw-07-dsls-in-java-2.html"&gt;Here is an artical&lt;/a&gt; on Java World which gives some nice examples how to create a slang in Java and in Groovy. Pizza-lovers of the world, eat your heart out.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-76995518790926402?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/76995518790926402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=76995518790926402' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/76995518790926402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/76995518790926402'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/dsls-introducing-slang.html' title='DSLs: Introducing Slang'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6728034633594459817</id><published>2008-07-28T15:49:00.002+02:00</published><updated>2008-07-28T16:04:51.490+02:00</updated><title type='text'>FREE! Really.</title><content type='html'>&lt;p&gt;I just found a nice comment under my blog. It offered a free service. One sentence was: "REGISTRATION IS ABSOLUTELY FREE!" When you see that, you know you're being ripped off. I'm not mentioning the name of the guys who tried that stunt in order to give them no additional advertisement. 'Nuff said.&lt;/p&gt;

&lt;p&gt;Tip: If you want me to join your planet or RSS mega feed or whatever, it's not smart to post a comment in my blog. This is my blog, my reputation, my honor. I decide who gets free advertisement here.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6728034633594459817?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6728034633594459817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6728034633594459817' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6728034633594459817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6728034633594459817'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/free-really.html' title='FREE! Really.'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1347432056380714559</id><published>2008-07-26T13:43:00.002+02:00</published><updated>2008-07-26T13:44:22.569+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>Testing With Databases</title><content type='html'>&lt;p&gt;When it comes to testing, databases are kind of a sore spot. People like to think that "you can't test when you need a database" or "it's too complicated" or "it's not worth it." I'd like to give you some ideas what you can do when you need to test code that depends on a database. This list is sorted in the order in which I try to tackle the problem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use POJOs to store the data from the database in the real code and for the tests, create some dummy objects with test data and use them.&lt;/li&gt;

&lt;li&gt;Make the database layer a plug-in of your application and replace it with a mockup for testing that doesn't need the database and which returns test objects instead.&lt;/li&gt;

&lt;li&gt;Instead of connecting to the real database, get &lt;a href="http://hsqldb.org/"&gt;HSQLDB&lt;/a&gt; or &lt;a href="http://db.apache.org/derby/"&gt;Derby&lt;/a&gt; and use an embedded or at least local database. I prefer HSQLDB because it's smaller and starts faster (and tests should always be fast) but Derby has more features.&lt;/li&gt;

&lt;li&gt;Create a second instance of the production database system on a different machine, preferably your own computer.&lt;/li&gt;

&lt;li&gt;Create another instance of the real database with test data on the same machine as the real database.&lt;/li&gt;

&lt;li&gt;Use database schemas to create a logical database in the real database, for example if all tables are in the schema APP, create APP_TEST and in your code, add a way to replace the schema name in the SQL statements. If you wrote the DB layer yourself, use a system property which isn't set in production. If you're using Hibernate, walk the mapping objects which are created and replace the table names after loading the production configuration. &lt;tt&gt;Field.setAccessible(true)&lt;/tt&gt; is your friend.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;If you can't decide, here are a few hints:&lt;/p&gt;

&lt;p&gt;Creating two databases using schemas in the same instance can get you into serious trouble without you noticing. For example, the tests should be able to rebuild the test database from scratch at the press of a button so you can be sure in which state the database really is. If you make a mistake with the schema name during that setup, you'll destroy the real database. You might not notice you did, because the flawed statement is usually hidden under a few hundred others.&lt;/p&gt;

&lt;p&gt;Installing a second instance on a different machine might trigger license fees or your DB admin might not like it for some reason. Also, a test database should be very flexible because you'll need to be able to drop and recreate it a dozen times per hour if you need to. Your DB admins might not like to give you the necessary rights to do that. Lastly, this means only one developer can run all the tests at any given point in time because you're all going against the same database. This is bad, really bad. More often than not, you'll have spurious errors because of that.&lt;/p&gt;

&lt;p&gt;If you can legally get a copy of the real database on your own machine, that's cool ... until you see the memory, CPU and hard disk requirements plus a DB admin will probably hog your machine for a day or two to install it. Having to run two applications which need 1GB of RAM (your IDE and the DB) with a machine that has only 1GB of RAM isn't going to fun.&lt;/p&gt;

&lt;p&gt;For many cases, using HSQLDB or Derby is a good compromise between all forces that pull at you. While that will make your tests slow, they will often run much faster than against the real DB. You can install these as many times you like without any license issues, fees or DB admins bothering you. They don't take much memory or hard disk space and they are under your total control.&lt;/p&gt;

&lt;p&gt;Only, they are not the real DB. There might be slight differences, hidden performance issues and other stuff that you won't notice. Don't bother about that, though. If you can test your application, you'll find that you'll be able to fix any problems that come up when you run against the real database in little time. If you can't test your application, thought, well, you're doomed.&lt;/p&gt;

&lt;p&gt;I strongly recommend to be able to setup the database from scratch automatically. With Derby, you can create a template database and clone that on the first connection. With HSQLDB, loading data is so fast that you can afford to rebuild it with INSERT statements every time you run the tests.&lt;/p&gt;

&lt;p&gt;Still, test as much code as possible without a database connection. For one, any test without a DB will run 100-1000 times faster. Secondly, you're adding a couple more points of failure to your test which are really outside the scope of your test. Remember, every test in your suite should test exactly one thing. But if you can't get rid of the connection, you're testing the feature you want plus the DB layer plus the DB connection plus the DB itself. Plus you'll have the overhead of setup, etc. It will be hard to run a single test from your suite.&lt;/p&gt;

&lt;p&gt;At the end of the day, testing needs to be fun. If you feel that the tests are the biggest obstacle in being productive, you wouldn't be the good developer you are if you didn't get rid of them.&lt;/p&gt;

&lt;p&gt;One last thing: &lt;b&gt;Do not load as much data as possible!&lt;/b&gt; It is a common mistake to think that your tests will be "better" if you have "as much data as possible". Instead load as little data as possible to make the tests work. When you find a bug, add as little data as possible to create a test for this bug. Otherwise, you'll hog your database with useless junk that a) costs time, b) no one can tell apart from the useful stuff and c) it will give you a false feeling of safety that isn't there.&lt;/p&gt;

&lt;p&gt;If you don't know which data is useful and which isn't, then you don't know. Loading of huge amounts of junk into your database won't change that. In order to learn, you must start with what you know and work from there. Simply copying the whole production system will only slow you down and it will overwrite the carefully designed test cases you inserted yesterday.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1347432056380714559?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1347432056380714559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1347432056380714559' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1347432056380714559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1347432056380714559'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/testing-with-databases.html' title='Testing With Databases'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2009346645392979937</id><published>2008-07-26T12:10:00.002+02:00</published><updated>2008-07-26T13:03:09.403+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven2'/><title type='text'>Nexus, a Maven Repository Manager</title><content type='html'>&lt;p&gt;If you're using Maven in a corporate environment, then you're struggling with the same problems all over again: How to make sure that the build builds?&lt;/p&gt;

&lt;p&gt;While a simple task at first glance, there are a few hidden obstacles which boil down to two things: Downloads via the Internet and plugin or dependency version stability. Both can be solved by a using a proxy or a in-house repository.&lt;/p&gt;

&lt;p&gt;The guys from &lt;a href="http://www.sonatype.com/"&gt;Sonatype&lt;/a&gt; have been busy in the last months and have released &lt;a href="http://blogs.sonatype.com/jvanzyl/2008/07/24/1216875180000.html"&gt;Nexus 1.0.0-beta-4.2&lt;/a&gt; which gives you another option to chose from besides &lt;a href="http://archiva.apache.org/"&gt;Archiva&lt;/a&gt; or &lt;a href="http://www.pdark.de/dsmp/"&gt;DSMP&lt;/a&gt; (my own Maven 2 proxy). I've tried Nexus yesterday and I have to say that I'm very pleased with the result. As usual for Open Source Software, the beta is more stable than some post-beta commercial products and it delivers with &lt;a href="http://www.sonatype.com/book/reference/repository-manager.html"&gt;very little setup&lt;/a&gt; (follow the link to see the documentation).&lt;/p&gt;

&lt;p&gt;Now, we have a second issue: version stability. Here is my recipe to achieve that. First of all, version anything in your POM. All dependencies, all plugins, everything. I'm using properties for that which I define in a common parent POM plus I'm using the &lt;a href="http://www.sonatype.com/book/reference/pom-relationships.html#d0e8267"&gt;dependency management&lt;/a&gt;. &lt;a href="http://maven.apache.org/download.html"&gt;Maven 2.0.9&lt;/a&gt; helps a lot here because it forces you to add version elements everywhere.&lt;/p&gt;

&lt;p&gt;The next step is to make sure the maven builds can find their stuff. To do that, I suggest to set up &lt;i&gt;two&lt;/i&gt; Nexus repositories. The first one is the "build" repository, the second one is the "cache" repository. While all developers should use the "build" repository, the "cache" repository can actually download dependencies from the Internet.&lt;/p&gt;

&lt;p&gt;The "build" repository, on the other hand, is just a local repository with no Internet connection. To avoid mistakes, I suggest to install the build repo with the default settings but with all remote repositories deleted or turned into local ones. The "cache" repository should run on an unusual port and with the remote repositories enabled as described in the &lt;a href="http://www.sonatype.com/book/reference/repository-manager.html"&gt;installation documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, you need to create a profile in your settings.xml which switches mirrors between the two. When you want to check out a new version of some plugin, switch to the cache repository and have it download all the new stuff. This will pollute your local copy of the maven repository but only yours. After you have verified that the build completes (or fixed all the problems you've got), check the RSS feeds of Nexus for stuff it downloaded. Then, all you have to do, is to copy those to the "build" repository. After a refresh, all the other developers in your company can use the new, verified downloads.&lt;/p&gt;

&lt;p&gt;Clean your local repository and build again to make sure that your colleagues won't have any problems after the change and you're set.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2009346645392979937?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2009346645392979937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2009346645392979937' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2009346645392979937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2009346645392979937'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/nexus-maven-repository-manager.html' title='Nexus, a Maven Repository Manager'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-27008011749463200</id><published>2008-07-23T10:44:00.002+02:00</published><updated>2008-07-23T10:47:39.488+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Recommendation'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Management'/><title type='text'>Management Is The Art of Choosing What Not To Do</title><content type='html'>&lt;p&gt;From &lt;a href="http://www.randsinrepose.com/archives/2008/07/22/the_taste_of_the_day.html"&gt;Rands in Repose&lt;/a&gt;: "... management is the art of choosing what &lt;b&gt;not&lt;/b&gt; to do ..."&lt;/p&gt;

&lt;p&gt;If you want to know more about management told in a way an engineer can understand, consider Rands' book "&lt;a href="http://www.managinghumans.com/"&gt;Managing Humans&lt;/a&gt;".&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-27008011749463200?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/27008011749463200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=27008011749463200' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/27008011749463200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/27008011749463200'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/management-is-art-of-choosing-what-not.html' title='Management Is The Art of Choosing What Not To Do'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2382900075014479656</id><published>2008-07-22T16:49:00.004+02:00</published><updated>2008-07-22T17:31:11.345+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>The Code Reuse Myth</title><content type='html'>&lt;p&gt;The post "&lt;a href="http://java.dzone.com/articles/the-code-reuse-myth"&gt;The Code Reuse Myth&lt;/a&gt;" by James Sugrue got me thinking.&lt;/p&gt;

&lt;p&gt;The main problem with code reuse is that our programming languages don't support it. We sacrificed this to the gods of efficiency four decades ago and, while a few people dared to question the practice, all of them were struck down by unexpected lightning out of the blue, so far.&lt;/p&gt;

&lt;p&gt;As James said, "context" is the keyword. What we'd need is a programming language where you can adapt concepts to a context that goes beyond "object instance" or "class" or "application". What we need is an efficient way to say "collect all objects and sort them by ID" where the context defines what "ID" is. What we need is an efficient way to describe a model (relations of basic data types) and then have some tool map that efficiently to reality so we can reuse parts or fragments of the model in different contexts.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.geocities.com/tablizer/oopbad.htm"&gt;OO can't do that&lt;/a&gt; because it's limited to factories and inheritance. Traditional preprocessors can't do it, because they can't see the &lt;a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;AST&lt;/a&gt;. Having &lt;a href="http://en.wikipedia.org/wiki/Closure_(computer_science)"&gt;closures&lt;/a&gt; in a programming language is the first, tiny step in the direction to be able to push external context into existing code. This allows us to put the code to access the database into a library and &lt;a href="http://svn.codehaus.org/groovy-contrib/gsql/trunk/gsql/test/org/javanicus/gsql/SelectResultSetTest.groovy"&gt;influence what it does&lt;/a&gt; per row of the result with a closure.&lt;/p&gt;

&lt;p&gt;But to be a real new paradigm, we need "closures" in data types as well. This means being able to reuse fragments of code and data structure definitions in a new context. These fragments need to pull along all the algorithms and structures they need &lt;i&gt;without&lt;/i&gt; the developer having to pay close attention what is going on &lt;i&gt;until&lt;/i&gt; the point where the result needs peep hole optimization because of performance issues.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre&gt;fragment Named {
    String name

    String toString () {
        return "name=${name}"
    }
}

class File : Named {...}

class Directory : Named, File {...}&lt;/pre&gt;

&lt;p&gt;Looks simple but with OO, this will get you in a lot of trouble: &lt;tt&gt;Directory&lt;/tt&gt; gets a name from the class &lt;tt&gt;File&lt;/tt&gt; and from the fragment &lt;tt&gt;Named&lt;/tt&gt; (this is an artificial example, bear with me). Which one should the compiler chose? In OO, I can't say "I don't care" or "Merge them".&lt;/p&gt;

&lt;p&gt;With real fragments, you could say "Directory is a File in the sense that it supports a lot of the operations of a file (like rename, delete, get last modification time) but not all (you can't execute a directory or open it for reading)." So the example would look like this:&lt;/p&gt;

&lt;pre&gt;class File : Named { 
    void delete () {...}
    Reader openForReading () {...}
}

class Directory : Named, File.delete {...}&lt;/pre&gt;

&lt;p&gt;Now, a &lt;tt&gt;Directory&lt;/tt&gt; has a name and it "copies" the method "delete" from &lt;tt&gt;File&lt;/tt&gt; along with anything this method would need. Internally, the compiler could create an invisible &lt;tt&gt;File&lt;/tt&gt; delegate or it could clone the source or byte code of the &lt;tt&gt;File&lt;/tt&gt; class, or whatever. Or, even better, we could say "give me a copy of &lt;tt&gt;File.delete()&lt;/tt&gt; but replace all references to the field &lt;tt&gt;File.path&lt;/tt&gt; with &lt;tt&gt;Directory.path&lt;/tt&gt;."&lt;/p&gt;

&lt;p&gt;The main goal would be to allow to use the compiler as a cut'n'paste tool which checks the syntax and allows me to say "copy that method over there and replace xxx with yyy". Because that's why we think that code reuse could work: We see the same code over and over and over again and each time, the difference is just a tiny little bit of code which we can't "patch" because the language just doesn't allow it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2382900075014479656?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2382900075014479656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2382900075014479656' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2382900075014479656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2382900075014479656'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/code-reuse-myth.html' title='The Code Reuse Myth'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6738490590029391</id><published>2008-07-22T10:34:00.002+02:00</published><updated>2008-07-22T10:38:13.739+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Recommendation'/><title type='text'>Lovin' Linux? Dig This!</title><content type='html'>&lt;p&gt;Want to make linux better? Ask the &lt;a href="http://linuxhaters.blogspot.com/"&gt;Linux Hater&lt;/a&gt;. If in doubt: He wouldn't write 15 articles per month telling where Linux sucks if he didn't care.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6738490590029391?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6738490590029391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6738490590029391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6738490590029391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6738490590029391'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/lovin-linux-dig-this.html' title='Lovin&apos; Linux? Dig This!'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1134053439217056586</id><published>2008-07-21T21:54:00.003+02:00</published><updated>2008-07-22T10:38:05.279+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Violence'/><category scheme='http://www.blogger.com/atom/ns#' term='Recommendation'/><title type='text'>How to Cure a Fanatic</title><content type='html'>&lt;p&gt;Like many people, I've always been wondering how the Jews, barely escaped from being extinct, can behave like they do in Israel and Palestine today. It seems, some of them wonder as well. One of them is &lt;a href="http://en.wikipedia.org/wiki/Amos_Oz"&gt;Amos Oz&lt;/a&gt; who has written a wonderful book about fanaticism: &lt;a href="http://press.princeton.edu/titles/8128.html"&gt;How to Cure a Fanatic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you don't understand that I'm arguing against violence here, get the book and read it.&lt;/p&gt;

&lt;p&gt;According to the book, a fanatic is a person who cares so much about you that he'd rather kill you than let you be miserable.&lt;/p&gt;

&lt;p&gt;Oddly, this makes sense. Fanatics want to make the world a better place -- at all cost. In the second chapter of the book, Oz tells a short story why this doesn't work. He does that in a way that even a fanatic might understand (translated into English by me; all mistakes are mine).&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;A friend of Amos Oz, the Israeli romancer &lt;a href="http://en.wikipedia.org/wiki/Sami_Michael"&gt;Sami Michael&lt;/a&gt; once made a long trip in a car. During the ride, the driver gave him the usual lecture how important it was for the Jews to kill all Arabs.&lt;/p&gt;

&lt;p&gt;Instead of harassing this guy with "What a horrible man you are! Are you Nazi? A Fascist?", Sami listened. He had decided to try a new approach and he asked the driver: "And who, in your opinion, should actually kill all the Arabs?"&lt;/p&gt;

&lt;p&gt;The driver replied: "What are you talking about? We! The Israeli Jews! We have to! We have no choice, just look at what they do to us every day!"&lt;/p&gt;

&lt;p&gt;"But who exactly should do the job in your opinion? The police or maybe the army or the fire brigade or a team of doctors? Who should do the work?"&lt;/p&gt;

&lt;p&gt;The driver scratched his head: "I think it should be spread among us. Everyone should kill a few."&lt;/p&gt;

&lt;p&gt;Sami went along with the game. "O.K., I assume you will pick an apartment building in the capital of Haifa, you ring the doorbell or you knock on every door and you say: 'Excuse me, dear Sir or Madam, are you an Arab by any chance?' And if he or she should reply with 'yes', you will shoot them. Then, you just finished your block and want to go home, just then, you hear a baby cry somewhere on the third floor. Would you go back and shoot the baby? Yes or no?"&lt;/p&gt;

&lt;p&gt;There was a moment of silence, then the driver said to Sami: "You know, you are a very cruel person."&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Now, if your feel anger or disgust, you didn't understand the point of the story, so get the book and read it. For everyone else, think about it. You'll be surprised how many levels of understanding this simple story has and how well it explains the reasons and the fundamental flaw of a fanatic.&lt;/p&gt;

&lt;p&gt;Disclaimer: No humans and no animals were harmed, tortured or killed for this blog entry. Only my cat is now mad at me because I dared not to devote her my full attention while I wrote this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1134053439217056586?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1134053439217056586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1134053439217056586' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1134053439217056586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1134053439217056586'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/how-to-cure-fanatic.html' title='How to Cure a Fanatic'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6160037247576653979</id><published>2008-07-21T17:20:00.003+02:00</published><updated>2008-07-21T17:31:18.823+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Toying With Swing</title><content type='html'>&lt;p&gt;I've been toying with &lt;a href="http://java.sun.com/docs/books/tutorial/uiswing/"&gt;Java Swing&lt;/a&gt; (the UI which comes with Java in case you're wondering) a bit lately to determine which UI to use for my &lt;a href="https://sourceforge.net/projects/epen/"&gt;ePen project&lt;/a&gt;. I'll post a longer article about my findings in the next few days but for now, just a few links I've collected:&lt;/p&gt;

&lt;p&gt;From &lt;a href="http://leghumped.com/index.php"&gt;LegHumped&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://leghumped.com/blog/2008/05/08/java-jtextfield-background-image/"&gt;JTextField with background image&lt;/a&gt; (as in the location field in your browser)&lt;/li&gt;

&lt;li&gt;&lt;a href="http://leghumped.com/blog/2008/02/15/java-word-wrap-for-jlabels/"&gt;Word-wrap for JLabels&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://leghumped.com/blog/2008/02/08/java-close-a-jframe-with-escape/"&gt;Close a JFrame with Escape&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://leghumped.com/blog/2008/01/10/java-methods-for-treenodes/"&gt;Utility methods for tree nodes&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Then, there is the &lt;a href="http://www.drye.org/java/faq.html"&gt;JFC Swing FAQ&lt;/a&gt; and of course the &lt;a href="http://java.sun.com/docs/books/tutorial/uiswing/"&gt;Java Swing Trail&lt;/a&gt; by Sun.&lt;/p&gt;

&lt;p&gt;I've been looking for a good source on editor components. &lt;a href="http://www.oreilly.de/catalog/swinghks/chapter/"&gt;Swing Hacks&lt;/a&gt; looked promising but it seems to only scratch the surface like the rest.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6160037247576653979?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6160037247576653979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6160037247576653979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6160037247576653979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6160037247576653979'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/toying-with-swing.html' title='Toying With Swing'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3220843944091138878</id><published>2008-07-16T09:41:00.003+02:00</published><updated>2008-07-22T10:38:46.316+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Recommendation'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='Documentation'/><title type='text'>Docs? Ask The Sphinx</title><content type='html'>&lt;p&gt;If you need to generate docs for your Python projects, try &lt;a href="http://sphinx.pocoo.org/index.html"&gt;Sphinx&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3220843944091138878?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3220843944091138878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3220843944091138878' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3220843944091138878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3220843944091138878'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/docs-ask-sphinx.html' title='Docs? Ask The Sphinx'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2838919470766953009</id><published>2008-07-15T11:04:00.004+02:00</published><updated>2008-07-16T09:41:18.310+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>There Are Two Kinds of People ...</title><content type='html'>&lt;p&gt;"... Those who separate people in two kinds and those who don't." But I digress.&lt;/p&gt;

&lt;p&gt;Ever wondered about the wars in IT? &lt;a href="http://www.vim.org/"&gt;VI&lt;/a&gt; vs. &lt;a href="http://www.gnu.org/software/emacs/"&gt;Emacs&lt;/a&gt;? &lt;a href="http://www.kde.org/"&gt;KDE&lt;/a&gt; vs. &lt;a href="http://www.gnome.org/"&gt;Gnome&lt;/a&gt;? &lt;a href="http://www.jetbrains.com/idea/"&gt;IntelliJ IDEA&lt;/a&gt; vs. &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt;? &lt;a href="http://en.wikipedia.org/wiki/Personal_computer"&gt;PC&lt;/a&gt; vs. &lt;a href="http://www.apple.com/"&gt;Mac&lt;/a&gt;? Why can't people pull along the same string for once?&lt;/p&gt;

&lt;p&gt;Well, because they can't. Duh. We all have differences and we find these to make our life more rich or more simple. Can't discuss with a guy who always agrees with you, can you? Or just image your better half to do as you do ... you couldn't even out your advantages and disadvantages! During work, we accept that people are different and we find that useful because it means that work can be spread and people can do what they're good at (instead of where they suck).&lt;/p&gt;

&lt;p&gt;Sometimes, this difference goes deep. Way deep. It's so fundamental to our personality that we don't even question this. That's the fundamental schism which fuels the wars in IT. There are "vi" people and there are "emacs" people. Each member of both groups thinks the others are imbeciles who just won't see the light, no matter how often they got beaten some brains into them.&lt;/p&gt;

&lt;p&gt;The "vi" people wants to get things done and they don't want the tools to get in the way. A tool should be like a hammer: Simple, to the point, easy to understand and use. If it comes with a manual, it's not a tool, it's a distraction.&lt;/p&gt;

&lt;p&gt;The "emacs" people, on the other hand, like to have the most powerful tool they can find at their fingertips. They want to abstract, hide, build tool layer upon tool layer until the task at hand literally happens at the press of a button. If the tool can't be customized, it's not a tool, it's a nuisance.&lt;/p&gt;

&lt;p&gt;No matter how much you wish for it, these two kinds of people will never use the other ones tool. If they have to, they will be constantly irritated. Take IntelliJ IDEA, for example. I'm a "vi" guy and this &lt;a href="http://en.wikipedia.org/wiki/Integrated_development_environment"&gt;IDE&lt;/a&gt; just freaks me out. It's always doing something with my source that I never told it to do, always reformatting, always adding and removing whitespace, always getting in my way. I hate it.&lt;/p&gt;

&lt;p&gt;Eclipse, on the other hand, comes with a rich tool set. I can have my source formatted any way I like, but it only does so when I tell it to. The default is to leave my artwork alone. Eclipse doesn't try to be smarter than me. Eclipse gets my jobs done when I want them to be done and it doesn't get in my way.&lt;/p&gt;

&lt;p&gt;Don't get my wrong. I'm not telling you why Eclipse is better for &lt;em&gt;you&lt;/em&gt; than IntelliJ, I'm saying it's better for &lt;em&gt;me&lt;/em&gt;. I'm a "vi" guy.&lt;/p&gt;

&lt;p&gt;Now, you may argue that I could probably hack IntelliJ into doing what I want. That's my point exactly: If I have to turn IntelliJ into an Eclipse clone to be able to use it, why not use the tool which fits my hand to begin with? And let's face it: No matter how customizable a tool is, after you've turned it into a clone, there will still be a lot of corner cases.&lt;/p&gt;

&lt;p&gt;These come from the core of the design of these tools and that's what makes them as fundamentally different as two humans and no argument in the world will change that.&lt;/p&gt;

&lt;p&gt;So, next time someone comes up and says "This or that would be better", answer: "It is better for &lt;em&gt;you.&lt;/em&gt;. How about &lt;em&gt;me?&lt;/em&gt;"&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2838919470766953009?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2838919470766953009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2838919470766953009' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2838919470766953009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2838919470766953009'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/there-are-two-kinds-of-people.html' title='There Are Two Kinds of People ...'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1024391082593618759</id><published>2008-07-11T20:08:00.002+02:00</published><updated>2008-07-11T20:12:11.504+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Fastest Way to Collecting Objects in a String</title><content type='html'>&lt;p&gt;The fastest way to collect a list of objects in a String in Java:&lt;/p&gt;

&lt;pre&gt;StringBuilder buffer = new StringBuilder ();
String delim = "";
for (Object o: list)
{
    buffer.append (delim);
    delim = ", "; // Avoid if(); assignment is very fast!
    buffer.append (o);
}
buffer.toString ();&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1024391082593618759?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1024391082593618759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1024391082593618759' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1024391082593618759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1024391082593618759'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/fastest-way-to-collecting-objects-in.html' title='Fastest Way to Collecting Objects in a String'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1387492794374089412</id><published>2008-07-09T09:25:00.002+02:00</published><updated>2008-07-09T09:32:53.918+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>Are Bad Tests Worse Than No Tests At All?</title><content type='html'>&lt;p&gt;In his article "&lt;a href="http://java.dzone.com/articles/are-bad-tests-worse-than-no-te"&gt;Are Bad Tests Worse Than No Tests At All?&lt;/a&gt;", olivstor writes:&lt;/p&gt;

&lt;blockquote&gt;
Are the drawbacks to bad tests worse than having &lt;b&gt;no coverage&lt;/b&gt; at all?

I think  the answer is that &lt;b&gt;in the short term, even bad tests are useful&lt;/b&gt;. Trying to squeeze a extra life out of them beyond that, however, pays diminishing returns.

Just like other software, your tests should be built for maintenance, but in a crunch, you can punch something in that works. &lt;b&gt;It's better to have bad tests than to have untested code.&lt;/b&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tests are like any other code: They can go bad.&lt;/p&gt;

&lt;p&gt;In my career, I've found that it's surprisingly hard to write good tests if you have no experience in doing so. People starting to write tests make them too complex, too long, let them have too many dependencies and they take too long to run.&lt;/p&gt;

&lt;p&gt;If you're in such a situation, you have to face the fact that you just programmed yourself in a corner and you must spent the effort to get out of there. Tests are no magic silver bullet. They are code and follow the usual rules of coding: When it hurts, something is broken and it won't stop hurting unless you fix it.&lt;/p&gt;

&lt;p&gt;So in this sense, I agree that bad tests are better than no tests because they tell you early that you need to fix something. That's what their core purpose is.&lt;/p&gt;

&lt;p&gt;Management might argue that you're spending too much time on testing. I've never had a problem to sell myself to them. I usually figure that I spend 50% of my time (or more!) writing tests and 50% actual coding - and I'm still much faster than those who write code 80% of the time or more. What's more: when my code goes into production, it's is rock solid or at least easy to fix when something comes up. In 99% of the cases, the things I need to fix were those which I didn't test.&lt;/p&gt;

&lt;p&gt;This is a positive reinforcement loop which drives me to test more and more because it stops the hurting. If your tests cost more than they seem to return, you need to fix them until you get the same positive feeling when you think about them.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1387492794374089412?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1387492794374089412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1387492794374089412' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1387492794374089412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1387492794374089412'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/are-bad-tests-worse-than-no-tests-at.html' title='Are Bad Tests Worse Than No Tests At All?'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1877137992592008134</id><published>2008-07-08T13:14:00.003+02:00</published><updated>2008-07-08T13:20:46.663+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='MQSeries'/><title type='text'>MQSeries 2045: MQRC_OPTION_NOT_VALID_FOR_TYPE</title><content type='html'>&lt;p&gt;While doing some work with MQSeries, I got an error "MQJE001: Completion Code 2, Reason 2045" in &lt;tt&gt;MQQueueManager.accessQueue()&lt;/tt&gt; which translates to "MQRC_OPTION_NOT_VALID_FOR_TYPE". Hm. Hey, IBM, how about adding real error messages to your products instead of having people look up odd codes in tables?&lt;/p&gt;

&lt;p&gt;Anyway, the error means that I'm trying to open a queue for output which doesn't support this. For example, remote queues can't be opened with the option MQC.MQOO_OUTPUT. Other queues don't allow to read from them, i.e. you have to get rid of MQC.MQOO_INPUT_AS_Q_DEF in the openOptions.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1877137992592008134?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1877137992592008134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1877137992592008134' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1877137992592008134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1877137992592008134'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/mqseries-2045-mqrcoptionnotvalidfortype.html' title='MQSeries 2045: MQRC_OPTION_NOT_VALID_FOR_TYPE'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4451097968541853779</id><published>2008-07-08T11:04:00.002+02:00</published><updated>2008-07-08T11:09:33.012+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TurboGears'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>TurboGears 2.0 Is On Track</title><content type='html'>&lt;p&gt;There are three things which hooked me to TurboGears:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Every day stuff is simple, complex stuff is possible&lt;/li&gt;
&lt;li&gt;Automatic reload after code change (no need to restart)&lt;/li&gt;
&lt;li&gt;It's in Python&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What I didn't like is that TG 2.0 has been so quiet for so long. I'm on the &lt;a href="http://planet.turbogears.org/"&gt;Planet Turbogears RSS feed&lt;/a&gt; and I wasn't sure whether 2.0 was alive or dead or whatever.&lt;/p&gt;

&lt;p&gt;Well, it seems to be more alive than I expected and hopefully, we'll see a 2.0 soon. In "&lt;a href="http://compoundthinking.com/blog/index.php/2008/07/07/doing-the-right-thing-should-be-easy/"&gt;Doing the right thing should be easy&lt;/a&gt;" by Mark Ramm, you can find more details.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4451097968541853779?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4451097968541853779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4451097968541853779' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4451097968541853779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4451097968541853779'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/turbogears-20-is-on-track.html' title='TurboGears 2.0 Is On Track'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7977047889303932121</id><published>2008-07-08T11:01:00.001+02:00</published><updated>2008-07-22T10:38:46.316+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Recommendation'/><title type='text'>Starting Your Own OSS Project</title><content type='html'>&lt;p&gt;If you're planning to roll your own little OSS toy project, you should read the article "&lt;a href="http://www.javaworld.com/javaworld/jw-06-2008/jw-06-oneman.html"&gt;Party of one: Surviving the solo open source project&lt;/a&gt;" by Kirill Grouchnikov. Very good points on what to do and what to avoid and why.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7977047889303932121?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7977047889303932121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7977047889303932121' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7977047889303932121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7977047889303932121'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/starting-your-own-oss-project.html' title='Starting Your Own OSS Project'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4245643882191094570</id><published>2008-07-08T10:54:00.003+02:00</published><updated>2008-07-08T11:11:00.157+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Genes in Wikipedia</title><content type='html'>&lt;p&gt;So if you ever wanted to know how that stuff works that you're made of, scientists have &lt;a href="http://en.wikipedia.org/wiki/User:ProteinBoxBot"&gt;started to put their knowledge&lt;/a&gt; about genes on &lt;a href="http://en.wikipedia.org/"&gt;Wikipedia&lt;/a&gt;. Beware, though, it's &lt;a href="http://en.wikipedia.org/wiki/ABCC5"&gt;heavy stuff&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's interesting to see how you can use an automated process to merge complex information from one system (the scientist's databases) into another. Now, I'm waiting for the "translate this goo into language xyz" bot :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4245643882191094570?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4245643882191094570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4245643882191094570' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4245643882191094570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4245643882191094570'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/genes-in-wikipedia.html' title='Genes in Wikipedia'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2231643098604684908</id><published>2008-07-06T12:08:00.003+02:00</published><updated>2008-07-22T10:38:57.031+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='Movie'/><title type='text'>Hancock</title><content type='html'>&lt;p&gt;Strange movie. Here in Switzerland, it's sold as a "comedy" but it's not, and people will be disappointed. Also, I'm unhappy about the amount of futile violence and gore in the movie. There are a couple of scenes where you'll sit in you chair and think "What the f***!?". This is bad. While in the theater, you should never realize that you're watching a movie.&lt;/p&gt;

&lt;p&gt;All in all, I think that the movie failed to deliver because it couldn't explain enough. Maybe it was too short or maybe the wrong scenes were chosen, I don't know. I left the cinema with a strange feeling of confusion, things just didn't add up. Unlike in other movies, I'm not able to say what they could have done different. After the big surprise in the second part of the movie, the behavior of the characters is suddenly consistent and you know why Hancock is such a bastard. Only, I don't know, it's as if something is lacking.&lt;/p&gt;

&lt;p&gt;Hancock is shallow and that fits for a comic character but he's more a tragic character and this doesn't add up for me. So in the end, even when he finds his only love and gets killed for her, I don't really care anymore (as much as you care when Garfield gets flattened by a door).&lt;/p&gt;

&lt;p&gt;See &lt;a href="http://www.imdb.com/title/tt0448157/#comment"&gt;what others have to say&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2231643098604684908?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2231643098604684908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2231643098604684908' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2231643098604684908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2231643098604684908'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/07/hancock.html' title='Hancock'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6400073844621022455</id><published>2008-06-29T21:46:00.003+02:00</published><updated>2008-07-08T11:09:57.059+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Seeing Is Believing</title><content type='html'>&lt;p&gt;If you take a photo of something, does that photo show reality? What is there?&lt;/p&gt;

&lt;p&gt;Most of us believe so but actually, the photo only shows what &lt;em&gt;was&lt;/em&gt; there when you pressed the button. This misconception led to the &lt;a href="http://www.juliusvonbismarck.com/fulgurator/fertig.html"&gt;Image Fulgurator&lt;/a&gt;. What's that? It's a device which projects a picture when it notices a flashlight, i.e. when someone makes a photo. Because of the flash, you can't see the image of the Fulgurator, but you will see it later on your photo. The photo shows what was there, not what is there.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6400073844621022455?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6400073844621022455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6400073844621022455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6400073844621022455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6400073844621022455'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/seeing-is-believing.html' title='Seeing Is Believing'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7314689152231220670</id><published>2008-06-26T22:46:00.003+02:00</published><updated>2008-06-26T22:48:03.548+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Fan Programming Language</title><content type='html'>&lt;p&gt;Another language running on the VM which is worthwhile to check out: &lt;a href="http://www.fandev.org/"&gt;Fan&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7314689152231220670?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7314689152231220670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7314689152231220670' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7314689152231220670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7314689152231220670'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/fan-programming-language.html' title='Fan Programming Language'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-9103945679787238497</id><published>2008-06-26T22:24:00.003+02:00</published><updated>2008-06-26T22:45:00.904+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: The Closures Controversy</title><content type='html'>&lt;p&gt;If you ever wanted to know if it is possible to go through 60 information-packed slides in 50 minutes: Yes, it is. I've been there and Joshua pulled it off in from of about 100 people, so it's not a delusion of mine, either.&lt;/p&gt;

&lt;p&gt;In his talk, Joshua presented a host of reasons why the BGGA proposal is a really bad idea. The key information here is "BGGA". We all want closures and Joshua is no exception, it's just that the BGGA proposal is like Generics on steroids and if you can't wrap your brain about Generics wildcards, then you won't understand BGGA closures as well.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://www.javac.info/closures-v05.html"&gt;code in the proposal&lt;/a&gt; doesn't look too bad at first glance:&lt;/p&gt;

&lt;blockquote&gt;{int x, int y =&gt; x+y}&lt;/blockquote&gt;

&lt;p&gt;Unless you try to use an array. If you did "int[] x", you'd get an error because closures are based on generics and generics can't handle arrays or primitives.&lt;/p&gt;

&lt;p&gt;But the next example is better to understand why BGGA will add a new level of hell to Java which will be worse than generics:&lt;/p&gt;

&lt;blockquote&gt;{int,String=&gt;Number throws IOException} xyzzy;&lt;/blockquote&gt;

&lt;p&gt;is translated into&lt;/p&gt;

&lt;blockquote&gt;interface Function1&lt;R,A2,throws E&gt; { // system-generated&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;R invoke(int x1, A2 x2) throws E;&lt;br /&gt;
}&lt;br /&gt;
Function1&lt;? extends Number,? super String,? extends IOException&gt; xyzzy;&lt;/blockquote&gt;

&lt;p&gt;Doesn't bother you because you're never going to see this? Well, think again because if you try something that the generics type system doesn't understand, you'll get a generics error message like this one:&lt;/p&gt;

&lt;blockquote&gt;NewtonWithClosures.java:26: invoke(capture#418 of ? super {double =&gt; double}) in {capture#418 of ? super {double =&gt; double} =&gt; capture#928 of ? extends {double =&gt; double}} cannot be applied to (double)&lt;/blockquote&gt;

&lt;p&gt;The reason for this is that the closures are implemented using generics and without any high level support in the compiler so the compiler can't generate a more useful error message. And this was a simple example. We all know how quickly generics get message and for me, that means that any implementation of &lt;em&gt;any new feature&lt;/em&gt; that is based on generics is a threat to the future of Java.&lt;/p&gt;

&lt;p&gt;Again, I'm &lt;em&gt;for closures&lt;/em&gt; and I use them as often as I can in Groovy but the current proposal is just a new way to make Java harder to use. Why don't they simply change the compiler to allow to access field and method objects (from java.lang.reflect) via the class? Like so:&lt;/p&gt;

&lt;blockquote&gt;collect(list, Math.class.min)&lt;/blockquote&gt;

&lt;p&gt;If we could use Method objects like first class citizens (instead of via the horrible reflection API with it's horde of checked exceptions), we could use Method objects as simple closures. Then, all we would need is a set of util classes for single mutable primitives and we're done. Sure, the syntax wouldn't be as compact but every normal Java developer would be able to understand the concept and how it's supposed to be applied in a few hours.&lt;/p&gt;

&lt;p&gt;If you care, here is a &lt;a href="http://www.javac.info/bloch-closures-controversy.ppt"&gt;link to the whole set of arguments&lt;/a&gt; by Joshua Bloch. Read it, keeping in mind that Joshua is &lt;em&gt;pro closure&lt;/em&gt;, he just wants to avoid a second generics debacle.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-9103945679787238497?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/9103945679787238497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=9103945679787238497' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/9103945679787238497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/9103945679787238497'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-closures-controversy.html' title='Jazoon: The Closures Controversy'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1678071210516130922</id><published>2008-06-26T22:20:00.003+02:00</published><updated>2008-06-27T16:35:04.361+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Jazoon: One Year Of Groovy</title><content type='html'>&lt;p&gt;That was my talk. Attendance could have been better but I guess with Joshua Bloch &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/tl/5620"&gt;presenting Java Puzzlers&lt;/a&gt;, Cédric Beust with "&lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=5249"&gt;A quick guide to modern languages and interesting concepts for the busy Java programmer&lt;/a&gt;" and Adam Bien with &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/tl/2562"&gt;Glassfish&lt;/a&gt; at the same time, it wasn't so bad.&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="http://www.pdark.de/Jazoon08%20One%20Year%20of%20Groovy.odp"&gt;link to the presentation&lt;/a&gt; as OpenOffice document. Feel free to post any comments or questions below.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1678071210516130922?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1678071210516130922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1678071210516130922' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1678071210516130922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1678071210516130922'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-one-year-of-groovy.html' title='Jazoon: One Year Of Groovy'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2904705712635219224</id><published>2008-06-26T22:09:00.002+02:00</published><updated>2008-06-26T22:20:15.420+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><category scheme='http://www.blogger.com/atom/ns#' term='JCR'/><title type='text'>Jazzon: Weblog in 15 minutes II</title><content type='html'>&lt;p&gt;I wish I could link that presentation because it was the best I've seen in the whole show, both visually and how it was presented. So here is the &lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=3140"&gt;link to the abstract&lt;/a&gt;. There is something to be learned by this talk for anyone who wants to demo a software: One human being can't talk and use a computer at the same time. While David explained things, Bertrand wrote the code. Thumbs up!&lt;/p&gt;

&lt;p&gt;And in this case, the visual candy didn't distract from the fact that these guys were really showing off something that ought to have an impact. They showed agile web development with &lt;a href="http://incubator.apache.org/sling/site/index.html"&gt;Apache Sling&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A sling gives you range and power and Apache Sling does just that. With just a few pieces of JavaScript added to an existing static HTML web site, they built a blog in roughly 10 minutes. Impressive. I've got to &lt;a href="http://incubator.apache.org/sling/site/discover-sling-in-15-minutes.html"&gt;try this out&lt;/a&gt; myself, probably this weekend.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2904705712635219224?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2904705712635219224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2904705712635219224' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2904705712635219224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2904705712635219224'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazzon-weblog-in-15-minutes-ii.html' title='Jazzon: Weblog in 15 minutes II'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1173091833066457141</id><published>2008-06-26T22:01:00.002+02:00</published><updated>2008-06-26T22:09:27.671+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: Thursday Keynote</title><content type='html'>&lt;p&gt;Thursday's keynote was "&lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=5201"&gt;Effective Java Reloaded&lt;/a&gt;" by &lt;a href="http://en.wikipedia.org/wiki/Joshua_Bloch"&gt;Joshua Bloch&lt;/a&gt; where he presented a few key points from his &lt;a href="http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683/ref=pd_bbs_1?ie=UTF8&amp;s=books&amp;qid=1214510701&amp;sr=8-1"&gt;new book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The examples showed how to replace bit fields (or rather int constants which are used a bit fields) with &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/EnumSet.html"&gt;EnumSet&lt;/a&gt; and &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/EnumMap.html"&gt;EnumMap&lt;/a&gt;, and how to do lazy initialization for various cases effectively and correctly. If you're a Java programmer who does more than "Hello World", this book is a must have because it explains not only how to do things but how to do things elegantly and why.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1173091833066457141?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1173091833066457141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1173091833066457141' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1173091833066457141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1173091833066457141'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-thursday-keynote.html' title='Jazoon: Thursday Keynote'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4569731285623106979</id><published>2008-06-26T21:50:00.003+02:00</published><updated>2008-06-26T22:01:40.596+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: Web Tests</title><content type='html'>&lt;p&gt;In &lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=3863"&gt;his talk&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/authors/Dierk_K%f6nig"&gt;Dierk König&lt;/a&gt; showed ways to test a web applications with &lt;a href="http://webtest.canoo.com/"&gt;canoo webtest&lt;/a&gt;. There are several way to come up with a test script: Recording the user actions with a browser plug-in or by writing the script directly, for example.&lt;/p&gt;

&lt;p&gt;He also explained the best ways to test an old application (just test what you can, look for NPE's, for example, load all pages, make sure some properties appear). Of course, since the app wasn't designed to be testable, you'll be limited in what you will be able to test.&lt;/p&gt;

&lt;p&gt;IFRAMEs, on the other hand, are not a problem, as are AJAX requests. The main issue with AJAX is that while they are still asynchronous, the test framework has some limitations as to what it can test (permutation of request order). Testing special code for IE and FF is not a problem, the framework supports some browser bugs, too. Also, you can have special code to login or to get the app into a certain state and use this code as a kind of "subroutine" in several tests to avoid code duplication.&lt;/p&gt;

&lt;p&gt;Internally, webtest will use &lt;a href="http://htmlunit.sourceforge.net/"&gt;htmlunit&lt;/a&gt; to examine the HTML returned by the app and execute the JavaScript in it. So DOM manipulations can be tested, too.&lt;/p&gt;

&lt;p&gt;It's not really suitable for load tests, though, since it lacks the features to run concurrently on several computers at once. Use &lt;a href="http://jakarta.apache.org/jmeter/"&gt;JMeter&lt;/a&gt; for that.&lt;/p&gt;

&lt;P&gt;If you need to prepare the DB before the tests, use &lt;a href="http://www.dbunit.org/"&gt;dbunit&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4569731285623106979?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4569731285623106979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4569731285623106979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4569731285623106979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4569731285623106979'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-web-tests.html' title='Jazoon: Web Tests'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2653893038294850139</id><published>2008-06-26T21:43:00.002+02:00</published><updated>2008-07-08T11:12:06.974+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Jazoon: Distributed Client/Server Persistence</title><content type='html'>&lt;p&gt;In &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/tl/3520"&gt;his talk&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/authors/Alexander_Snaps"&gt;Alexander Snaps&lt;/a&gt; presented a framework called &lt;a href="http://www.holchoko.org/"&gt;Hölchoko&lt;/a&gt; which allows to cache objects from the server on the client. This is a bit like &lt;a href="http://gears.google.com/"&gt;Gears&lt;/a&gt; but for &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt;. No magic bullet, just a layer over the OR mapper to push objects over the wire, cache them in a local DB and make the merge with the server more simple once you're connected again.&lt;/p&gt;

&lt;p&gt;See &lt;a href="http://www.jroller.com/greenhorn/entry/jazoon_presentation_on_distributed_client"&gt;his blog&lt;/a&gt; for more details.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2653893038294850139?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2653893038294850139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2653893038294850139' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2653893038294850139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2653893038294850139'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-distributed-clientserver.html' title='Jazoon: Distributed Client/Server Persistence'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3104388584539715433</id><published>2008-06-26T21:37:00.004+02:00</published><updated>2008-07-08T11:11:19.089+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven2'/><title type='text'>Jazoon: Spring and Maven 2</title><content type='html'>&lt;p&gt;After some technical difficulties (the only ones I saw during the whole show, well done Jazoon!), we got a short company placement. One or two sentences, next slide, that's how it's ought to be (if at all; I mean if I was interested in your company, I'd look at the web site and not at the presentation but I digress).&lt;/p&gt;

&lt;p&gt;They presented the &lt;a href="http://EL4J.sf.net"&gt;EL4J&lt;/a&gt; project which is the result of several years of developing web applications. From what I gathered, it makes it a bit more simple to wire web apps together using a bit of convention over configuration and Maven 2. It also has some Swing support in it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3104388584539715433?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3104388584539715433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3104388584539715433' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3104388584539715433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3104388584539715433'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-spring-and-maven-2.html' title='Jazoon: Spring and Maven 2'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-7385327819408751048</id><published>2008-06-26T21:31:00.003+02:00</published><updated>2008-06-26T21:36:46.950+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: Overview of Jazz and GWT</title><content type='html'>&lt;p&gt;After spending an hour talking to Ted and keeping him away from the work he had to do, I attended the &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/tl/5580"&gt;presentation of Jazz&lt;/a&gt;. Another talk that would have benefited greatly from a live demo. Walked out after a few minutes to see the &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/jl/3840"&gt;GWT presentation&lt;/a&gt;. The presenter of that one had the same problem. *sigh*&lt;/p&gt;

&lt;p&gt;Guys, we're developers, not managers. Show us code and an IDE with a "Run" button.&lt;/p&gt;

&lt;p&gt;Still stayed till the break so I could ask some questions.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-7385327819408751048?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/7385327819408751048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=7385327819408751048' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7385327819408751048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/7385327819408751048'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-overview-of-jazz-and-gwt.html' title='Jazoon: Overview of Jazz and GWT'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-60399902110918452</id><published>2008-06-26T21:21:00.002+02:00</published><updated>2008-06-26T21:31:08.892+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: Wednesday Keynotes</title><content type='html'>&lt;p&gt;I don't remember much from these keynotes except that Ted was great as usual and that the second keynote bored me to death. I did take some notes, though: I should have a look at &lt;a href="http://incubator.apache.org/sling/site/index.html"&gt;Apache Sling&lt;/a&gt; (in incubation) and &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ted gave some examples of simple questions which a third grader could solve but which most adults (even those with a degree) can't solve in any reasonable time. Most needed one hour or more. One was this:&lt;/p&gt;

&lt;blockquote&gt;Take two sticks, one is 4 meters and the other is 5 meters. Throw them in a well which is 3 meters wide. In which height do the sticks intersect?&lt;/blockquote&gt;

&lt;p&gt;It took me 15 minutes to come up with 2.7 meters (or (5*sqrt(34)) / (5+sqrt(34))). Anyone?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-60399902110918452?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/60399902110918452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=60399902110918452' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/60399902110918452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/60399902110918452'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-wednesday-keynotes.html' title='Jazoon: Wednesday Keynotes'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1931254096406694285</id><published>2008-06-26T20:29:00.002+02:00</published><updated>2008-07-08T11:12:32.705+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon Cut: Privacy Supporting Identity Systems</title><content type='html'>&lt;p&gt;Jazoon Cut is a nice idea: You got a project, they give you 20 minutes to present it (i.e. "cut" as in "cutting edge"). In this Cut, we had &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5760"&gt;NetKernel&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5761"&gt;iGesture&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5762"&gt;Interactive Paper&lt;/a&gt;, and &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5763"&gt;Privacy Supporting Identity Systems&lt;/a&gt;. A rather interesting mix.&lt;p&gt;

&lt;p&gt;When we buy something, we hand over money. This money is untraceable. If the vendor passes it on to his bank later, there is no way anyone could tell that it was you gave him this specific bank note or what you bought with it (the vendor might know that but again, he couldn't say which bank note you gave him). This is a good thing. If the bank could figure out what you bought, some people would become very interested in this data, for example marketing people. They are looking for a way to measure how easy we are to influence for ages.&lt;/p&gt;

&lt;p&gt;But the area is getting more tight. If you had some RFID chips on you, say, one of those &lt;a href="http://www.securityfocus.com/brief/315"&gt;new passports&lt;/a&gt; or a &lt;a href="http://www.securityfocus.com/brief/336"&gt;contactless credit card&lt;/a&gt;, I could place some people in a shopping mall or city center with technology to track where you go. Under optimal conditions, an RFID chip can be tracked over the distance of 60 meters. That's not much and I probably need a couple of radio stations spread over the city to do that but with such a system, I could find out what you buy.&lt;/p&gt;

&lt;p&gt;"Now," you say, "I can't be identified by that," and you'd be wrong. Some credit cards will offer all the details stored on them (enough to &lt;em&gt;buy&lt;/em&gt; something with that data in the Internet) when asked. For the rest of you, you're lucky until someone figures a way out to do that. Nonetheless, even if I don't know your identity I can track you. So if your last stop was at an expensive jeweler, chances are that you have enough money that it's worthwhile to mug you.&lt;/p&gt;

&lt;p&gt;And I can pick you from a safe distance of 20 to 60 meters, follow you around out of sight and wait for the perfect moment to strike. Oh, and better not step into some sex shop because I'd know. In fact, I can track your movements for a couple of days, find out where you live (and thus your identity). All without you ever knowing that I even exist.&lt;/p&gt;

&lt;p&gt;I hope I have made you understand that the question is not that you have nothing to hide (which is not true; when was the last time you filed a correct tax declaration?), the question is what evil someone could come up with if he knew something about you. The problem with this question is: Nobody knows the answer &lt;em&gt;until&lt;/em&gt; someone comes up with a new evil that nobody else thought about so far!&lt;/p&gt;

&lt;p&gt;In his talk, &lt;a href="http://jazoon.com/jazoon08/en/conference/authors/Thomas_Heydt-Benjamin"&gt;Thomas Heydt-Benjamin&lt;/a&gt; showed how you might be able to have both: Comfort and security. The attack described above wouldn't work if the range of the RFID chip in your credit card would be reduced to a few centimeters. It would still be comfortable if you had to put it on the desk for a moment, making hard contact with the surface to be able to read it. Surely, you would notice if someone followed you holding a strange device to your pocket.&lt;/p&gt;

&lt;p&gt;The next thing is the data on the card. The vendor needs the data to know who you are and if your credit is valid. But actually, he does never have to &lt;em&gt;see&lt;/em&gt; the real data. The only thing he needs to know is "credit is valid" or not. He doesn't need your credit card number. Or the name. Or the expiration date. Or the security code on the back. What could be done is this:&lt;/p&gt;

&lt;p&gt;You check into a hotel. You present your passport to the reader device on the desk. On your side of the screen, you can select which data the hotel guy can see. To allow the police to track you in case you didn't pay your bill or you're involved in some kind of crime, the hotel's computer gets an encrypted code that identifies you. For everyone who can't decrypt this key, it's just a long, random string of data. For all legal means and purposes, you're as anonymous as you want. While this might not make much sense in the hotel scenario (hotel staff hates it to call everyone "Mr. Smith"), it starts to make sense on the Internet.&lt;/p&gt;

&lt;p&gt;You're stuck in some kind of game and want to check the walk through. Only, the game is for people over 16. So the site with the solution should check your age because the walk through contains all those images which were the reason for the age limitation. In this case, you only want to tell the site your age or rather that you're older than 16 and nothing else. You don't want to tell them your name, or where you live. Otherwise, the police might decide to shoot you for reasons of precaution (this is an example, okay?).&lt;/p&gt;

&lt;p&gt;Or let's face the truth: 99% of the Internet is pr0n. And you surely don't want to leave your personal details with people who treat women like in the movies they sell.&lt;/p&gt;

&lt;p&gt;With the &lt;a href="http://www.eclipse.org/higgins/"&gt;Higgins framework&lt;/a&gt;, such things are possible. This framework allows to transfer data like "I'm older than 18" in such a way that the other side can be sure you are even though they will never find out what your real age is or your name. At the same time, it doesn't allow for illegal activity because you can be identified by your IP address and when the police compares the data sent to the web site in question and your passport, they can prove without doubt that it was your passport that was used in the transaction.&lt;/p&gt;

&lt;p&gt;At that time, you want a passport that can't be skimmed in the subway.&lt;/p&gt;

&lt;p&gt;While I talked to Mr. Heydt-Benjamin, he also explained to me that &lt;a href="http://www.nytimes.com/2008/03/12/business/12heart-web.html"&gt;certain pacemakers contain a radio interface&lt;/a&gt;. Which makes sense. By this interface, you can query for the patient's data (name, for example) and you can also &lt;em&gt;control&lt;/em&gt; the pacemaker. This interface is not protected by any encryption or password. So you can see the heart curves recorded by the sensors. But you can also change the sensor settings of the pacemaker. This is actually what happens when the doctors adjust them to your needs after the surgery.&lt;/p&gt;

&lt;p&gt;The scary part is that the pacemaker has a function to stop a heart. This is necessary to "heal" certain kinds of heart rhythm irregularities like ventricular fibrillation. Now if I'm a hacker and I don't like you, I can turn off the sensors and stop your heart. The device will try to start your heart again after stopping it but that will fail because the settings of the sensors will prevent it to get any feedback.&lt;/p&gt;

&lt;p&gt;So if you can see a large antenna at the horizon, the words "denial of service attack" might make you feel a little bit uneasy in the future if you do need a pacemaker.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1931254096406694285?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1931254096406694285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1931254096406694285' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1931254096406694285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1931254096406694285'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-cut-privacy-supporting-identity.html' title='Jazoon Cut: Privacy Supporting Identity Systems'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6569151068939800622</id><published>2008-06-26T20:26:00.001+02:00</published><updated>2008-06-26T20:29:26.024+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon Cut: Interactive Paper</title><content type='html'>&lt;p&gt;Jazoon Cut is a nice idea: You got a project, they give you 20 minutes to present it (i.e. "cut" as in "cutting edge"). In this Cut, we had &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5760"&gt;NetKernel&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5761"&gt;iGesture&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5762"&gt;Interactive Paper&lt;/a&gt;, and &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5763"&gt;Privacy Supporting Identity Systems&lt;/a&gt;. A rather interesting mix.&lt;p&gt;

&lt;p&gt;This talk really intrigued me. As we all know, the "paperless office" really means "kill more trees". Every year, the work consumes about 5% more paper and that's despite declines in book and newspaper sales. The guys around &lt;a href="http://jazoon.com/jazoon08/en/conference/authors/Nadir_Weibel"&gt;Nadir Weibel&lt;/a&gt; came up with a system to &lt;em&gt;link&lt;/em&gt; paper with the screen. When Nadir started to draw on the screen as he talked, nobody noticed at first. We were thinking he used a graphics tablet or something like that but he actually used a clipboard with a few sheets of paper on it. The paper was just normal paper with the exception of a fine grid of points printed on it which you can barely make out (The concept is &lt;a href="http://www.anoto.com/"&gt;explained here&lt;/a&gt;). You'll need a special pen that can recognize that pattern but after that, you're set.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://www.globis.ethz.ch/research/iserver/plugins/paper/"&gt;iPaper&lt;/a&gt; guys have created two demonstrations of their technology: &lt;a href="http://portal.acm.org/citation.cfm?doid=1226969.1226981"&gt;PaperPoint&lt;/a&gt; and &lt;a href="http://portal.acm.org/citation.cfm?id=1358682"&gt;PaperProof&lt;/a&gt;. The former is a printout of a presentation with a menu and some buttons &lt;em&gt;printed on the paper&lt;/em&gt;. So you can use the pen to &lt;em&gt;control&lt;/em&gt; the presentation just by using &lt;em&gt;your pen&lt;/em&gt;. You want to jump to a certain slide? Draw a dot on the "here" "button" on the printout and the computer will recognize where you are on the printout and sent the command to your presentation software. There are options to select a color and line width and then you can just draw on the paper and the same lines will appear on the screen. Hint: You will want to sit down when you do that; drawing something more complex than a little arrow while juggling the clipboard isn't for the easily irritated.&lt;/p&gt;

&lt;p&gt;Not convinced? Well, PaperProof takes it step further. You don't actually have the computer running while you use iPaper. What you can do is print out some long text (like the book or article you're currently working on). Then you go out, relax in your deck-chair with a nice drink at your side and the sun above and edit that text, making corrections, marking errors, etc. With the traditional way, you eventually return to your computer and then you have to go through all that &lt;em&gt;again&lt;/em&gt; copying everything you did from paper into your word processor.&lt;/p&gt;

&lt;p&gt;PaperProof does that for you. It can recognize a few gestures and your handwriting. So when you return in this scenario, you start your computer, sync it with the pen and when you open your text document, &lt;em&gt;it will already contain all the annotations, error corrections and insertions you made with your pen.&lt;/em&gt; Editors and authors around the world, isn't that a dream come true?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6569151068939800622?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6569151068939800622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6569151068939800622' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6569151068939800622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6569151068939800622'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-cut-interactive-paper.html' title='Jazoon Cut: Interactive Paper'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2387741882308213252</id><published>2008-06-26T20:25:00.000+02:00</published><updated>2008-06-26T20:26:54.557+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon Cut: iGesture</title><content type='html'>&lt;p&gt;Jazoon Cut is a nice idea: You got a project, they give you 20 minutes to present it (i.e. "cut" as in "cutting edge"). In this Cut, we had &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5760"&gt;NetKernel&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5761"&gt;iGesture&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5762"&gt;Interactive Paper&lt;/a&gt;, and &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5763"&gt;Privacy Supporting Identity Systems&lt;/a&gt;. A rather interesting mix.&lt;p&gt;

&lt;p&gt;The presentation of &lt;a href="http://www.igesture.org/"&gt;iGesture&lt;/a&gt; was a disaster from my point of view. The software is a workbench to create gesture recognition software or configuration packages for a gesture recognizer. That's it. And it took the people in the audience about the same time to figure this out as it took you to read this. After that, we waited for something to happen and nothing did. Shame. My suggestion: Next time, bring a laptop, show the first two slides of your presentation and then take a mouse and show the real thing: Train the thing and see the people rip it out of your hands.&lt;/p&gt;

&lt;p&gt;I did learn a few tricks how you can recognize gestures, though. The most simple way is to filter the input until you have general directions like up (U), left (L), right (R) or down (D), then simply create a string with these characters and use a regular expression to describe the gesture (a rectangle would then be /U+R+D+L+/).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2387741882308213252?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2387741882308213252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2387741882308213252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2387741882308213252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2387741882308213252'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-cut-igesture.html' title='Jazoon Cut: iGesture'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-8066961510211847409</id><published>2008-06-26T20:21:00.003+02:00</published><updated>2008-06-26T20:25:33.076+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon Cut: NetKernel</title><content type='html'>&lt;p&gt;Jazoon Cut is a nice idea: You got a project, they give you 20 minutes to present it (i.e. "cut" as in "cutting edge"). In this Cut, we had &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5760"&gt;NetKernel&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5761"&gt;iGesture&lt;/a&gt;, &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5762"&gt;Interactive Paper&lt;/a&gt;, and &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/ed/5763"&gt;Privacy Supporting Identity Systems&lt;/a&gt;. A rather interesting mix.&lt;p&gt;

&lt;p&gt;In the &lt;a href="http://www.1060.org/"&gt;NetKernel&lt;/a&gt; talk, Brian Sletten again tried to sell his "RDF is the best and you should use it everywhere." Basically, NetKernel is a little core where you can register translation services (called ... I don't know what he called them and I can't find the link to the actual presentation, just the abstract :/). So when a service needs some data (or "resource"), he calls the kernel and the kernel figures out who might be able to serve that request which might go through several hoops before it comes back. Nothing fancy here, Unix pipes do that for ages with the exception that they don't build themselves.&lt;/p&gt;

&lt;p&gt;His demo was to show how you could calculate &lt;a href="http://en.wikipedia.org/wiki/Fibonacci_number"&gt;Fibonacci numbers&lt;/a&gt; by using a "bsh" service (BeanShell, that's JavaScript) to add two intermediate numbers of the result. You would imagine that this is slow as hell with all that creating messages, sending them around, starting a JavaScript interpreter and run each add. As you might remember, the Fibonacci generators are usually implemented recursively and that should kill the NetKernel.&lt;/p&gt;

&lt;p&gt;Only &lt;a href="http://1060.org/upload/fibonacci.html"&gt;it doesn't&lt;/a&gt;. If you look at the runtime graphs, the Java version of the Fibonacci generator needs exponential time as the input grows. Around 30, the Java version takes seconds to run while the NetKernel version always needs to same amount of time. The nice thing about the design is that you can cache the results. So the call to fibonacci(30) will just add the cached results of fibonacci(29) and fibonacci(28) and be done. One level of recursion required.&lt;/p&gt;

&lt;p&gt;While this is mighty impressive and surprising, the question remains how that will scale in reality. After all, caching a 500MB result from some service might not be feasible or even possible.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-8066961510211847409?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/8066961510211847409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=8066961510211847409' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8066961510211847409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/8066961510211847409'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-cut-netkernel.html' title='Jazoon Cut: NetKernel'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5735993892305897504</id><published>2008-06-25T13:41:00.001+02:00</published><updated>2008-06-25T13:49:39.177+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: Data Driven Applications</title><content type='html'>&lt;p&gt;Not one of my favorite talks, to be frank. &lt;a href="http://jazoon.com/jazoon08/en/conference/authors/Brian_Sletten"&gt;Brian Sletten&lt;/a&gt; &lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=5120"&gt;tried to explain&lt;/a&gt; how we would write less code in the future because data would become more important. Seeing is believing and I haven't seen nothing, yet.&lt;/p&gt;

&lt;p&gt;He has a few good point like that we should be able to recall data sets which we created with Web 2.0 sites (kind of like bookmarks on steroids that can save the state of the web 2.0 app as you bookmark it). Also, that the semantic web will make a lot of things possible and happen.&lt;/p&gt;

&lt;p&gt;I buy that. But on the other hand, we don't even have a decent UI framework for Java yet and that's eight (8) years after Swing came out. This sure looks promising; I just wonder if I will be still around when it starts to deliver and companies get the CPU power and network throughput to really run all their data through RDF converters. And see the result before you get downsized.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5735993892305897504?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5735993892305897504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5735993892305897504' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5735993892305897504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5735993892305897504'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-data-driven-applications.html' title='Jazoon: Data Driven Applications'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-9149768502231552821</id><published>2008-06-25T13:28:00.004+02:00</published><updated>2008-06-25T13:43:35.618+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Jazon: Building DSL's</title><content type='html'>&lt;p&gt;&lt;a href="http://jazoon.com/jazoon08/en/conference/authors/Neal_Ford"&gt;Neal Ford&lt;/a&gt;'s &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/tl/5256"&gt;talk about DSLs&lt;/a&gt; and how to create them in static and dynamic languages (Java and Groovy in this case) was very interesting because he clear up the fog around DSL's a but, why they are great and when they help. Basically a DSL is "jargon". It is compact code that allows you to express much more tightly what you want than any "general purpose" language ("one site fits all" actually makes everyone look ridiculous).&lt;/p&gt;

&lt;p&gt;Remember that old OO promise to allow to mirror the world in a programming language, to allow to model the code after what the customer had in mind? Turns out, that OO was ... nah, not lying ... it was just overselling itself because customers don't think in objects or models. They think jargon. And DSL's allow you to make a compiler understand jargon. That's even possible with Java even though "Java is like taking to a retard": You always have to repeat yourself to make sure that the stupid compiler gets what you want (pun intended).&lt;/p&gt;

&lt;p&gt;A DSL is not to be confused with an API. An API uses explicit context like "obj.setThis(...); obj.setThat(...);" etc. Here "obj" is the context and "setXyz()" is not meaningful without knowing the object we're talking about here. A DSL, on the other hand, is all about context and context is implicit. It goes "obj.should(...).allow(...).this(...)". An example is &lt;a href="http://code.google.com/p/hamcrest/wiki/Tutorial"&gt;hamcrest&lt;/a&gt;: "assertThat(theBiscuit, is(myBiscuit));" Reads fluently, compact code, and it's obvious that "is(myBiscuit)" should be compared to "theBiscuit" in some way.&lt;/p&gt;

&lt;p&gt;The handouts of his presentation are available from &lt;a href="http://nealford.com/mypastconferences.htm"&gt;his homepage&lt;/a&gt; but without his witty remarks. A pity but still worth to check out if you want to see just how far you can push Java to get code that your customer might understand.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-9149768502231552821?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/9149768502231552821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=9149768502231552821' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/9149768502231552821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/9149768502231552821'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazon-building-dsls.html' title='Jazon: Building DSL&apos;s'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3654127100366797605</id><published>2008-06-25T13:11:00.002+02:00</published><updated>2008-06-25T13:28:33.445+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: Rich GUI development with Java</title><content type='html'>&lt;p&gt;If you ever tried to develop a nice you with Java, you'll know the pain. Swing: Old, steep learning curve, unweildy widgets. SWT: Nice, good learning curve, "which JAR's do I need, Sir?" and who puts that DLL in my search path. There might be other contenders but I don't even remember their names.&lt;/p&gt;

&lt;p&gt;So the guys at Canoo faces the dragon and chipped a few scales off it. As &lt;a href="http://jazoon.com/jazoon08/en/conference/authors/Bruno_Sch%e4ffer"&gt;Bruno Schäffer&lt;/a&gt; said in &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/tl/5340"&gt;his talk&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;Developers should focus on the what and not how.&lt;/blockquote&gt;

&lt;p&gt;They used &lt;a href="http://en.wikipedia.org/wiki/Swing_(Java)"&gt;Swing&lt;/a&gt;, some components from &lt;a href="https://swingx.dev.java.net/"&gt;SwingX&lt;/a&gt;, &lt;a href="http://www.jgoodies.com/downloads/products.html"&gt;JGoodies Smart Client&lt;/a&gt; and &lt;a href="http://jemmy.netbeans.org/"&gt;Jemmy&lt;/a&gt; for testing for the UI and something called &lt;a href="http://sourceforge.net/projects/c3p0"&gt;c3pO&lt;/a&gt; for JDBC connection pooling to build a smart client. &lt;a href="http://www.openarchitectureware.org/"&gt;openArchitectureWare&lt;/a&gt; was used to generate a model editor for the data model, so they could generate the DAO classes for that efficiently.&lt;/p&gt;

&lt;p&gt;Their application is split into modules but they don't use &lt;a href="http://www.osgi.org/Main/HomePage"&gt;OSGi&lt;/a&gt; or any other module framework out there because they got in their way, it's just good old, traditioal loading on demand from the classpath. I can relate to that. OSGi is so great and stuff ... but it somehow lost contact to the base. It's just eithet not flexible enough or not simple enough for me to understand and use.&lt;/p&gt;

&lt;p&gt;Good talk but less product placement for your company next time, Bruno.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3654127100366797605?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3654127100366797605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3654127100366797605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3654127100366797605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3654127100366797605'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-rich-gui-development-with-java.html' title='Jazoon: Rich GUI development with Java'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3222773194813820214</id><published>2008-06-25T12:59:00.002+02:00</published><updated>2008-07-08T11:12:46.740+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Jazoon: openID</title><content type='html'>&lt;p&gt;Robert Ott &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/tl/5180"&gt;showed off openID&lt;/a&gt;. If you wondered about these strange links which start to pop up all over the web near the login buttons, openID is a way to register yourself &lt;em&gt;once&lt;/em&gt; at a place you &lt;em&gt;trust&lt;/em&gt; and then use &lt;em&gt;that&lt;/em&gt; to login elsewhere.&lt;/p&gt;

&lt;p&gt;The idea behind openID is that you click on the link, the web site passes you on to an identity Provider which can use any means to make sure you are you and then give that confidence back to the original site. See the &lt;a href="http://openid.net/"&gt;openID.net website&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;The cool thing about openID is that you just have to manage a single identity and use that to log in into various services on the net &lt;em&gt;without&lt;/em&gt; giving all of them the same password (and thus make you very vulnerable agains attacks). The main problems which openID doesn't solve is stalking and spamming.&lt;/p&gt;

&lt;p&gt;openID makes stalking easier because you have to enter your openID at every place you want to log in to. Same id means same person. There are talks in the openID community to allow a person to have more than one ID and still use the same identity provider but there is nothing definite, yet.&lt;/p&gt;

&lt;p&gt;Also, openID doesn't protect against spammers. It might help, though, because of two things: a) You can black list identity providers which allow spammers and b) you can send the police to the other identity providers which will hand over the real identity of the person behind the openID to the authorities on court order. So this might help in the war against forum spam, we'll see.&lt;/p&gt;

&lt;p&gt;All in all, a good talk.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3222773194813820214?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3222773194813820214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3222773194813820214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3222773194813820214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3222773194813820214'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-openid.html' title='Jazoon: openID'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-6028341111326476390</id><published>2008-06-24T16:04:00.004+02:00</published><updated>2008-06-25T12:59:08.769+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><title type='text'>Blogging From The Jazoon: Keynotes Tuesday</title><content type='html'>&lt;p&gt;So this is day one of the Jazzon with the keynotes and talks. I'll go through things as they happened.&lt;/p&gt;

&lt;h3&gt;Scalable Languages&lt;/h3&gt;

&lt;p&gt;Martin Odersky, father of Scala, gave an &lt;a href="http://jazoon.com/jazoon08/en/conference/presentations/istr/5242"&gt;introduction to scalable languages&lt;/a&gt; or rather to &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;. Well, Scala looks really promising with its traits and other features. But my original objection still remainds: The syntax is just ugly. Proves my point that there are only five people on this planet who can design a language and of them, I only know &lt;a href="http://www.python.org/~guido/"&gt;Guido van Rossum&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Adoption-Led Market&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://www.webmink.net/"&gt;Simon Phipps&lt;/a&gt; followed wth a talk about the "&lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=5240"&gt;Adoption-Led Market&lt;/a&gt;". It's astonishing how many OSS projects Sun supports or started and how little is known about that. Marketing again. *sigh* His talk wasn't all about Sun but how people start to despise vendors or rather their promise that their product is going to deliver to the promise ... &lt;em&gt;after&lt;/em&gt; you've paid for it. Of course in an OSS world, where you can just download something and try it out, it becomes increasingly hard for them to "justify their 1000% profit margin."&lt;/p&gt;

&lt;p&gt;This is a very good point. With OSS software, you pay for what you need (and not what the vendor things is best for him\b\b\byou). If you need a feature, support or whatnot, well, you can always pay someone to give it to you. But then, you pay when &lt;b&gt;you&lt;/b&gt; need it. That makes is a justifiable cost, not an arbitrary one. Also, support gets you what you need when you need it. Just imagine to ask MicroSoft for a specific feature in Windows which you need. How much would that cost? What are you're chances to actually get it? Forget it! But with OSS, for the first time in software history, you can get what you need for a reasonable price and you might even make someone on the other side of the planet very happy.&lt;/p&gt;

&lt;p&gt;Of course, "the greatest threat to freedom is a happy slave" but the talk gave a lot of arguments how to sell OSS to your company, even if that company happens to be the government.&lt;/p&gt;

&lt;p&gt;He also gave a good reason which OSS license to chose for your next OSS project:&lt;/p&gt;

&lt;blockquote&gt;
A license is the constitution of a community
&lt;div style="text-align: right"&gt;Eben Moglen&lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nice guy, good talk. If you can, &lt;a href="http://www.webmink.net/2008/06/please-vote-for-my-photo.htm"&gt;vote for his photo&lt;/a&gt; at &lt;a href="http://www.webmink.net/"&gt;his website&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Innovation&lt;/h3&gt;

&lt;p&gt;The third keynote was by Rod Johnson: "Where will tomorrows innovation in Java Enterprise come from?" After explaining where innovation comes from, he shows how standards kill innovation and how committees can't drive innocation due to political games by the companies who dispatch the people that form these committees plus general group stupidity.&lt;/p&gt;

&lt;p&gt;After the more or less failure of the JCP in recent years, attributed mostly to ignoring feedback from the community and drowning ideas in ceremony, he hopes that &lt;a href="http://jcp.org/en/jsr/detail?id=316"&gt;JSR 316&lt;/a&gt; (that's Java Enterprise version 6) will help to fix Java EE. If it does, then that might mean that a good sign that the JCP has become a helper for the Java cause instead of another reason to abandon it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-6028341111326476390?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/6028341111326476390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=6028341111326476390' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6028341111326476390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/6028341111326476390'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/blogging-from-jazoon-keynotes-tuesday.html' title='Blogging From The Jazoon: Keynotes Tuesday'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5635425331367321017</id><published>2008-06-23T22:31:00.003+02:00</published><updated>2008-06-23T22:52:27.983+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jazoon'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title type='text'>Jazoon 2008, Day 0</title><content type='html'>&lt;p&gt;Just back from the &lt;a href="http://jazoon.com/"&gt;Jazoon 2008&lt;/a&gt;, Tutorial day (the day before the actual conference starts). I attended Ted Neward's talk "&lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=5041"&gt;The Busy Java Developer's Guide to Groovy&lt;/a&gt;". As always, the talk was quite a lot of fun even for someone like me, who already &lt;a href="http://groups.google.com/group/groovy-developer/search?group=groovy-developer&amp;q=aaron+digulla&amp;qt_g=Diese+Gruppe+durchsuchen"&gt;knows a lot about Groovy&lt;/a&gt;. If you get a chance to attend a talk given by Ted: Go. It's worth it.&lt;/p&gt;

&lt;p&gt;In his talk, Ted crammed a pretty complete introduction in the key features of &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; into three hours. For me, the key points of the talk were these: Productivity and ceremony.&lt;/p&gt;

&lt;p&gt;Research shows that all developers roughly write the same amount of code lines per day. The difference between guru developers and the greenhorns is that the gurus write a line once and it works first try and each line achieves much more in respect to reaching the goal than any line of a novice. So in order to boost productivity of a guru, the only way is to use a programming language which can achieve more in a single line of code (and we're talking one statement per line here, obviously). So it's not that the guru writes ten times as much code per day as the novice, the novice just writes every line ten times because every time, (s)he gets something wrong and has to fix it.&lt;/p&gt;

&lt;p&gt;The other aspect is ceremony. A lot of code in Java is ceremony. In most cases, the Java compiler knows where a statement ends and it wouldn't need the semicolon. Still it insists that I press the key anyway (and it's two keys on the German or Swiss keyboard). The same goes for many other things in Java which are just there for tradition. It would be simple for the Java compiler to infer the type of an object after &lt;tt&gt;if (obj instanceof ...)&lt;/tt&gt;. There really is no need for the cast in the next line. I could find another 10 examples easily.&lt;/p&gt;

&lt;p&gt;Groovy does away with all that. It comes at a price, though. If you like to rely on the compiler creating a cozy padded cell for you, checking types and syntax as much as possible, then Groovy is not for you. In Groovy, the idea is that the developer knows exactly what (s)he's doing and all (s)he needs is the fastest path to get there. You &lt;em&gt;can&lt;/em&gt; do all the dirty things you wished for in Java but you don't &lt;em&gt;have&lt;/em&gt; to. Groovy is an "also" language, not an "either-or" language. If you feel that Java is dirty enough, already, try &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks, Ted.&lt;/p&gt;

&lt;p&gt;If you want to know more about Groovy and you're in Zurich, why not attend &lt;a href="http://jazoon.com/jazoon08/en/conference/presentationdetails.html?type=sid&amp;detail=4163"&gt;my talk&lt;/a&gt; on &lt;a href="http://jazoon.com/en/conference/thursday.html"&gt;Thursday&lt;/a&gt;?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5635425331367321017?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5635425331367321017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5635425331367321017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5635425331367321017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5635425331367321017'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/jazoon-2008-day-0.html' title='Jazoon 2008, Day 0'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3738728318507816655</id><published>2008-06-21T17:30:00.003+02:00</published><updated>2008-06-21T17:34:50.682+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Collaborative Editing</title><content type='html'>&lt;p&gt;Mustafa K. Isik has a video on &lt;a href="http://www.vimeo.com/"&gt;vimeo&lt;/a&gt; demonstrating &lt;a href="http://www.vimeo.com/1195398?pg=embed&amp;sec=1195398"&gt;collaborative editing of a Java class in Eclipse&lt;/a&gt;. I'm not sure where this leads and my experience winces at the idea but it would sure help if the superman of your team could attach to your editing session, see the code you're working on and help you fix it (instead of having to get up and coming over).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3738728318507816655?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3738728318507816655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3738728318507816655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3738728318507816655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3738728318507816655'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/collaborative-editing.html' title='Collaborative Editing'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-873715020460299542</id><published>2008-06-20T09:42:00.002+02:00</published><updated>2008-06-20T09:54:02.626+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>prefuse - Information Visualization Toolkit</title><content type='html'>&lt;p&gt;If you're looking for a cool way to visualize your data for the user in Java, try &lt;a href="http://prefuse.org/"&gt;prefuse&lt;/a&gt;. The &lt;a href="http://prefuse.org/gallery"&gt;examples&lt;/a&gt; are impressive.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-873715020460299542?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/873715020460299542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=873715020460299542' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/873715020460299542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/873715020460299542'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/prefuse-information-visualization.html' title='prefuse - Information Visualization Toolkit'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1769435430359371251</id><published>2008-06-19T11:27:00.004+02:00</published><updated>2008-06-19T14:04:43.367+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ePen'/><title type='text'>ePen</title><content type='html'>&lt;p&gt;After a long time, I'm starting a new OSS project called "&lt;a href="https://sourceforge.net/projects/epen/"&gt;ePen&lt;/a&gt;". From the description:&lt;/p&gt;

&lt;blockquote&gt;
ePen - A cross platform tool for creative writers and book authors. ePen is able to manage all information around a book project: The actual text, descriptions of the characters and scenes, the storyline.
&lt;/blockquote&gt;

&lt;p&gt;ePen should become for authors what a pen was for centuries: A simple tool to convert ideas into amazing, breathtaking stories.&lt;/p&gt;

&lt;p&gt;Right now, ePen is in the planning stage even though I'll commit a prototype this weekend. The first thing on the agenda is to decide how to implement the tool. The prototype was done in Python and PyQt and while it was a nice experience, the text editor leaves a lot to be desired (read: it sucks). I've collected my thoughts in &lt;a href="http://epen.on-wiki.net/"&gt;this wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've also create a &lt;a href="http://groups.google.de/group/epen"&gt;Google Group for discussions&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1769435430359371251?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1769435430359371251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1769435430359371251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1769435430359371251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1769435430359371251'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/epen.html' title='ePen'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-4748019677195803676</id><published>2008-06-17T10:21:00.002+02:00</published><updated>2008-06-17T10:40:48.157+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>How to Work Better</title><content type='html'>&lt;p&gt;From the &lt;a href="http://maps.google.com/maps/ms?ie=UTF8&amp;hl=en&amp;t=h&amp;msa=0&amp;msid=105852379886197898420.00044fd8962bc3cb1cc2c&amp;ll=47.41458,8.548605&amp;spn=0.001751,0.001663&amp;z=19&amp;iwloc=00044fd89b6ef704b840e"&gt;wall of a corporate building&lt;/a&gt; in Zurich:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do One Thing at a Time&lt;/li&gt;

&lt;li&gt;Know the Problem&lt;/li&gt;

&lt;li&gt;Learn to Listen&lt;/li&gt;

&lt;li&gt;Learn to Ask Questions&lt;/li&gt;

&lt;li&gt;Distinguish Sense from Nonsense&lt;/li&gt;

&lt;li&gt;Accept Change as Inevitable&lt;/li&gt;

&lt;li&gt;Admit Mistakes&lt;/li&gt;

&lt;li&gt;Say It Simple&lt;/li&gt;

&lt;li&gt;Be Calm&lt;/li&gt;

&lt;li&gt;Smile&lt;/li&gt;

&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-4748019677195803676?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/4748019677195803676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=4748019677195803676' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4748019677195803676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/4748019677195803676'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/how-to-work-better.html' title='How to Work Better'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-5095530525379128378</id><published>2008-06-17T10:18:00.001+02:00</published><updated>2008-06-17T10:20:59.628+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Communication Skill</title><content type='html'>&lt;p&gt;From a calendar:&lt;/p&gt;

&lt;blockquote&gt;The real art of conversation is not only to say the right thing at the right time, but also to leave unsaid the wrong thing at the tempting moment.&lt;br /&gt;&lt;div style="text-align: right;"&gt;-- Author unknown&lt;/div&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-5095530525379128378?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/5095530525379128378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=5095530525379128378' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5095530525379128378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/5095530525379128378'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/communication-skill.html' title='Communication Skill'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3479231061413552151</id><published>2008-06-16T17:39:00.003+02:00</published><updated>2008-06-17T10:17:50.708+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>Eye Candy For Developers</title><content type='html'>&lt;p&gt;There are two new projects on the 'net which might influence the way we see software in the future (in the literal sense). &lt;a href="http://vis.cs.ucdavis.edu/~ogawa/codeswarm/"&gt;code_swarm&lt;/a&gt; can visualize the CVS history of a project in a cunning way and &lt;a href="http://wordle.net/"&gt;Wordle&lt;/a&gt; creates tightly packed tag clouds.&lt;/p&gt;

&lt;p&gt;What I find especially interesting about Wordle is that it creates the tag cloud in real time (as you watch) using a Java applet. If you happen to have Java 6 installed, the animations are very smooth, almost like Flash.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3479231061413552151?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3479231061413552151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3479231061413552151' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3479231061413552151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3479231061413552151'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/eye-candy-for-developers.html' title='Eye Candy For Developers'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-3216635699774825179</id><published>2008-06-13T10:10:00.000+02:00</published><updated>2008-06-13T10:11:05.708+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Education'/><title type='text'>The Lucifer Effect</title><content type='html'>&lt;p&gt;I'm back from a 2 week holiday in &lt;a href="http://en.wikipedia.org/wiki/Ischia"&gt;Ischia&lt;/a&gt; (Italy). I like to take a book or two with me because I rarely find the leisure (and the concentration) to read something complex during my normal life. This time, it was &lt;a href="http://www.lucifereffect.org/"&gt;The Lucifer Effect&lt;/a&gt; by &lt;a href="http://www.zimbardo.com/"&gt;Philip Zimbardo&lt;/a&gt;. If you haven't heard about this guy, you may have heard about the &lt;a href="http://www.prisonexp.org/"&gt;Stanford Prison Experiment&lt;/a&gt; (SPE). If you haven't heard about this as well, here is a short summary: Take 20 random, normal people (i.e. someone like you and me and your neighbor), put them into a situation where they can get away with anything and watch them turn into human nightmares within &lt;em&gt;a few days.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The book explains in great detail how normal people turn evil. Evil in the sense that they stop acting kind and instead start to humiliate, torture, even kill other people. The hard part of the book is to understand that these people aren't evil to begin with. They are just ordinary people. For example, most suicide bombers are well educated, have an intact family background. Still, it's exactly these people who are most vulnerable to the mechanics which turn a nice guy into Darth Vader.&lt;/p&gt;

&lt;p&gt;I'll point out a few places in the book in this post which impressed me most. On pages 167f, Jerry-5486 (one of the prisoners in the SPE) explained how he rationalized his own evil actions against a fellow prisoner by thinking "It's only a game, and I know it and I can endure it easy enough, and they can't bother my mind, so I'll go through the actions." Doing this, he could completely ignore how much his actions would hurt the people around him, even people he thought of as friends. Instead of supporting those he liked, he submitted to the cruel commands of the guards. Because of how our brains work in these circumstances, he only noticed what he had done afterwards.&lt;/p&gt;

&lt;p&gt;On page 205, there is a great quote:&lt;/p&gt;

&lt;p style="text-align: right;"&gt;Life is the art of being well-deceived; and in order that the&lt;br /&gt; deception may succeed it must be habitual and uninterrupted.&lt;br /&gt;-- William Hazlitt, "On Pedantry", &lt;em&gt;The Round Table&lt;/em&gt;, 1817&lt;/p&gt;

&lt;p&gt;as is on page 208:&lt;/p&gt;

&lt;p style="text-align: right;"&gt;Wherever anyone is against his will, that is to him a prison&lt;br /&gt;-- Epictetus, &lt;em&gt;Discourses&lt;/em&gt;, second century A.D.&lt;/p&gt;

&lt;p&gt;On page 210ff, Zimbardo explains the different factors which led to the humiliation/torture in the SPE: Situation, role expectations, responsibility (or lack thereof), anonymity and &lt;a href="http://en.wikipedia.org/wiki/Deindividuation"&gt;deindividuation&lt;/a&gt;, cognitive dissonance and social approval. On page 220, he explains how cognitive dissonance forces us to rationalize our actions when we hurt others:&lt;/p&gt;

&lt;blockquote&gt;Oddly enough, the dissonance effect becomes &lt;em&gt;greater&lt;/em&gt; as the justification for such behavior &lt;em&gt;decreases&lt;/em&gt;, for instance, when a repugnant action is carried out for little money, without threat, and with only minimal sufficient justification or inadequate rationale provided for the action. Dissonance mounts, and the attempts to reduce it are greatest, when the person has a sense of free will or when she or he does not notice or fully appreciate the situational pressures urging enactment of the discrepant action.&lt;/blockquote&gt;

&lt;p&gt;Instead of using our brain to stop what we do, we use it to explain the pain away. The less reason someone has to be cruel, the stronger the desire to give the cruel actions a reason that will make it "look good". Ever wondered why anyone will come up with such unreal excuses when they are caught? That's why.&lt;/p&gt;

&lt;p&gt;In out daily life, we feel that our reason is in control when in fact, it's the situation that shapes how we see the world and thus forces our hand without our reason even noticing. This is what happens when the government calls the population to arms because of a "threat to national security". Ironically, it was always those who yelled that were the threat (and not those who were accused). Unfortunately, situational forces, our shared desire for social approval, drives us to believe the yellers even when five minutes of rational thought would show how silly their words and how false their motives must be (p. 226ff). This is what lead to slaughter of the Jews in World War II, the &lt;em&gt;Challenger&lt;/em&gt; disaster, the &lt;a href="http://en.wikipedia.org/wiki/Rwanda#French-Government_and_Military_Help_To_The_Genocide_And_Its_Perpetrators"&gt;genocide in Rwanda&lt;/a&gt; and the abuses in &lt;a href="http://en.wikipedia.org/wiki/Abu_Ghraib_torture_and_prisoner_abuse"&gt;Abu Ghraib&lt;/a&gt; (which was one of the more harmless &lt;a href="http://www.hrw.org/reports/2005/us0405/"&gt;incidents in US prisons in the area&lt;/a&gt;). It's always the same mechanisms which lead to these results.&lt;/p&gt;

&lt;p&gt;The basics of these mechanisms are listed on p. 230: Our need "&lt;em&gt;for consistency and rationality&lt;/em&gt;", our need "&lt;em&gt;to know and to understand our environment and our relationship to it&lt;/em&gt;" and "our &lt;em&gt;need for stimulation&lt;/em&gt;". Also, how we sense time has a great influence on our behavior (p. 243): Do we believe in the past? The future? Do we have reason to plan or do we sit back in depression because we feel all our plans and hopes are in vain?&lt;/p&gt;

&lt;p&gt;These same mechanisms are used by the military to train normal people (which still have an inhibition to kill) into people who can kill on command. A visitor to the &lt;a href="http://www.prisonexp.org/"&gt;SPE website&lt;/a&gt; explains how the drill instructors used the usual old, irrational lie to punish the group for a mistake: "if you guys would have moved faster, we wouldn't be doing this for hours". Well, the only reason why the group is going "this" is because of the drill instructor (p. 256).&lt;/p&gt;

&lt;p&gt;Tests show that group pressure is a great tool to create obedience. Imagine you had to judge the length of a line on a card against three reference cards. Doing the test alone, you'd get it right more than 99% of the time. But what if you were in a group with several people who would chose the wrong answer &lt;em&gt;on purpose?&lt;/em&gt; Could you resist the urge to comply to the group or would you submit? When the experiment was done, 70% of 123 test persons caved and agreed with the group that two obviously different lines had the same length (p. 263). Modern technologies allow to look into the brain and help to understand what happens. If you deviate from the group's consensus, the images from your brain will show that "resistance creates an emotional burden for those who maintain their independence -- autonomy comes at a psychic cost" (p. 265). The images also show that often, you don't even notice the conflict. The brain will adjust it's perception of the world to what the group wants to believe &lt;em&gt;before&lt;/em&gt; reason is even asked for its opinion.&lt;/p&gt;

&lt;p&gt;That all leads to &lt;a href="http://en.wikipedia.org/wiki/Milgram_experiment"&gt;Milgram's experiment&lt;/a&gt; where unsuspecting test persons would be lead by the experimenter to apply deadly electrical shocks to another person. Of course, the other person was a confederate and the shocks were never actually applied but the test person didn't know that. 66% of the test persons would go all the way even when the "victim" would scream in pain and beg for mercy. Most would even continue after the "victim" stopped responding. Because the results were so shocking, the experiment was repeated with different people in different countries. With different settings, Milgram could get the compliance rate (people who would go through the whole hell until the bitter end) from 10% to 90%. It didn't matter &lt;em&gt;who&lt;/em&gt; was tested but &lt;em&gt;how.&lt;/em&gt; From the results of his various experiments, Milgram compiled a list of ten methods to turn anyone into a torturer (p. 273f):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a sense of obligation (for example, make a contract or say "you have to protect your country/family/whatever").&lt;/li&gt;

&lt;li&gt;Give the participant a positive role (teacher, protector, soldier)&lt;/li&gt;

&lt;li&gt;Present a set of rules that seem to make sense at first glance. It doesn't matter if they are really consistent since you can later change them arbitrarily.&lt;/li&gt;

&lt;li&gt;Make the job sound harmless. Don't say "hurt the prisoner", say "protect the country".&lt;/li&gt;

&lt;li&gt;Make sure no one really feels responsible for what happens or that everyone can point at someone else to blame when something bad happens. In Milgram's Experiment, a lot of people stopped unless the experimenter told them "I'll accept full responsibility if the other person is harmed".&lt;/li&gt;

&lt;li&gt;Start with an act that points in the general direction but doesn't seem too bad ("We'll just lock these people up to protect society").&lt;/li&gt;

&lt;li&gt;Work with small, seemingly insignificant steps ("that's not much different from what I did yesterday"). Humans are great for detecting big changes but they suck with little ones.&lt;/li&gt;

&lt;li&gt;Gradually change the nature of the authority figure (leader, boss) from "just and reasonable" to "unjust, demanding, even irrational". If you do this in little steps, the subject won't notice and still believe in the "first impression" even after the transformation is complete. At that stage, the leader can ask anything and (s)he will get it.&lt;/li&gt;

&lt;li&gt;Make exiting hard. People are allowed to complain but insist that they still follow the orders to the letter ("Do you want to ruin everything we achieved?")&lt;/li&gt;

&lt;li&gt;Offer an ideology, an explanation or a big lie to justify the use of any means to achieve the seemingly desirable ends.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;If you get everything right, 90% of all people will follow you to hell and beyond. If you take these rules, you can easily find parallels to the many dictatorships around the planet. That's how and why they work and why it is so hard to break them down from within.&lt;/p&gt;

&lt;p&gt;There are also references to anonymity experiments with schoolchildren during Halloween (p. 301) which shows what happens if people can be aggressive anonymously. In this scenario, they will act more aggressive unless they can be identified, even if their aggressive behavior is not in their best interest.&lt;/p&gt;

&lt;p&gt;Being part of a group apparently causes us to reduce our self-awareness (a process called &lt;a href="http://en.wikipedia.org/wiki/Deindividuation"&gt;deindividuation&lt;/a&gt;, p. 305) and our ratio  (our "good" sides) in favor of our "Dionysian nature", where instincts, lust and desire rule. This is what creates the strong group cohesion or "peer pressure" which allows us to create a civilization despite our egos. But if you don't know about these effects, then they can get out of hand, driving the group ever deeper towards chaos or evil.&lt;/p&gt;

&lt;p&gt;These effects are enhanced when we see other people as inferior, non-human, animals or objects. In the end, it leads to a state of moral disengagement (p. 310). In this state, the people of the group are still able to understand that their actions are wrong but they don't care anymore. This state allows people to kill, torture, rape.&lt;/p&gt;

&lt;p&gt;We don't even have to go that far. People are less likely to help when they are in a hurry (p. 316). The same effect is at work when a large group of bystanders watch someone suffer and don't intervene to help. Or when a sane person is taken to a mental hospital (p. 321). Staff members of a hospital played the role of patients for a short period of time and were very surprised how they were treated by their colleagues on duty. In the end, lawyers had to demand their release or they would still be in the ward.&lt;/p&gt;

&lt;p&gt;Or Abu Ghraib. In chapter 14, Zimbardo dissects the situation and the people behind the media hype we all know from the images in the news shows. An apparently normal, mental healthy soldier is thrown into a situation where a &lt;a href="http://www.time.com/time/magazine/article/0,9171,1129601-1,00.html"&gt;life doesn't count much&lt;/a&gt;, there is no support from outside or superiors, the place is under constant attack by the locals and local forces that are supposed to help instead smuggle weapons into the cells of the prisoners for money and your superiors order you to torture to get intelligence from the prisoners. And the icing of the cake is that you get the night shift which means sleep deprivation. How long could you withstand such a stress? Staff Sergeant &lt;a href="http://en.wikipedia.org/wiki/Ivan_Frederick"&gt;Chip Frederick&lt;/a&gt; (that's the guy who got all the blame for the incident) made it for more than two months until he caved (p. 343).&lt;/p&gt;

&lt;p&gt;From the official news, you might get the idea that he was accused to have tortured the prisoners. I find that hard to believe. Others have killed prisoners and are still walking free (see &lt;a href="http://www.time.com/time/magazine/article/0,9171,1129601-1,00.html"&gt;"The Iceman"&lt;/a&gt;). From my point of view, he was convicted for making trophy photos. Other teams with similar records were instructed to destroy the evidence before returning home. The kind reader is welcome to draw his/her own conclusions.&lt;/p&gt;

&lt;p&gt;This pattern of taking trophy photos comes up again and again when people are abused. It happened when black men and women were lynched in the US, German soldiers took them after committing atrocities against Polish Jews and Russians, etc. The list is endless. But there is a difference between these photos and real trophy photos (taken when a big-game hunter had his shot). On the original photos, the hunters don't laugh and cheer. They appear "rather grim, rarely are they smiling: they are victors in a battle against formidable adversaries." (p. 364).&lt;/p&gt;

&lt;p&gt;The author goes on to explain how the Bush government actively helped to produce the environment which lead to abuses like in Abu Ghraib and many other places in Afghanistan and the Iraq, Guantanamo, and probably elsewhere, too. The last figure I know is of 600 similar incidents. An interesting if controversial read.&lt;/p&gt;

&lt;p&gt;Chapter 16 contains the most important part of the book: How to fight evil. Not on a big scale but on a personal one. How to notice and withstand forces which try corrupt you. On page 451ff, you can find a list of ten steps to "resist unwanted influences". I especially like "Reject simple solutions as quick fixes for complex personal or social problems." Print that out and read it twice every morning.&lt;/p&gt;

&lt;p&gt;Even if you don't read the rest of the book, look at these few pages. They alone are worth the buy.&lt;/p&gt;

&lt;p&gt;In the last part of the book, Zimbardo takes a look at heroism. Unlike popular belief, heroes and heroines are ordinary people who just did the right thing at the right time at great personal risk because they believed they had to do it (p. 457). Or as the author puts it (p. 466):&lt;/p&gt;

&lt;blockquote&gt;Heroism can be defined as having four key features: (a) it must be engaged in voluntarily; (b) it must invoke a risk or potential sacrifice, such as the threat of death, an immediate threat to the physical integrity, a long-term treat to health, or the potential for serious degradation of one's quality of life; (c) it must be conducted in service to one or more other people or the community as a whole; and (d) it must be without secondary, extrinsic gain anticipated at the time of the act.&lt;/blockquote&gt;

&lt;p&gt;Recommendation: Must Have.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-3216635699774825179?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/3216635699774825179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=3216635699774825179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3216635699774825179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/3216635699774825179'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/lucifer-effect_13.html' title='The Lucifer Effect'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1549297790368722017</id><published>2008-06-12T18:05:00.003+02:00</published><updated>2008-06-17T10:18:47.099+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>The Craft of Text Editing</title><content type='html'>&lt;p&gt;While looking for a decent code base for a text editor on &lt;a href="http://code.google.com/"&gt;Google Code&lt;/a&gt; (tip: search for "label:editor"), I found a &lt;a href="http://code.google.com/p/epytor/wiki/GeneralTheory"&gt;wiki page&lt;/a&gt; in the &lt;a href="http://code.google.com/p/epytor/"&gt;epytor project&lt;/a&gt; which links to "&lt;a href="http://www.finseth.com/craft/"&gt;The Craft of Text Editing&lt;/a&gt;", by Craig A. Finseth. That document not only explains all the basic algorithms behind the scenes of a text editor but also compares different implementations and contains a wealth of useful general comments.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1549297790368722017?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1549297790368722017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1549297790368722017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1549297790368722017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1549297790368722017'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/craft-of-text-editing.html' title='The Craft of Text Editing'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-1004934400278018197</id><published>2008-06-12T14:17:00.003+02:00</published><updated>2008-06-17T10:18:26.442+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>Does It Have To Be a Scrollbar?</title><content type='html'>&lt;p&gt;Every once in a while, someone comes up with a nice idea and everyone adopts it. People needed a way to navigate in a document larger than the screen, so scrollbars were invented to give an idea where they are related to the whole document.&lt;/p&gt;

&lt;p&gt;Scrollbars offer a consistent interface, they are well understood and they don't change size while you use them. That's good. But they also fail give you an idea where to look when you search something. Like: Where did I modify my document? What's above and below?&lt;/p&gt;

&lt;p&gt;&lt;a href="http://code.google.com/p/farmhand/"&gt;farmhand&lt;/a&gt; shows this information. Instead of a gray/blue blob that moves, you get a zoomed view of the document along with change marks. It takes a bit more space on the screen and I'm not totally convinced how it fares with really large documents but it's definitely a new idea with some potential.&lt;/p&gt;

&lt;p&gt;I'd just put these "farmhand bars" as pop ups on the editor tabs, so they don't clutter the screen when hidden and are still easily accessible when you switch editors.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-1004934400278018197?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/1004934400278018197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=1004934400278018197' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1004934400278018197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/1004934400278018197'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/does-it-have-to-be-scrollbar.html' title='Does It Have To Be a Scrollbar?'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23170963.post-2929523258228932818</id><published>2008-06-11T17:28:00.003+02:00</published><updated>2008-06-17T10:18:10.384+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>Rich Applications in 2008</title><content type='html'>&lt;p&gt;For about five years, I'm trying to write a small OSS application to help me write SciFi stories. Today again, I ran into this familiar pain: There is just no good OSS framework to write applications. Here is what I tried:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.riverbankcomputing.com/software/pyqt/intro"&gt;PyQt 4.4&lt;/a&gt;. This is nice but you need to do a lot of manual plumbing to connect your &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; model to the Qt UI. Why are there no support classes to display a Python list in a QListView? Or to map fields from objects in a list to a QTableView? You can't even simply connect a field of an object to a basic text widget.&lt;/p&gt;

&lt;p&gt;There are other Python frameworks (wxWidget, for example) but they are even worse (less features, more complex to use, no data binding as well).&lt;/p&gt;

&lt;p&gt;So let's look at Java. What do we have? &lt;a href="http://spring-rich-c.sourceforge.net/"&gt;Spring Rich Client&lt;/a&gt; is more or less dead (they say they are working on Spring Desktop but there isn't even a web site, yet). Also, this project is locked to Swing. Not a killer feature in 2008.&lt;/p&gt;

&lt;p&gt;So let's look at &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt;. We have &lt;a href="http://www.eclipse.org/swt/"&gt;SWT&lt;/a&gt;, &lt;a href="http://wiki.eclipse.org/index.php/JFace_Data_Binding"&gt;Data Binding&lt;/a&gt; and ... well ... &lt;a href="http://www.eclipse.org/modeling/emf/"&gt;EMF&lt;/a&gt;. Some love EMF, some like it, others ... you get the idea. Also, this solution again asks for a lot of plumbing (manually connecting objects with the UI). And while I gave Eclipse 3.4 RC4 a try (to see if EMF got usable in the last three years), it crashed in USER32.dll. *sigh*&lt;/p&gt;

&lt;p&gt;Then, there is &lt;a href="http://turbogears.org/"&gt;TurboGears&lt;/a&gt;. Automatic data binding, automatic generation of a nice UI, cool. Web only ... *sigh* Maybe I should try it with &lt;a href="http://www.mozilla-europe.org/de/products/firefox/"&gt;Firefox&lt;/a&gt; and &lt;a href="http://www.mozilla.org/projects/xul/"&gt;XUL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, none of these frameworks offer a simple WYSIWYG editor which can be extended (for example with a typing help, tooltips, proportional font support).&lt;/p&gt;

&lt;p&gt;After ten years of OSS application frameworks, you'd expect that there was at least a single choice which allows to build a toy application with ten simple objects within a few minutes.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23170963-2929523258228932818?l=darkviews.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkviews.blogspot.com/feeds/2929523258228932818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23170963&amp;postID=2929523258228932818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2929523258228932818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23170963/posts/default/2929523258228932818'/><link rel='alternate' type='text/html' href='http://darkviews.blogspot.com/2008/06/rich-applications-in-2008.html' title='Rich Applications in 2008'/><author><name>Aaron Digulla</name><uri>http://www.blogger.com/profile/14968768538267443622</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
