<?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-2643514316523207801</id><updated>2012-01-18T08:20:48.776-08:00</updated><category term='BEA'/><category term='BEA Workshop'/><category term='BEA WebLogic bookmarkability browser history back/forth filter URLRewriter'/><category term='J2EE'/><category term='WebLogic'/><category term='shared library'/><title type='text'>Kenneth H. Nielsen</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kennethhn.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-2533861704377715991</id><published>2012-01-18T08:19:00.000-08:00</published><updated>2012-01-18T08:20:48.784-08:00</updated><title type='text'>uncheck checkboxes with jQuery</title><content type='html'>$('input[type=checkbox]').removeAttr('checked');&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-2533861704377715991?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/2533861704377715991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/2533861704377715991'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2012/01/uncheck-checkboxes-with-jquery.html' title='uncheck checkboxes with jQuery'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-8082521586352532684</id><published>2010-06-01T13:13:00.000-07:00</published><updated>2010-06-01T14:01:52.899-07:00</updated><title type='text'>JavaScript self-replicating program (or Quine)</title><content type='html'>This program will output the code for itself&lt;span style="font-family:monospace;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;using function.toString()&lt;/span&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;(function() {var f;function r() {&lt;br /&gt;return "(function() {var f;" + f + ";f=rep.toString();return r();})();";&lt;br /&gt;};f = r.toString();return r();})();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;using unescape()&lt;/span&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var a = "(function() { return 'var a = ' + unescape('%22') + a + unescape('%22') + ';' + a; })();";(function() { return 'var a = ' + unescape('%22') + a + unescape('%22') + ';' + a; })();&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-8082521586352532684?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8082521586352532684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8082521586352532684'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2010/06/javascript-self-replicating-program-or.html' title='JavaScript self-replicating program (or Quine)'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-8668289225270120418</id><published>2009-10-29T07:53:00.000-07:00</published><updated>2009-10-29T08:03:01.975-07:00</updated><title type='text'>Python UTF-8 for non english characters</title><content type='html'>&lt;span style="font-weight: bold;font-size:130%;" &gt;Configure module&lt;/span&gt;&lt;br /&gt;First make sure your python module is saved as UTF-8&lt;br /&gt;&lt;br /&gt;Next, in the top of your python module add the setting:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;    # -*- coding: utf-8 -*-&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;this will tell the compiler to use UTF-8 instead of OS specific&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Prefix a 'u' for all strings&lt;/span&gt;&lt;br /&gt;&lt;code&gt;    print u"rødgrød med fløde"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;- will work&lt;br /&gt;&lt;br /&gt;&lt;code&gt;    print "red porridge with cream"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;- wil work because no non-english characters are present&lt;br /&gt;(or whatever difference between your OS and UTF-8)&lt;br /&gt;&lt;code&gt;&lt;br /&gt;    print "rødgrød med fløde"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;- will not work because the encoding is misinterpreted&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Entire python script&lt;/span&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;    # -*- coding: utf-8 -*-&lt;br /&gt;    print u"rødgrød med fløde"&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-8668289225270120418?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8668289225270120418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8668289225270120418'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2009/10/python-utf-8-for-non-english-characters.html' title='Python UTF-8 for non english characters'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-6286124415464640593</id><published>2009-08-31T14:09:00.000-07:00</published><updated>2009-08-31T14:15:28.564-07:00</updated><title type='text'>KHAN's ladder to programming excellence!</title><content type='html'>In Maxwell Gladwells book 'Outliers' he mentions that in order to excel in anything you have to put atleast 10000 hours in to it, which is the equivalent of 6 hours each day in 5 years. 356 * 5 * 6 = 10680, well almost.&lt;br /&gt;&lt;br /&gt;Here I present the ladder of programming excellenceu as perceived by me :)&lt;br /&gt;Legend: HoP = Hours of Programming&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;KHAN's ladder to programming excellence!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I reckoned I hit the programming experience mark of 5000 hours 5 years ago.&lt;br /&gt;&lt;br /&gt;Programming in Basic and DOS before my education = 1000 HoP&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic; font-weight: bold;font-size:130%;" &gt;beginning programmer&lt;/span&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;1000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;Programming in high school Assembler, electronics, VB, Java, ASP, HTML: 1000 HoP&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;font-size:130%;" &gt;greenhorne programmer&lt;/span&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;2000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;Higher education as datamatician(mostly Java) 2 1/4 years, with an average of 140 hours a month: 4000 HoP&lt;br /&gt;&lt;br /&gt;- at this point I broke the 5000 HoP&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;span style="font-style: italic;"&gt;jorneyman programmer&lt;/span&gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;4000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;After the bulk of work with non-contractor jobs 3 years, with an average of 180 hours a month: 6500 HoP&lt;br /&gt;This involved mostly Java with J2EE, but I began on more complex tasks like configuring WebSphere servers, designing parts of enterprise wide technical solutions. Here I picked up many new complex skills, Eclipse RCP, Version control, functional programming, unit testing, server administration etc.&lt;br /&gt;- here i accelarated because I had to break into many new concepts and frameworks, working after hours and reading a lot while experimenting.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;span style="font-style: italic;"&gt;veteran programmer&lt;/span&gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;8000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;At this point I started my own company and began working as a freelancer. I had no products, no particular approach or plan, only my skill as a programmer. Though I discovered I also needed economical and business skills.&lt;br /&gt;In this work I now have 2 years of experience, my pace has slowed down and I would now estimate to having 170 hours per month of IT experience: 4000 HoP, making a total of 16500 HoP.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;span style="font-style: italic;"&gt;expert programmer&lt;/span&gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;16000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;master for me is 5 years away&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;span style="font-style: italic;"&gt;master programmer&lt;/span&gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;32000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;I might achieve programming guru before retirement&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;span style="font-style: italic;"&gt;programming guru&lt;/span&gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;64000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;//TODO insert lots of effort&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;deity programmer&lt;/span&gt; - &lt;/span&gt;&lt;span style="font-size:130%;"&gt;128000&lt;/span&gt; HoP&lt;br /&gt;&lt;br /&gt;I think of this scale as a logarithmic one. Each step requires the double amount of effort and I find this to be quite true. At a time while being greenhorne I experienced discovering new things more often, towards becoming a guru I can only guess to what I learn.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-6286124415464640593?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6286124415464640593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6286124415464640593'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2009/08/khans-ladder-to-programming-excellence.html' title='KHAN&apos;s ladder to programming excellence!'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-7227864571495175684</id><published>2009-04-13T14:26:00.000-07:00</published><updated>2009-04-13T15:09:07.801-07:00</updated><title type='text'>Automatically testing advanced web applications (revisited)</title><content type='html'>More than one and a half years ago I first posted a blog article &lt;a href="http://kennethhn.blogspot.com/2007/12/high-automatic-test-coverage-of-web.html"&gt;'high automatic test coverage of web applications'&lt;/a&gt;. While working with this and later projects I realized that in order to have complete coverage and a more dynamic testing environment I had to take it a step further and therefore started inventing my own test framework, described in the article &lt;a href="http://kennethhn.blogspot.com/2008/02/full-testing-with-javascript.html"&gt;'full testing with javascript'&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Soon thereafter I discovered the &lt;a href="http://seleniumhq.org/projects/core/"&gt;Selenium Core&lt;/a&gt; framework which was still rather immature. Since it functions similar to the framework I was working on, I gave it a go and never looked back.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Testing priorities in a web application&lt;/span&gt;&lt;br /&gt;When testing you have to first plan what areas need the most testing. Test driven development requires a lot of focus on unit testing and functional testing. I will not discuss unit testing here, since it depends heavily on the platform of the web application.&lt;br /&gt;Aside from unit testing, functional testing is the most important testing for web applications, because it can be used to directly measure progress and prohibits regression.&lt;br /&gt;On a second place comes integration testing, because alot of problems tend to occur in communication with other systems.&lt;br /&gt;In third comes performance testing. This tends to be the focus of automatic tests, but that is an ancient view imo. Performance testing is important, but it's rather easy once functional testing has been done, because you can leverage the functional tests and scale them to performance tests.&lt;br /&gt;On a fourth place comes installation testing. Redeploying a web application is important, both for testing environments, but also for reestablishing an environment.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Functional testing&lt;/span&gt;&lt;br /&gt;this is exactly what Selenium is for. It's fast and works for Python, Java and several other popular platforms. I would go for Python because the interactive compiler is killer for writing test cases. Java is not a bad alternative with Seleniums excellent integration with JUnit.&lt;br /&gt;You should not need any other tool for this task.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Performance testing&lt;/span&gt;&lt;br /&gt;For performance testing you could use &lt;a href="http://httpunit.sourceforge.net/"&gt;HTTPUnit&lt;/a&gt;, which also integrates well with JUnit. It's a rather simple, but powerful framework for controlling all parameters of requests and monitoring the responses.&lt;br /&gt;Functional test cases written for functional testing using Selenium could be rewritten easily and scaled to do performance testing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Integration testing&lt;/span&gt;&lt;br /&gt;This depends on what technology is used for communication, I'll only present the most common one here. Integration in web applications are typically over Web Services, therefore testing could be done with a framework for easily creating web clients, like &lt;a href="http://ws.apache.org/axis2/"&gt;Axis 2&lt;/a&gt; and using JUnit to execute it, but HTTPUnit is also viable.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Installation testing&lt;/span&gt;&lt;br /&gt;Installation testing involves two parts. Scripts to deploy the application and verification of the function.&lt;br /&gt;Scripts would typically depend on the platform of the web application. For WebLogic or WebSphere, you would use &lt;a href="http://ant.apache.org/"&gt;ant&lt;/a&gt; targets available from the vendor. How you manage to deploy the application automatically is rather irrelevant, since you needn't verify anything during the process.&lt;br /&gt;The second part of verifying function after installation is rather easy, since it's just a matter of running the functional tests.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;Using a few open source tools is an easy, fast and effective way to test advanced Web Applications with lots of javascript and complexity.&lt;br /&gt;Standardizing the executing can be achieved using a common executing framework like JUnit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-7227864571495175684?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7227864571495175684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7227864571495175684'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2009/04/automatically-testing-advanced-web.html' title='Automatically testing advanced web applications (revisited)'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-7185290644908033687</id><published>2009-02-26T12:32:00.000-08:00</published><updated>2009-02-26T13:03:36.070-08:00</updated><title type='text'>KHANDI the temporal database manager</title><content type='html'>Introduction&lt;br /&gt;On contract for a customer I had to develop a temporal database manager.&lt;br /&gt;&lt;br /&gt;The problem is very simple. You have an entity that exists from a data to another date and is dependent on another entity to exist in the same period.&lt;br /&gt;&lt;br /&gt;Consider the example below, this is a valid dependency, because, the dependency exists in atleast the same period as the entity.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Entity&lt;br /&gt;     I-------------I&lt;br /&gt;&lt;br /&gt;Dependency Entity&lt;br /&gt;   I-------------------I&lt;br /&gt;&lt;br /&gt;Legend:&lt;br /&gt;lines represent the existance of the entities&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Considering you have to edit an entity, you have two basic changes you can make.&lt;br /&gt;Edit attributes of an entity, creating a new record from that point, or&lt;br /&gt;Edit the period in which the entity exists&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Editing attributes&lt;/span&gt;&lt;br /&gt;Entity&lt;br /&gt;     I-------I (attribute changed on this date)&lt;br /&gt;              I----I&lt;br /&gt;&lt;br /&gt;Dependency Entity&lt;br /&gt;   I-------------------I&lt;br /&gt;&lt;br /&gt; - dependency is still valid&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Editing period&lt;/span&gt;&lt;br /&gt;Entity&lt;br /&gt;     I-------I (end date of entity is sooner)&lt;br /&gt;&lt;br /&gt;Dependency Entity&lt;br /&gt;   I-------------------I&lt;br /&gt;&lt;br /&gt; - dependency is still valid&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now consider the situation where a user makes an invalid edit.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Invalid edit&lt;/span&gt;&lt;br /&gt;Entity&lt;br /&gt;     I-------------------I (end date of entity is later)&lt;br /&gt;&lt;br /&gt;Dependency Entity&lt;br /&gt;   I-------------------I&lt;br /&gt;&lt;br /&gt; - dependency is NOT valid&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The main point of this last example is that there's a lot of checks that need to be made before editing something.&lt;br /&gt;&lt;br /&gt;The database I've made with the customer consists of multiple tables 20+, that are all interdependent.&lt;br /&gt;&lt;br /&gt;The component I've written is an ORM with temporal management built-in and transparently handles these relation restrictions as defined in the business logic.&lt;br /&gt;&lt;br /&gt;Although very clean, it poses some challenges in a UI. If you need to edit several types of entities in the same submit, you could end up having dependencies, that may put the user in a deadlock. Therefore, one should consider if temporal management of an entitty is really necessary to store temporally.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;KHANDI Component short:&lt;/span&gt;&lt;br /&gt;temporal ORM manager&lt;br /&gt;compliable with java 1.4&lt;br /&gt;Connects with SAS and MySQL out of the box, easily integratable with other dbs&lt;br /&gt;&lt;br /&gt;Write me at &lt;a href="mailto:kennethhn@gmail.com"&gt;kennethhn@gmail.com&lt;/a&gt;, if interested in knowing more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-7185290644908033687?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7185290644908033687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7185290644908033687'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2009/02/khandi-temporal-database-manager.html' title='KHANDI the temporal database manager'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-5231488667475082313</id><published>2009-01-12T03:18:00.000-08:00</published><updated>2009-01-12T03:21:05.441-08:00</updated><title type='text'>TOMCAT UTF-8 gotcha</title><content type='html'>If you are having problem with your encoding running on a platform with other than UTF-8 as a default, try going through your code and make sure request.getParameter() is not called before setting request.setCharEncoding().&lt;br /&gt;&lt;br /&gt;example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  request.setCharacterEncoding("UTF-8");&lt;br /&gt;  String adUser = request.getParameter(TAM_AD_USER);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If you have no hook for it, consider making a filter: http://cagan327.blogspot.com/2006/05/utf-8-encoding-fix-tomcat-jsp-etc.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-5231488667475082313?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5231488667475082313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5231488667475082313'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2009/01/tomcat-utf-8-gotcha.html' title='TOMCAT UTF-8 gotcha'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-864146587562209618</id><published>2008-09-08T06:11:00.000-07:00</published><updated>2008-09-10T04:24:42.272-07:00</updated><title type='text'>Full JS applications</title><content type='html'>Recently I asked my network for novel ideas for small web applications or sites.&lt;br /&gt;&lt;br /&gt;My accountant mentioned that he had a hard time calculating distance travelled for some of his customers. He needs to calculate the specific distance for any  trip made in a private car for a refund from the danish IRS.&lt;br /&gt;&lt;br /&gt;For each trip made by an employee in one of the companies he used to go to a GeoCoding site like &lt;a href="http://www.maps.google.com"&gt;http://www.maps.google.com&lt;/a&gt;. Plot in 1 trip with From and To addresses, take the distance and put it into a spreadsheet. And so his days went. He made sure to mention to me that it is a problem for many smaller companies.&lt;br /&gt;&lt;br /&gt;Using Google's public GeoCoding services I managed to put together an application run entirely by javascript. It is available at &lt;a href="http://www.kennethhn.dk/map.html"&gt;http://www.kennethhn.dk/map.html&lt;/a&gt;, it is in danish, until I bother using JS I18N. To give it a go, I included a demo, click 'tryk her for hjælp og demo', in the appeared box click 'klikke her'. Then at the bottom of the page click 'beregn alle'. This will calculate all the inputs with the rate of DKK/KM.&lt;br /&gt;&lt;br /&gt;Then to print the results click 'print'.&lt;br /&gt;&lt;br /&gt;The tricky thing here is to transfer all the data. What I did was serialize all the data in JSON and put it as a parameter for the print page.&lt;br /&gt;&lt;br /&gt;Aside from some escape issues, this transfer works perfectly. It might aswell have been a server request, but this way, you don't need all that performance reducing Serverside rendering..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-864146587562209618?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/864146587562209618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/864146587562209618'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2008/09/full-js-applications.html' title='Full JS applications'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-6877186570823004291</id><published>2008-03-06T11:02:00.000-08:00</published><updated>2009-04-13T14:26:19.271-07:00</updated><title type='text'>cross site javascript</title><content type='html'>&lt;a href="http://www.kennethhn.dk/webhole/demo.html"&gt;This&lt;/a&gt; is an ajax widget I wrote, while learning about cross site scripting (xss). Read more about the Webspace wormhole &lt;a href="http://www.kennethhn.dk/webhole/index.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The idea is that on any page on any browser I should be able to embed this script and it will share content. Much like Google maps and a ton of other useful stuff from Yahoo and Google.&lt;br /&gt;&lt;br /&gt;On the page itself the script only needs a small amount of information, like the id of the div it will use for the graphics and what 'tag' it will subscribe to.&lt;br /&gt;&lt;br /&gt;The transport it uses is not the typical Ajax.Request from the &lt;a href="http://www.prototypejs.org"&gt;prototype&lt;/a&gt; lbirary, because this uses solely XMLHttpRequest, which for security reasons default in browsers is not cross site.&lt;br /&gt;&lt;br /&gt;Instead I had to write a transport of my own. The basic work-around is to embed a script element in the dom created by a dynamic page. This way, when the script is loaded it can inject data into the javascript execution, just like a plain script file. I implemented a reusable class for it, thusly:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var Transport = Class.create({&lt;br /&gt; initialize: function(url, jsonCallback) {&lt;br /&gt;  this.url = url;&lt;br /&gt;  this.jsonCallback = jsonCallback;&lt;br /&gt; },&lt;br /&gt; activate: function() {&lt;br /&gt;   this._cleanUpScript(this.url);&lt;br /&gt;   var script_object = new Element('script', {src: this.url, type: 'text/javascript'});&lt;br /&gt;     var head=document.getElementsByTagName('head')[0] ;&lt;br /&gt;     head.appendChild(script_object);&lt;br /&gt;     this._xssScriptLoad(); &lt;br /&gt; },&lt;br /&gt; _xssScriptLoad: function() {&lt;br /&gt;  var _this = this;&lt;br /&gt;  if(typeof(wh_xss_result) != 'undefined') {&lt;br /&gt;     this.jsonCallback(wh_xss_result);&lt;br /&gt;     void(wh_xss_result);&lt;br /&gt;    } else  {&lt;br /&gt;     setTimeout(function(){_this._xssScriptLoad();}, 100);&lt;br /&gt;    }&lt;br /&gt; },&lt;br /&gt; _cleanUpScript: function(url) {&lt;br /&gt;  $A(document.getElementsByTagName('script')).each(function(el){&lt;br /&gt;   if(el.src == url){&lt;br /&gt;    el.remove();&lt;br /&gt;   };&lt;br /&gt;  });&lt;br /&gt; }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The only 'gotcha' here is that I have to know the name of the variable that the result is stored in. This could be set on the serverside if I pass it as a parmater if I want the serverside to be more reusable, but for the sake of my little wormhole, I hardcoded the variable on both sides.&lt;br /&gt;&lt;br /&gt;Here is an example usage of the transport:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var url = 'http://www.kennethhn.dk/webhole/get.php?tag=science';&lt;br /&gt;var t = Transport(url, function(json){alert("json object = " + json});&lt;br /&gt;t.activate();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;In this case, the url is a reference to a php script on my site that returns a url for  content submitted for the tag.&lt;br /&gt;&lt;br /&gt;The second argument is a callback function, that will be called with the resulting json object.&lt;br /&gt;&lt;br /&gt;The result might look like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var wh_xss_result = {&lt;br /&gt;    message: 'fetched url for tag science',&lt;br /&gt;    result: 'http://tbn0.google.com/images?q=tbn:-U28WILXKSXv5M:http://www.familycourtchronicles.com/philosophy/wormhole/wormhole-diagram.jpg'}; &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The transport class will then embed the result as a script and set a timeout event to repeat until the browser has loaded the script. Loading of the script is determined by  the variable wh_xss_result, which will be 'undefined' until executed.&lt;br /&gt;&lt;br /&gt;Xss can be very useful, but also very dangerous, just be vary of what scripts you choose to embed.&lt;br /&gt;&lt;br /&gt;Update 13/04/2009: removed the WebSpace wormhole from this page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-6877186570823004291?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6877186570823004291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6877186570823004291'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2008/03/cross-site-javascript.html' title='cross site javascript'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-1666159053594549021</id><published>2008-02-26T01:38:00.000-08:00</published><updated>2008-02-26T02:09:19.208-08:00</updated><title type='text'>Full testing with JavaScript</title><content type='html'>In my efforts to achieve a full and robust test of web applications I have run into several difficulties.&lt;br /&gt;1. simulating different browsers&lt;br /&gt;2. keeping test scripts simple&lt;br /&gt;3. fragile tests&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Simulating different browser&lt;/h3&gt;&lt;br /&gt;Initially I achieved this using the Canoo Webtest. Though powerful, this integration fo different third party frameworks has shown not to be able to handle JavaScript very well. This means that if you have no control over the javascript in an application, the test becomes very fragile.&lt;br /&gt;&lt;br /&gt;Instead I concluded that the best way to simulate the different browsers is not to actually simulate them. Instead it is very efficient to inject JavaScript along with your tests into the page that you wish to test and thereby testing on the executed page.&lt;br /&gt;&lt;br /&gt;Several issues comes with this. Firstly, the security in the browser won't allow you to execute JS on another page, if they are not from the same domain, so you have to execute the test from the domain itself. For inhouse testing this is not a problem, but involves some more deployment.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;keeping test script simple&lt;/h3&gt;&lt;br /&gt;This is really up to the implementation of the web application. If its based on poor standard, test script become increasingly difficult. If for example id's are duplicated or tags are broken, the traversal of the DOM becomes difficult. The best solution to this is to stick to strict xhtml and keep your styles in CSS while maintaining ids on all divs.&lt;br /&gt;&lt;br /&gt;A second worry is that the script becomes complicated with lots of hacks and too much code, but this is really up to the framework being used. The better the framework and web application coexist, the easier and cleaner the scripts become.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;fragile tests&lt;/h3&gt;&lt;br /&gt;With a low sense of 'standards' in a project, the test become very fragile. The team must agree upon how to use divs and lists etc. Once referring to an id of a div or anchor at a specific position, that has moved or is renamed, the script might have to be rewritten. The framework should help avoid too specific referenced. Whenever referencing an element in the DOM, reference it as lenient as possible.&lt;br /&gt;&lt;br /&gt;here is an example of how the framework might be implemented&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;MyTestFramework.clickLink = function(text) {&lt;br /&gt;  $$('a').each(function(el){if(el.innerHTML==text){window.location=el.href}});&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;MyTestFramework.clickLink('login');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I'll be working on this and post when I have a functioning framework. I'll proably pull in some JSUNit library and use that for a backbone for TestCase and TestRunner.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-1666159053594549021?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1666159053594549021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1666159053594549021'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2008/02/full-testing-with-javascript.html' title='Full testing with JavaScript'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-1302209888880242967</id><published>2008-02-07T00:56:00.000-08:00</published><updated>2008-02-18T05:54:27.593-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BEA WebLogic bookmarkability browser history back/forth filter URLRewriter'/><title type='text'>Making the BEA Weblogic Portal bookmarkable</title><content type='html'>&lt;h2&gt;The issue&lt;/h2&gt;&lt;br /&gt;The two big Portal servers I know have problems with state. WebSphere and WebLogic.&lt;br /&gt;&lt;br /&gt;It seems as though somewhere along the productline, someone concluded that maintaining state in the portal while having clean bookmarkable URLs and back/forth working, was too much of a hassle, so they decided to disregard bookmarkability and browser history.&lt;br /&gt;&lt;br /&gt;In any major portal project I have worked, this issue has come up. The customer says it's a 'need to have', and I agree.. but the portals really should handle this internally.. alas they don't.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;A Weblogic solution&lt;/h2&gt;&lt;br /&gt;Through an experienced BEA developer I heard of a URL-rewriter plugin for the WebLogic portal, which might offer a solution. The idea is pretty straightforward, anywhere a URL is compiled, the URL rewriter is called upon to do it's *magic*.&lt;br /&gt;Decompiled from 'com.bea.portlet.GenericURL', it looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if(urlRewriterPlugin != null)&lt;br /&gt;{&lt;br /&gt;    ServletContext servletContext = UIContext.getFromRequest(httpRequest).getServletContext();&lt;br /&gt;    String target = path;&lt;br /&gt;    if(path != null || contextualPath != null)&lt;br /&gt;    {&lt;br /&gt;        DefaultUrl defaultUrl = resolveTemplate(removeUnsetParams);&lt;br /&gt;        target = defaultUrl.url;&lt;br /&gt;    }&lt;br /&gt;    if(scopedRequest != null)&lt;br /&gt;        val = urlRewriterPlugin.createUrl(target, params, getUrlType(), isStandalone(), scopedRequest, httpResponse, servletContext);&lt;br /&gt;    else&lt;br /&gt;        val = urlRewriterPlugin.createUrl(target, params, getUrlType(), isStandalone(), httpRequest, httpResponse, servletContext);&lt;br /&gt;    if(debug.ON)&lt;br /&gt;        debug.out((new StringBuilder()).append("Output from the URL rewriter: ").append(val).toString());&lt;br /&gt;    if(urlCompression != null &amp;&amp; !suppressUrlCompression &amp;&amp; val != null &amp;&amp; !val.startsWith("wsrp_rewrite?"))&lt;br /&gt;        val = compress(val);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see its a typical adapter pattern. What we can also see is that the URL rewriter also has to address the complexity of ScopedRequest, which is probably used for referencing any resources inside the scope of a portlet.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Implementing the rewriter&lt;/h2&gt;&lt;br /&gt;Firstly it must implement the interface 'com.bea.portlet.GenericURL.UrlRewriterPlugin'.&lt;br /&gt;this interface forces the method:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public String createUrl(String path, Map parameters, String urlType, boolean&lt;br /&gt; isStandAlone, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, there's a lot of different parametres here, but we are only/mostly interested in parameters and the request.&lt;br /&gt;Back to the issue of the ScopedRequest; We actually just want to ignore it, any request string coming in, should be the same coming out with the parameters trailing. In order to disregard a ScopedRequest, you can do something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  if(request instanceof ScopedRequestImpl) {&lt;br /&gt;   ServletRequest sRequest = ((ScopedRequestImpl) request).getRequest();&lt;br /&gt;   request = ((ScopedRequestImpl) request).getOuterRequest();&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now you have the original request and you may add any parameters you like. Firstly though, be sure to add all parameters from the Map parameters in order to keep any state the framework put there in the first place.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Example use case&lt;/h2&gt;&lt;br /&gt;One use of this is to have the portlets react to a parameter on the request. Thereby allowing a bookmarkable URL to return to the same page, with the same information. One side effect of this is that back and forth will be working, since the browser history executes via URLs :).&lt;br /&gt;The responsibility of maintaining the parameters is then up to the portlets themselves. I will leave it up to individual projects to implement a backbone for the portlets communication with the URL rewriter. But using session might be the easy way out..&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Registering the URL rewriter&lt;/h2&gt;&lt;br /&gt;The URL rewriter is retrieved from the request by the framework, but we need a way of putting it there in the first place. The simple solution is to use a filter, so we'll do just that:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void doFilter(ServletRequest request, ServletResponse response, FilterChain&lt;br /&gt; chain) throws IOException, ServletException {&lt;br /&gt;request.setAttribute(UrlRewriterPlugin.URL_REWRITER_PLUGIN, new MyURLRewriter());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and then add the appropriate configuration in the web.xml:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;filter&amp;gt;&lt;br /&gt;    &amp;lt;filter-name&amp;gt;URLFilter&amp;lt;/filter-name&amp;gt;&lt;br /&gt;    &amp;lt;filter-class&amp;gt;com.mycompany.URLFilter&amp;lt;/filter-class&amp;gt;&lt;br /&gt;&amp;lt;/filter&amp;gt;&lt;br /&gt;&amp;lt;filter-mapping&amp;gt;&lt;br /&gt;    &amp;lt;filter-name&amp;gt;URLFilter&amp;lt;/filter-name&amp;gt;&lt;br /&gt;    &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;    &amp;lt;dispatcher&amp;gt;REQUEST&amp;lt;/dispatcher&amp;gt;&lt;br /&gt;&amp;lt;/filter-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Prologue&lt;/h2&gt;&lt;br /&gt;These few tips should be enough for a developer to implement bookmarkability in a WebLogic portal server. But beware of this solution, since it is highly dependant on the BEA implementation. If any issues regarding bad URLs pop-up, I would refer you to the 'com.bea.portlet.GenericURL' class. See what it does if the URLRewriter is not used. I have implemented a great deal of security around the URLRewriter in order to ensure the state of the portlet and portal. The power of the URLRewriter is great though.. use with caution ;)&lt;br /&gt;&lt;br /&gt;&lt;em&gt;credit for an example of this goes to Deepak Natarajan&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-1302209888880242967?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1302209888880242967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1302209888880242967'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2008/02/making-bea-weblogic-portal-bookmarkable.html' title='Making the BEA Weblogic Portal bookmarkable'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-8301746741789483785</id><published>2008-01-21T07:19:00.000-08:00</published><updated>2008-01-23T05:39:59.020-08:00</updated><title type='text'>Interactive javascript environment</title><content type='html'>Before I really got into Javascript I experienced it as a necessary evil when constructing web applications.&lt;br /&gt;&lt;br /&gt;Though recently because of the added pressure of webapps being interactive, I finally took the bullet and gave object oriented javascript a go.&lt;br /&gt;&lt;br /&gt;I was amazed, after going through several tutorials on &lt;a href="http://script.aculo.us/"&gt;scriptaculous&lt;/a&gt;(based on &lt;a href="http://www.prototypejs.org/"&gt;prototype&lt;/a&gt;) and &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But to really get my groove on I needed the ultimate tools, which I found here: &lt;a href="https://www.squarefree.com/bookmarklets/webdevel.html"&gt;Web Development Bookmarklets&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;The JavaScript interactive compiler(drag to bookmarks bar), from web development page. You can click this bookmarklet to open a javascript shell for any page and it keeps its scope across new requests.. Excellent!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;here's a bookmarklet for loading prototype on the fly, made this myself :), drag to bookmark bar:&lt;br /&gt;&lt;br /&gt;&lt;a class="bml" href="javascript:var s=document.createElement('script');s.setAttribute('src', 'http://wiki.script.aculo.us/javascripts/prototype.js');document.getElementsByTagName('body')[0].appendChild(s);void(s);"&gt;load prototype&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then you may write something like this, in the shell, to print the names of all divs:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$$('div').each(function(element){print(element.name);});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Or this to make all divs blink&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$$('div').each(function(element){blink(element);});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can load any script you want, which is particularly easy in the shell with&gt; load(scriptURL). ex.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;load('http://wiki.script.aculo.us/javascripts/prototype.js');&lt;br /&gt;//to add more fun load this:&lt;br /&gt;load('http://wiki.script.aculo.us/javascripts/effects.js');&lt;br /&gt;//shake all divs&lt;br /&gt;$$('div').each(function(divElement){Effect.Shake(divElement);});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It boils down to being able to manipulate the dom at will and test Ajax very easily. Enjoy it, I do.&lt;br /&gt;&lt;br /&gt;UPDATE:&lt;br /&gt;more powerfull load&lt;br /&gt;&lt;a href="javascript:var s=document.createElement('script');s.setAttribute('src', 'http://wiki.script.aculo.us/javascripts/prototype.js');document.getElementsByTagName('body')[0].appendChild(s);s=document.createElement('script');s.setAttribute('src', 'http://wiki.script.aculo.us/javascripts/effects.js');document.getElementsByTagName('body')[0].appendChild(s);function shakeDivs(){$$('div').each(function(divElement){Effect.Shake(divElement);});}void(s);"&gt;load scripts&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;adds the function shakeDivs(); - try it&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-8301746741789483785?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8301746741789483785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8301746741789483785'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2008/01/interactive-javascript-environment.html' title='Interactive javascript environment'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-7890103619773133551</id><published>2007-12-23T13:14:00.000-08:00</published><updated>2008-12-08T19:51:58.579-08:00</updated><title type='text'>High automatic test coverage of web applications</title><content type='html'>&lt;h2&gt;Tests in web applications&lt;/h2&gt;&lt;br /&gt;Features in a web application reside in one of two locations: On the client or on the server.&lt;br /&gt;&lt;br /&gt;A unit test of the feature in the serverside codebase can cover numerous errors. If the application is written in PHP, Python or any other language compiled at runtime, the unit test can cover compiler errors. It can also cover logical errors and the error of not meeting the requirements.&lt;br /&gt;&lt;br /&gt;A functional test on the client side can also cover the integration test with browsers if the test framework can execute the tests in multiple browsers, otherwise the lowest denominator might be adequate (think IE 6).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;frameworks to use&lt;/h2&gt;&lt;br /&gt;Almost every decent language has a unit testing framework which provide a standard way of defining, executing and reporting tests. Some, like Django's, also handles the fixtures, like creating and deleting a database for each test run. This is very helpful.&lt;br /&gt;&lt;br /&gt;For functional tests in the browser engine, there are numerous frameworks. Some record a macro and repeats it, these tools are to be avoided, since they make maintenance of the tests very cumbersome, which may lead to neglect in the project. Instead of dicussing pro's and con's of various frameworks, like loadrunner, selenium etc. I'm simply going for Canoo's webtest, which aggregates HtmlUnit and several other thirdparty frameworks into one very good framework.&lt;br /&gt;&lt;br /&gt;It has the advantage that it is defined in XML, which ought to be readable by most with at least some technical interest. Think testers, new developers and maybe even project managers. It also has a very good reporting tool that is generated in static html files. I'll give an example of a webtest further down.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;implementing and maintaining the tests&lt;/h2&gt;&lt;br /&gt;When developing testdriven, it is a given that at least unit tests are being made. In most IDE's for java developers JUnit tests are we easily made and runnable (though sometimes it can be tricky to setup a full test suite running all tests). In Django you simply write a tests.py module at the root of your application*1. The management tool in Django can then invoke all tests py simple running 'manage.py tests' at the root of the project. In java you have to marshal all the tests in an ANT script or reference all test classes from 1 testsuite, leading to tedious work that puts the tests in jeopardy of being neglected.&lt;br /&gt;&lt;br /&gt;A canoo webtest is run by an ANT script. 1 script, which I always use is simply called 'allTests.xml'. Separating tests should not be the norm as with JUnit instead you should have to put some effort into excluding certain tests. The exclusions might be performance tests or some other test that is not a candidate for regression testing.&lt;br /&gt;&lt;br /&gt;In webtest you may define several macros and reuse them when you like and it has all the functionality of ANT. In the next section I give an example of a test implementation.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;testing upload and file conversion&lt;/h2&gt;&lt;br /&gt;This feature of my project involves multiple units on the serverside and only 1 clientside. Because most of the features serverside are using almost exclusively the Django framework there is no need to cover it, so I can rely on one simple unit test to test this for me, it takes a file and converts it, which is the only part I have implemented myself:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def test_convert_video(self):&lt;br /&gt;        entity = Entity(name="test video")&lt;br /&gt;        entity.save()&lt;br /&gt;        physical = Physical(content_object=entity)&lt;br /&gt;        &lt;br /&gt;        convert_to_flv(self.avifilename, self.flvfilename, physical)&lt;br /&gt;        result = os.path.exists(self.flvfilename)&lt;br /&gt;        self.assertTrue(result)&lt;br /&gt;        self.assertEqual(self.flvfilename, physical.converted_filename)&lt;br /&gt;        os.remove(self.flvfilename)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There are several more features surrounding this one, like test_grab_thumbnail_from_flv, test_invalid_cleanup_convert_video, test_get_default_thumbnail_filename and many more. This part has to have high coverage because it is a core function of the web application, but I will not go into priority vs. coverage in this entry.&lt;br /&gt;&lt;br /&gt;The unit under test in the example is the convert_to_flv. When the test executes a fake database is set up and some test doubles are made. The files used in the test are cleaned up afterwards to ensure that the state of the system is not changed as a result of the test.&lt;br /&gt;&lt;br /&gt;On the client side I have this webtest:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;target name="test"&amp;gt;&lt;br /&gt;  &amp;lt;webtest name="add different kinds of content"&amp;gt;&lt;br /&gt;   &amp;lt;login username="user" password="pass"/&amp;gt;&lt;br /&gt;   &amp;lt;addContent name="picture 1" file="../../JOOLLU_webtest/tests/picture1.png"/&amp;gt;&lt;br /&gt;   &amp;lt;addContent name="picture 2" file="../../JOOLLU_webtest/tests/babe.jpg"/&amp;gt;&lt;br /&gt;   &amp;lt;addContent name="movie 1" file="../../JOOLLU_webtest/tests/plane_lands.avi"/&amp;gt;&lt;br /&gt;   &amp;lt;addContent name="movie 2" file="../../JOOLLU_webtest/tests/preview.mov"/&amp;gt;&lt;br /&gt;   &amp;lt;addContent name="" file="../../JOOLLU_webtest/tests/preview.mov"/&amp;gt;&lt;br /&gt;   &amp;lt;addContent name="plain flv" file="../../JOOLLU_webtest/tests/3.flv"/&amp;gt;&lt;br /&gt;  &amp;lt;/webtest&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It covers the feature of uploading files. Other tests rely on this being executed which leads to test dependencies, which is totally fine. If it was a requirement not to have test dependencies I would have tests that were hard to maintain since all tests relying on this one would have to upload content themselves, putting the test at risk of being neglected.&lt;br /&gt;&lt;br /&gt;Inspect the test. The tag 'addContent' is one macro I have defined as a part of my test project, and it looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;macrodef name="addContent" description="add some content to the current user profile"&amp;gt;&lt;br /&gt; &amp;lt;attribute name="name"/&amp;gt;&lt;br /&gt; &amp;lt;attribute name="file"/&amp;gt;&lt;br /&gt; &lt;br /&gt; &amp;lt;sequential&amp;gt;&lt;br /&gt;   &amp;lt;clickLink label="add content"/&amp;gt;&lt;br /&gt;   &amp;lt;setInputField name="name" value="@{name}"/&amp;gt;&lt;br /&gt;   &amp;lt;setFileField name="file" fileName="@{file}"/&amp;gt;&lt;br /&gt;   &amp;lt;clickButton htmlId="add_button"/&amp;gt;&lt;br /&gt; &amp;lt;/sequential&amp;gt;&lt;br /&gt;&amp;lt;/macrodef&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The power of this is that I can encapsulate code that is part of implementing the tests separately and thus make the actual test easier to read and maintain. A tester with no programming background would be able to read the test and change the name of the file and the file itself.&lt;br /&gt;Among other tests that rely on this I have contentValidation.xml, invalidContentValidation.xml, verifyCorrectContent.xml and many others. The nice thing is that each subsequent test can be a direct verification of the feature or requirement. This way I can ensure that no test effort is lost because the implementation on the server has changed.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;closing remarks&lt;/h2&gt;&lt;br /&gt;Testing this way allows for full coverage of a web application. The webtest framework can handle almost all browser functionality even Ajax, ehich is due to the HtmlUit project. It has a couple of bugs, it can for example only drag and drop 1 item for each test. But these are minor issues. If my application did not contain flash as part of the implementation I reckon I could achieve 100% coverage in automatic tests. As it is now I don't have much test of requirements for performance, but I think I'm at 80% coverage in total with unit tests and webtest.&lt;br /&gt;&lt;br /&gt;To get the high automatic coverage you need to figure out on which side you have to test your feature, client or server. Then implement the unit tests for serverside and clientside tests in a framework like webtest.. and then you can implement the feature itself, knowing that when the bar in the reporting tool reaches green.. you are finished.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_tLGk_vv69BM/R27eX9coa1I/AAAAAAAAAAw/wu_YUbTzg9A/s1600-h/webtestReport.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_tLGk_vv69BM/R27eX9coa1I/AAAAAAAAAAw/wu_YUbTzg9A/s400/webtestReport.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5147295927344065362" /&gt;&lt;/a&gt;&lt;br /&gt;links&lt;br/&gt;&lt;br /&gt;&lt;a href="http://webtest.canoo.com/"&gt;canoo webtest&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://www.djangoproject.com/documentation/testing/"&gt;Django testing&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;footnotes&lt;br /&gt;*1 in Django there are multiple applications per project. An application in Django is the equivalent of a plugin in Eclipse RCP or a Web Application Resource in J2EE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-7890103619773133551?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7890103619773133551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7890103619773133551'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/12/high-automatic-test-coverage-of-web.html' title='High automatic test coverage of web applications'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_tLGk_vv69BM/R27eX9coa1I/AAAAAAAAAAw/wu_YUbTzg9A/s72-c/webtestReport.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-1278667691192654562</id><published>2007-12-04T04:10:00.000-08:00</published><updated>2007-12-12T01:19:24.430-08:00</updated><title type='text'>Development with Django and NADB</title><content type='html'>Python has always intrigued me. Occasionally I have kept revisiting the language to be marbled at the simplicity and ease of use. Until recently I did not have a reason to go further with it.&lt;br /&gt;&lt;br /&gt;I started implementing the project Joollu(coming soon &lt;a href="http://www.joollu.com"&gt;joollu&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I decided to use the &lt;a href="http://www.djangoproject.com"&gt;Django framework&lt;/a&gt;. Because a) its done in python and b) I heard it was good for content-driven websites.&lt;br /&gt;&lt;br /&gt;And boy it's intuitive, being a novice Python-programmer I felt it astonishing that I could implement my own video blog in less than approx. 10 hours. The documentation is equally astounding.&lt;br /&gt;&lt;br /&gt;The Django framework has an object relational-mapper, that handles all your db-management for you, it's a very simple way of making a model layer. You only need to configure the things that are specfic for you, making it very rapid for simple features. I thought it might be a bigger task to implement the NADB, which is only based on interfaces, but then I discovered this notion of Generics implemented in Django.&lt;br /&gt;&lt;br /&gt;Generics is used to associate a model object with any other object, without knowing anything about it's implementation. This is exactly what the NADB is all about. Instead of having a Video model class, I implemented a Physical(for storing files), viewable(for attributes like thumbnail, width/height etc.) and firstly an Entity class to represent the actual video, the only attribute here is name and id. None of these models know anything about the other on the DB-layer, instead I have a MediaManager, that can marshal a video from all its referred interfaces. Retrieving a video can be done like so:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from joollu.core.models import *&lt;br /&gt;&gt;&gt;&gt; entity = Entity.objects.get(name="myvideo")&lt;br /&gt;&gt;&gt;&gt; physical = Physical.objects.get(content_object=e)&lt;br /&gt;&gt;&gt;&gt; viewable = Viewable.objects.get(content_object=e)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or more simply with a little wrapping&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from joollu.core.managers import MediaManager&lt;br /&gt;&gt;&gt;&gt; entity = Entity.objects.get(name="myvideo")&lt;br /&gt;&gt;&gt;&gt; video = MediaManager().filter_video(name="myvideo")&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;OR&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from joollu.core.managers import MediaManager&lt;br /&gt;&gt;&gt;&gt; entity = Entity.objects.get(name="myvideo")&lt;br /&gt;&gt;&gt;&gt; video = MediaManager().get_media(entity.id)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;sadly it kinda impairs the possibilities of filtering and retrieving which is done very easily with Django. Here is an example for physical, if I want particular files:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from joollu.core.models import *&lt;br /&gt;&gt;&gt;&gt; physical_list = Physical.objects.filter(file__endswith=".png")&lt;br /&gt;&gt;&gt;&gt; physical_list&lt;br /&gt;[Physical: /Users/kennethnielsen/pythonspace/joollu/media/content/picture1.png]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Keeping the notions of things like video and images in the business layer increases flexibility. If I were to change attributes I can slap it on one of the exisitng interfaces or make a new one. Like if I want to save who and when something has been published, I can make a new model class Publishable and attach it to all content. This would be regardless of it being a video, image or other. It is up to the business layer to decide if published attributes are needed in specific cases. Comments is another example and so it goes..&lt;br /&gt;&lt;br /&gt;There are a ton of other stuff worth mentioning about Django, it all just kinda fits together in this very intuitive framework. You should read up on it, or find the tech talk about it on google tech talks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-1278667691192654562?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1278667691192654562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1278667691192654562'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/12/development-with-django-and-nadb.html' title='Development with Django and NADB'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-4893326218302338879</id><published>2007-12-04T03:16:00.000-08:00</published><updated>2007-12-04T03:19:18.629-08:00</updated><title type='text'>Outsourcing</title><content type='html'>With all the J2EE projects being outsourced to India, I guess this zeitgeist graph makes sense:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.google.com/trends?q=what+is+j2ee&amp;ctab=0&amp;hl=en"&gt;Google searches for 'What is j2ee'&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Look at the regions...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-4893326218302338879?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/4893326218302338879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/4893326218302338879'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/12/outsourcing.html' title='Outsourcing'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-8350554670346003006</id><published>2007-10-31T11:35:00.000-07:00</published><updated>2008-12-08T19:51:58.795-08:00</updated><title type='text'>No Artifacts DataBase (NADB)</title><content type='html'>&lt;h1&gt;prologue&lt;/h1&gt;&lt;br /&gt;Fueled by the Tech Talk 'Everything is miscellanous' and the book about abstract datamodelling I read lately I think it's time I give it some action...&lt;br /&gt;&lt;br /&gt;Databases today inherently have trouble adapting to changes in the business, nowadays business logic changes rapidly because of the increasing demand of adaptive business and use of IT in general.&lt;br /&gt;&lt;br /&gt;Our databases are not up to speed though. Designing a database often takes too much time and is too great a risk to mess up, so you start of by designing this, and then basing your software on it. &lt;br /&gt;&lt;br /&gt;With rapid development, it ought to be the other way around. The business dictates what needs to be in the database and often business changes. Databases should be as adaptable.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Avoid artifacts in the database&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;Data are not static! The database of a typical company contains a product, order and orderline.&lt;br /&gt;&lt;br /&gt;Looking at the product table, what constitutes a Product? That you say it's a product? - no, it has a price and can be bought and therefore is a product.&lt;br /&gt;&lt;br /&gt;If you are a paint store your product table could contain the columns: color, viscousity, manufacturer, price. If the paint store at some point wishes to extend it's catalogue to, perhaps, lamps, the table would be extended and we would have a table with the columns: color, viscousity, manufacturer, bulbtype and price.&lt;br /&gt;&lt;br /&gt;This would leave some of the rows as null values, since a lamp doesn't have viscousity(Okay bad example.. you get the idea). Maybe you would fill out viscousity anyway or do something awful like using the column for something else.&lt;br /&gt;&lt;br /&gt;In a big company I worked for I actually saw a table called 'Ship' which also contained 'Automobiles', because when automobiles became accepted as a business object some time in the past, the table happened to involve some of the same systems and had a property like 'Motor registration number'. Ofcourse, some columns in the table were along the way misused for something completely different then intended.&lt;br /&gt;Actually it wasn't really clear anymore what entites were saved there, but I think also 'Caravans' were in there.&lt;br /&gt;&lt;br /&gt;Taking the example of mixing 'Paint' and 'Lamps', lets look at their individual properties:&lt;br /&gt;&lt;li&gt;&lt;br /&gt;&lt;ul&gt;Paint&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;viscousity&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;color&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;&lt;ul&gt;Lamp&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;bulbtype&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;&lt;ul&gt;Product&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;price&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;Notice that I dont go all out here and create a 'Fluid' table for viscousity and a 'Coloured' table for the color. Also I have left out the property manufacturer, because it becomes a table 'Manufactured'. A product could be a service, which is not manufactured.&lt;br /&gt;&lt;br /&gt;So you're probably asking, what handles the relations between all these properties. Well, the product should not relate to either 'Paint' or 'Lamp' since it should not define what a product is. Instead the business handles this by instantiating entities in the database with an abstract table 'Instance'. The abstract modelling I have come up with is shown below. The relations are read as "Instance implements Type" and "Type describes Instance". It is like the modelling we know from Object-oriented languages, with the key difference that it only describes states, because we are dealing with a persistence mechanism, that should only handle state. Behaviour is described by the business(READ application on top of DB).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_tLGk_vv69BM/RyjjmNP153I/AAAAAAAAAAU/1po0ToPArR4/s1600-h/NADBModel.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_tLGk_vv69BM/RyjjmNP153I/AAAAAAAAAAU/1po0ToPArR4/s400/NADBModel.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5127598421291951986" /&gt;&lt;/a&gt;&lt;br /&gt;You might be thinking, what about metadata like logging of change of state and other valuble business info. These are very relevant issues and such a log of something should be an instance in its own right. It would have properties like date and user. Where user is a property that is a reference to an instance. So the property user would have a domain allowing it to be an instance, and the value would be a reference to an actual instance of a user. This is the way to do metadata in the model. If you would to refer to a user by a UserId you lock the table in to being a User logged event, by allowing it to be a reference to an arbitrary instance you can define it to be a User logged event in your business by checking the type of the referred instance.&lt;br /&gt;&lt;br /&gt;Note that this is not a classical Inheritance hierarchy where types can 'be of' other types, the 'Type' here is equal to an interface(as implemented in Java atleast). The creators of Java have since regretted the class inheritance as we know it today, because of the classical problem of the fragile superclass. The superclass is fragile because it's children are inherently(pun intended) dependant on the implementation of the superclass. When several children exists, the purpose of the superclass becomes more obscured as the business continues to grow and different requirements are put on the children, as the case with a table expanding horizontally. Instead, the children should implement different interfaces, dividing up the different requirements into several descriptors. The implementation of the interfaces can then be delegated. The big difference here is that state is not inherited.&lt;br /&gt;&lt;br /&gt;In the case of paint being sold, it would be an instance of paint AND price, collectively becoming what the business would describe as paint we are selling.&lt;br /&gt;&lt;br /&gt;The 'Instance' does not contain any properties itself because the 'Instance' is the sum of its relations.&lt;br /&gt;&lt;br /&gt;&lt;H1&gt;Conclusion&lt;/H1&gt;&lt;br /&gt;The relational databases today are too statically implemented, by abstracting the data, we can much more easliy build a clean database, without ripping out tables. To change the properties of an instance you only need to relate it to a different property and not do heavy, frightening, undoable 'Alter tables' etc.&lt;br /&gt;&lt;br /&gt;The model ofcourse requires some robust business logic on top, but from the recent working with Hibernate and Linq it's apparent that the traditional business logic never really worked. Contraints and validation of data has moved more towards UI and the business layer has become some dumb DAO, hopefully this approach will revitalize the layer and bring more flexibility into our backend.&lt;br /&gt;&lt;br /&gt;From here I have to prove my theory by actually implementing a system for it and describe how intuitive and flexible my backend became :)&lt;br /&gt;&lt;br /&gt;Stating that something is within a particular domain by putting the instance in a table with a certain name, does not make it so. It is as absurd as arguing whether Pluto is a moon or a planet, because it doesn't fit into either. Pluto is just an instance with a different set of properties.. "Everything is miscellanous".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-8350554670346003006?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8350554670346003006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8350554670346003006'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/10/no-artifacts-database-nadb.html' title='No Artifacts DataBase (NADB)'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_tLGk_vv69BM/RyjjmNP153I/AAAAAAAAAAU/1po0ToPArR4/s72-c/NADBModel.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-6450386449568323450</id><published>2007-10-17T03:51:00.000-07:00</published><updated>2007-10-17T04:18:09.420-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shared library'/><category scheme='http://www.blogger.com/atom/ns#' term='WebLogic'/><category scheme='http://www.blogger.com/atom/ns#' term='BEA'/><category scheme='http://www.blogger.com/atom/ns#' term='J2EE'/><category scheme='http://www.blogger.com/atom/ns#' term='BEA Workshop'/><title type='text'>BEA Weblogic tips</title><content type='html'>J2EE shared libraries are very useful, because they are merged with your web application you can reuse web resources like JSP's, special framework stuff like BEA controller's and so on.&lt;br /&gt;&lt;br /&gt;Here's how you might do it:&lt;br /&gt;&lt;h3&gt;creating a shared J2EE library&lt;/h3&gt;&lt;br /&gt;a library can be any J2EE module. Mind you I've mostly used Portal Web projects as the base for my libraries as I found that I often have web resources in my libraries&lt;br /&gt;&lt;h3&gt;defining a shared J2EE library&lt;/h3&gt; &lt;br /&gt;   1. go to the META-INF folder&lt;br /&gt;   2. open the MANIFEST.MF file&lt;br /&gt;   3. add the following three lines, filling in (example given further down):&lt;br /&gt;   4. Extension-Name:&lt;br /&gt;   5. Specification-Version:&lt;br /&gt;   6. Implementation-Version: &lt;br /&gt;&lt;br /&gt;Manifest-Version: 1.0&lt;br /&gt;Extension-Name: common-portlet-template-web&lt;br /&gt;Specification-Version: 0.1&lt;br /&gt;Implementation-Version: 0.1&lt;br /&gt;&lt;br /&gt;NOTE: the version MUST be given in order to import the library into BEA Workshop 10.0 &lt;br /&gt;&lt;h3&gt;exporting a shared J2EE library from a Web project&lt;/h3&gt;&lt;br /&gt;   1. update the versions as commented in 'defining a shared J2EE library'&lt;br /&gt;   2. right-click the project, choose 'export-&gt;WAR file' &lt;br /&gt;&lt;h3&gt;exporting a shared J2EE library from a J2EE Utility project&lt;/h3&gt;&lt;br /&gt;   1. update the versions as commented in 'defining a shared J2EE library'&lt;br /&gt;   2. right-click the project, choose 'export-&gt;Export', select JAR file, click 'Next'&lt;br /&gt;   3. choose your source folders and the META-INF folder for export, click finish &lt;br /&gt;&lt;h3&gt;importing a shared J2EE library into the BEA Workshop 10.0&lt;/h3&gt;&lt;br /&gt;   1. in window-&gt;preferences-&gt;weblogic-&gt;J2EE libraries click 'add'&lt;br /&gt;   2. click 'browse', locate your exported WAR or JAR or EAR&lt;br /&gt;   3. click 'open', click 'ok'&lt;br /&gt;   4. adding it to your project is done by expanding the 'WebLogic Deployment Descriptor' in your project&lt;br /&gt;   5. right-click -&gt; add, 'browse', locate it and click 'ok'&lt;br /&gt;&lt;h3&gt;redeploying a shared J2EE library from the Workshop&lt;/h3&gt;&lt;br /&gt;  1. in window-&gt;preferences-&gt;weblogic-&gt;J2EE libraries select the library and click 'remove'&lt;br /&gt;  2. open the server overview by double-clicking the server in the 'Servers' view&lt;br /&gt;  3. in the published module list, select the ear project and click 'Undeploy'&lt;br /&gt;  4. after the ear has finished undeploying, click the shared Library module, and click 'Undeploy'&lt;br /&gt;  5. now your are ready to deploy the library again, do this by going to window-&gt;preferences-&gt;weblogic-&gt;J2EE libraries&lt;br /&gt;  6. click 'add', then 'browse' and navigate to your shared library, select the library, click 'ok'&lt;br /&gt;  7. redploy the library by running you project on the server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-6450386449568323450?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6450386449568323450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6450386449568323450'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/10/bea-weblogic-tips.html' title='BEA Weblogic tips'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-9175539448572422004</id><published>2007-10-11T10:52:00.000-07:00</published><updated>2007-10-14T05:28:43.538-07:00</updated><title type='text'>Slow development cycles? Try something old-school.</title><content type='html'>Does this scenario sound familliar?&lt;br /&gt;&lt;br /&gt;"Quality Assurance just discovered a logical error in your presentation of the customers product.. instead of the 'Two-month no credit limit' - product, the 'Three-month no credit limit' - product emerges,&lt;br /&gt;Thinking you have the answer, you are remembering the pesky ProductNameProvider you wrote, and you guess it's a one-off error here. You seem to remember that the first two OR three records in its output are just static titels. You can't remember if it was the first two OR three, so you try incrementing your reference-index by 1. You then restart the server, deploy the application and wait patiently for a result...&lt;br /&gt;&lt;br /&gt;After replicating the error in 42 easy steps, you conclude this wasn't the right fix, now it's showing a completely wrong 'One-month no credit limit' - product.&lt;br /&gt;&lt;br /&gt;You suddenly realize that this could be an error in the actual product request or maybe the text formatting or maybe it's the caching?&lt;br /&gt;- so you try every possible path for the error and try out 3-4 different scenarios for 3-4 different paths only repeating the 42 easy steps... again... and again..."&lt;br /&gt;&lt;br /&gt;Such slow processes of bugfixing are caused by ONE thing.. lack of unit tests and proper structure. This cycle of fixing said bug, should have an obvious solution. A unit test somewhere should test that the output of a ProductNameProvider is fixed. Having an automatic testframework and supporting stubbing(maybe mocking), would allow you to test this functionality exclusively and not the entire application at once, which is too complex for any human to handle... well some applications are, especially if you like me only handle applications for shorter periods(READ 3-6 months).&lt;br /&gt;&lt;br /&gt;I have just begun working on an assignment at a large danish company. Their applications are mainly J2EE with some heavy junk in the trunk.&lt;br /&gt;My task there involves developing portlets in WebLogic 10. This is a nice platform for portals because of their intuitive CMS and flexibility in layout. BUT since its a J2EE platform, it's inherently slow, because of lots of configuration and stuff under the hood that does lots of... well.. stuff.&lt;br /&gt;&lt;br /&gt;To test an application developers tend to restart the server, because we are neurotically inclined to think that an incorrect state of the configuration involved is the main cause of our bugs, and it's understandable. Although 99% of the time, we just fucked up, we do however restart the server about 5 times before admitting it..&lt;br /&gt;&lt;br /&gt;NONE of my tasks will ever involve extending the CMS or directly interfacing with the CMS in ANY manner, so why would I need to EVER start this up when doing a simple two-page portlet.. or a complex seventy-page one for that matter.. case is.. I don't and I certainly won't. So, my advice is to avoid that the running of your code requires a running server. A common mistake is to run code, right there in your main methods.. for an example in a struts action, a beehive controller or whatever. Delegate, delegate, delegate all responsibility to classes with limited responsibility.. atleast 1 class, that doesn't require you to load a shitload of code or annotated compiles.&lt;br /&gt;&lt;br /&gt;Even a simple ProductNameProvider will eventually be executed atleast 10 times in its development stage and atleast 10 times (maybe hundreds) in its lifetime for debugging purposes.. so lets do the math.&lt;br /&gt;&lt;br /&gt;total runs = 20&lt;br /&gt;Writing the ProductNameProvider in a unit test friendly environment = 15 min&lt;br /&gt;Restarting a shitload of applications on a J2EE server  + replicating bug = 2 min (atleast)&lt;br /&gt;running a single unit test = 1 sec (atmost)&lt;br /&gt;&lt;br /&gt;60 x 15 (unittest creation) + 20 x 1 (unittest running) = 920 seconds&lt;br /&gt;60 x 2 x 20 = 2400 seconds&lt;br /&gt;&lt;br /&gt;I am not counting in maintenance of unit tests, this is parrallel to development and should not acquire extra time.. unless you implement a completely new feature..&lt;br /&gt;&lt;br /&gt;I'm not even getting in on how unit testing reduces bugs, facilitates refactoring, reduces the footprint of your code etc etc.. there are tons of documented experienced of that out there.. read it.. read it all... now!&lt;br /&gt;&lt;br /&gt;Running/testing your code, should be as easy as ALT + SHIFT + x, t&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-9175539448572422004?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/9175539448572422004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/9175539448572422004'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/10/slow-development-cycles-try-something.html' title='Slow development cycles? Try something old-school.'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-7651624962821186580</id><published>2007-08-14T03:11:00.000-07:00</published><updated>2008-12-08T19:51:58.959-08:00</updated><title type='text'>Hilbert curve</title><content type='html'>Is it nerdy when playing with a folding measure, you implement a Hilbert curve?&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_tLGk_vv69BM/RsGJ9DnKz8I/AAAAAAAAAAM/SbJyuswmdrQ/s1600-h/HilbertCurve.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_tLGk_vv69BM/RsGJ9DnKz8I/AAAAAAAAAAM/SbJyuswmdrQ/s400/HilbertCurve.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5098507935194730434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Hilbert_curve"&gt;Hilbert curve&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-7651624962821186580?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7651624962821186580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7651624962821186580'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/08/hilbert-curve.html' title='Hilbert curve'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_tLGk_vv69BM/RsGJ9DnKz8I/AAAAAAAAAAM/SbJyuswmdrQ/s72-c/HilbertCurve.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-5487305761589799637</id><published>2007-07-27T17:35:00.000-07:00</published><updated>2007-07-27T17:52:13.452-07:00</updated><title type='text'>Synger af vrede</title><content type='html'>Iliaden er en episk fortælling om grækernes invasion af Troja. Den beskriver det hele, lige fra det politiske spil, til den menige soldats kamp imod overmagten og gudernes indblanden.&lt;br /&gt;&lt;br /&gt;Oversættelsen jeg har læst, er skrevet i et moderne sprog, der til tider kan forvirre mig om jeg nu læser et moderne action eventyr, eller om det virkeligt er en fortælling der blev skrevet for over 2500 år siden. I begge tilfælde kan jeg sige at der ikke er nogen mangler på nogen fronter, der kan sætte tvivl ved at dette er den oprindelige fortælling, det oprindelige eventyr.&lt;br /&gt;&lt;br /&gt;Akilles er født af guder og dennes kendskab til egen usårlighed og oprindelse giver ham et noget aggressivt væsen, der ikke accepterer et nej. Agamemnon, overkongen, har et udestående med kong Priamos af Troja og inden man er noget ret langt ind i bogen er der så mange årsager til at angribe Troja at det snart bliver uundgåeligt at grækerne samler deres styrker.&lt;br /&gt;&lt;br /&gt;Det overrasker mig hvor let bogen springer fra drama til action til erotik og hele vejen tilbage igen ret hurtigt. Det virker fuldstændigt og man får en fornemmelse af at alt kan vende på et øjeblik. Gudernes indblanden i menneskenes affærer retfærdiggøre 100% dette skift i fortællingen og når man kommer til slutningen er man knap i tvivl om at det virkelige drama er sket blandt guderne, på trods af at en af menneskenes byer står i brand(Spoiler! :D).&lt;br /&gt;&lt;br /&gt;Odyssus og de andre tapre kriger begår konstant heroiske gerninger, men det er blot opvarmning til det store slag der kommer da Akilles beslutter sig for at drage i krig. Det sker efter at hans bedste ven(og muligvis elsker?) bliver sloget ihjel af troerne. Til sidst dør han dog, som guderne havde bestemt på forhånd og Troja falder.  Ingen guder er dog døde, enekelte er knap forurettede, men slaget blev afgjort på Olympen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-5487305761589799637?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5487305761589799637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5487305761589799637'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/07/synger-af-vrede.html' title='Synger af vrede'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-5015020717644107386</id><published>2007-07-27T17:21:00.000-07:00</published><updated>2007-07-27T17:35:22.951-07:00</updated><title type='text'>Dante's helvede</title><content type='html'>Den Guddommelige Komedie starter med lyrikken: "Midtvejs på vor rejse igennem livet, finder jeg mig selv i en mørk skov"&lt;br /&gt;&lt;br /&gt;Der refereres til at vi alle har en sti vi følger igennem livet, her vågner Dante op og ser sig omkring. Inden længe er hans rejse begyndt og den fører ham igennem helvede, purgatoriet og paradiset. I dette indlæg vil jeg kun kort nævne nogle ting jeg bed mærke i.&lt;br /&gt;&lt;br /&gt;Oversættelsen jeg har fundet indeholder oversætterenes noter, hvilket skal vise sig at være helt uvurderligt, da Dante ofte refererer til begivenheder omkring hans hjemstavn i Florence, Italien.&lt;br /&gt;&lt;br /&gt;Han tur gennem helvede starter uden for de ni kredse, hvor afdøde der ikke troede på Gud i livet tilbringer evigheden. Her findes alle former for kættere som f.eks. vikinger. Stedet kaldes for limbo.&lt;br /&gt;&lt;br /&gt;Dante bruger desuden referencer til Homer's værker, hvilket i en sammenhæng hurtigt kan tilbyde en hel historie til selv den, ellers, mest ubetydelige genstand. Denne egenskab giver fortællingen meget historie, men hvis baglandet mangler, som i mit tilfælde bliver det svært at få det hele med.&lt;br /&gt;&lt;br /&gt;Hans tur igennem helvede fortæller om alskens pinsler overgået mest hans landsmænd, men også andre af historiens store personligheder. Yderst finder man de mest larmende, støjende straffe, som de døde der bliver hugget i af djævle, mens de koges i lava. Det er som om at den der straffes mest med sin egen samvittighed betragtes som hårdere ramt. Én undtagelse er der dog Judas, der i en evighed bliver gnavet på af én af djævlens tre hoveder i den inderste kreds.&lt;br /&gt;&lt;br /&gt;Jeg glæder mig til at læse om hans rejse igennem de to sidste dødsriger, men først vil jeg have baglandet på plads. Jeg starter med Illiaden.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-5015020717644107386?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5015020717644107386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5015020717644107386'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/07/dantes-helvede.html' title='Dante&apos;s helvede'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-7384020841280522650</id><published>2007-07-27T17:08:00.000-07:00</published><updated>2007-07-27T17:35:41.191-07:00</updated><title type='text'>De episke værker</title><content type='html'>Jeg har altid haft en vis interesse i oldtiden, som jeg først udforskede i folkeskolen, hvor jeg kunne læse større historiebøger om grækenland og det gamle Persien.&lt;br /&gt;&lt;br /&gt;Interessen falmede dog, da de bøget jeg læste manglede indlevelse og overaskelser, det var som om at forfatterne kun beskrev, men aldrig selc lagde en mening eller fortolkning i deres fortælling om hvordan tingene var. &lt;br /&gt;&lt;br /&gt;Det kan man ikke bebrejde dem, hvis jeg havde indset at det var ikke den virkelige historie jeg var interesseret i, men mere hvad mennesker på den tid drømte om, hvad de forundrede sig over og hvordan de formulerede deres tanker der ikke var konkrete.&lt;br /&gt;&lt;br /&gt;Fornyligt har jeg genoptaget min betagelse af oldtiden og valgte at kaste mig over de episke værker, hvoraf verdens historier og uvirkelighed udspringer. &lt;br /&gt;&lt;br /&gt;Jeg refererer til værker som Iliaden, Odysseen, Aeneid og Den Guddommelige Komedie. Dette er listen af bøger jeg har tænkt mig at læse. Listen opstod efter at jeg havde læst første del af Den Gudommelige Komedie. Halvdelen af referencerne forstod jeg knap, jeg opdagede så at de var taget fra ovennævnte bøger, med stor reference til Virgil's Aeneide, da Virgil er Dante's 'guide' igennem de 3 dødsriger.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-7384020841280522650?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7384020841280522650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7384020841280522650'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/07/de-episke-vrker.html' title='De episke værker'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-355632077826957652</id><published>2007-07-01T13:34:00.000-07:00</published><updated>2007-07-11T05:54:35.561-07:00</updated><title type='text'>Lol@my cat</title><content type='html'>I just had to attach captions to my cat Maximus. His formal name is Baron von Maximus.. the whiskered beard adds credibility to his noble origin.&lt;br /&gt;&lt;br /&gt;So I found some snapshots from when he was kitty. I lol'ed em' up, or rather.. tried to.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.kennethhn.dk/images/LolMax1.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://www.kennethhn.dk/images/LolMax1.JPG" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.kennethhn.dk/images/LolMax2.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://www.kennethhn.dk/images/LolMax2.JPG" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-355632077826957652?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/355632077826957652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/355632077826957652'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/07/lolmy-cat.html' title='Lol@my cat'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-6516386255191151141</id><published>2007-07-01T03:32:00.000-07:00</published><updated>2007-07-01T13:52:32.837-07:00</updated><title type='text'>Lottery numbers</title><content type='html'>Hey! Last payout from the danish lottery was a staggering 10 million some euro. I'd like to get a piece of that. So what can we do to improve our chances?&lt;br /&gt;&lt;br /&gt;Well, we assume it's impossible to just pick the right numbers, so we'd had to calculate a bit on the chances of a random hit.&lt;br /&gt;&lt;br /&gt;&lt;img style="float:left; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 50px;" src="http://419.bittenus.com/FLAG/lottery.jpg" border="0" alt="" /&gt;&lt;br /&gt;In the danish lottery there are 36 different numbers, put together in 10 lists of seven to complete one row and one shot at the big bucks. That equals to 36^7 different possibilities for a row and 36^7 / 10 for a chance on a single ticket. So we'd have to buy 8 million tickets and assemble the orders to make sure there are no duplicates. That would cost 40 million euro's, not counting the hours of work filling in the tickets.&lt;br /&gt;&lt;br /&gt;1 way of increasing our chances would be to know all drawn numbers so far and work on a kind of probablity. So what I did was find a way getting all 17 years worth of numbers out of the national lottery's webpage.&lt;br /&gt;&lt;br /&gt;I went to the list of draws here: http://www.danskespil.dk/spil/lotto/indhold/resultater.php&lt;br /&gt;But I found it only shows the last 2 years worth. I examined the html and found that an attribute was set to a draw for retrieving your selection. So I put it on the request like this: ?draw=1. I now have access to the last 17 years worth of numbers, so far so good.&lt;br /&gt;&lt;br /&gt;I don't want to sit and retrieve all the numbers manually so I had to conjure a script for it. I would've used Python, but I don't know the framework well enough yet, so I ended up using Java. And ofcourse I started of by writing a test:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt; @Test&lt;br /&gt; public void TestSingleExtract() throws Exception{&lt;br /&gt;  LottoDataExtractor lde = new LottoDataExtractor();&lt;br /&gt;  String numbers888 = lde.extract(888);&lt;br /&gt;&lt;br /&gt;  assertEquals("01 - 03 - 12 - 15 - 18 - 22 - 31:08", &lt;br /&gt;    numbers888);&lt;br /&gt;&lt;br /&gt;  String numbers1 = lde.extract(1);&lt;br /&gt;&lt;br /&gt;  assertEquals("04 - 06 - 10 - 14 - 17 - 22 - 33:02 - 21",&lt;br /&gt;    numbers1);&lt;br /&gt;&lt;br /&gt;  String numbers127 = lde.extract(127);&lt;br /&gt;&lt;br /&gt;  assertEquals("02 - 04 - 10 - 13 - 15 - 16 - 26:11 - 17 - 35",&lt;br /&gt;    numbers127);&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In the above code I  test on the extraction of numbers far between because I found out the html shifted a little in characters and the first version of my LottoDataExtractor simple counted characters. So I had to smarten up the program a bit by looking at tags instead.&lt;br /&gt;&lt;br /&gt;I now have the lottery numbers from 17 years back. I will have to analyze these a bit, to hopefully find a trend or something, but I don't expect it to give me an immense advantage.&lt;br /&gt;&lt;br /&gt;get the neatly formatted numbers &lt;a href="http://www.kennethhn.dk/LottoData.txt"&gt;here&lt;/a&gt;. Note, the last line is draw 889, which is 30/06/07, every line is a new draw.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-6516386255191151141?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6516386255191151141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/6516386255191151141'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/07/lottery-numbers.html' title='Lottery numbers'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-8545091796524923721</id><published>2007-06-23T16:17:00.000-07:00</published><updated>2007-07-01T13:20:11.718-07:00</updated><title type='text'>Python - first impression</title><content type='html'>I've tried out some Python now and it is really intriguing.&lt;br /&gt;&lt;br /&gt;&lt;embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=7760178035196894549&amp;hl=en" flashvars=""&gt; &lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;One of the first thing you meet is the interactive interpreter. Now, I've come across similar things before, like a javascript shell or even, well, an OS shell.&lt;br /&gt;But in Python this is really how everything works.&lt;br /&gt;&lt;br /&gt;Atop of the very interactive programming possibilities, the language is very intuitive.&lt;br /&gt;Like this little snippet, which is how I'd like to write boolean statements, but can't in java for an example.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; x = 10&lt;br /&gt;&gt;&gt;&gt; if 0 &lt; x &lt;= 10:&lt;br /&gt;...     print "true"&lt;br /&gt;...&lt;br /&gt;true&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In Python, list is a built-in type. If I want to perform a common action like arranging two lists into a set, I do not have to bother with much complexity. As shown.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; listKey = range(5,15)&lt;br /&gt;&gt;&gt;&gt; listValue = range(10)&lt;br /&gt;&gt;&gt;&gt; zip(listKey,listValue)&lt;br /&gt;[(5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5), (11, 6), (12, 7), (13, 8), (14&lt;br /&gt;, 9)]&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Not quite clear from the code, but the printout is a list of 'tupple' all of which are built-in types.&lt;br /&gt;&lt;br /&gt;I will try to implement the 'stamp' program, for seeing how little complexity I will have to deal with. &lt;br /&gt;&lt;br /&gt;Coming up; "The Stamp/Python tutorial"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-8545091796524923721?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8545091796524923721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8545091796524923721'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/python-first-impression.html' title='Python - first impression'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-5213909195580128660</id><published>2007-06-23T03:27:00.001-07:00</published><updated>2007-07-01T13:17:39.528-07:00</updated><title type='text'>Python</title><content type='html'>I've heard good things about Python, so I decided to watch a Tech Talk about it.&lt;br /&gt;&lt;embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=1135114630744003385&amp;hl=en" flashvars=""&gt; &lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;Basically the ideas are as follows:&lt;br /&gt;1. trust the programmer&lt;br /&gt;2. don't prevent the programmer from doing what needs to be done&lt;br /&gt;3. keep the language small and simple&lt;br /&gt;4. provide only 1 way of doing a specific task&lt;br /&gt;&lt;br /&gt;So I asked myself how would I expect to use Python.&lt;br /&gt;Well instead of using my currently favoured languages Java &amp; C#, I would use the language when working with people I totally trust as good programmers with the right skills and same perspective as I. People the speak the same language.. aye.&lt;br /&gt;&lt;br /&gt;Some of the differences lie in 'Trust the programmer', if the language has to trust the programmer, then programmers must trust each other. For an example in Python you do not use 'private' annotation or other permissive annotations. This means a programmer of one class cannot totally ensure correct use of the class from another programmer.&lt;br /&gt;&lt;br /&gt;If I were to write a program that will be used in a big corporation, where there are programmers of varying skills I would probably like to encapsulate some properties, for them not to be bastardized out of scope and loosing complete track of its usage. The debugging nightmare. To some extend this is argumented against by the speaker in the Tech Talk. He states 'You don't want your code to be misued by fools, but as we all know fools can be ingenious'. What he means is that they will find some other workaround possible obscuring the usage even further.&lt;br /&gt;&lt;br /&gt;Several other benefits of Python are passing of functions, usage of templates, multiple inheritance(careful though!) and more.&lt;br /&gt;&lt;br /&gt;I will try it out and update with a little example here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-5213909195580128660?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5213909195580128660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/5213909195580128660'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/python.html' title='Python'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-1457320516738178152</id><published>2007-06-17T14:28:00.000-07:00</published><updated>2007-06-17T15:33:04.593-07:00</updated><title type='text'>Sunday java code guidelines</title><content type='html'>Avoid using static references.&lt;br /&gt;&lt;br /&gt;You are making the code dependent on implementation of a function. This does not scale well. It puts your program at risk because a reference somewhere else might require the implementation to change, without the ability to abstract it by polymorphism.&lt;br /&gt;&lt;br /&gt;You can use dependency injection to achieve this.. see Guice f.ex.&lt;br /&gt;&lt;br /&gt;Use the final keyword as much as possible.&lt;br /&gt;&lt;br /&gt;this reduces the chance that you will change the state of an object inadvertently, greatly stabilizing your code as the program evolves and become larger.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-1457320516738178152?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1457320516738178152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1457320516738178152'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/sunday-java-code-guidelines.html' title='Sunday java code guidelines'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-1847733350918512171</id><published>2007-06-17T13:34:00.000-07:00</published><updated>2007-06-17T13:37:51.708-07:00</updated><title type='text'>Enso</title><content type='html'>Wow this is a great tool.&lt;br /&gt;&lt;br /&gt;A few first impressions:&lt;br /&gt;its sleek and the interface is really nice. The opacity lets me focus on the content while navigating. This has been seen in many a flash webpage. Now I can use it anywhere.&lt;br /&gt;&lt;br /&gt;Here's the tasks it's already helping me with:&lt;br /&gt;1. navigating to the correct window&lt;br /&gt;2. opening programs&lt;br /&gt;&lt;br /&gt;Because I usually hav a lot of windows open I tend to want to close when I have too many programs open. Which is actually a burden.&lt;br /&gt;&lt;br /&gt;When I have to launch some program I don't usually use I have to go through the bookmarks in start-up, which can be somewhat frustrating.&lt;br /&gt;&lt;br /&gt;Bookmarks in the browser can also be avoided. Really nice. I'll be updating about this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-1847733350918512171?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1847733350918512171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1847733350918512171'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/enso.html' title='Enso'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-3477520469445432510</id><published>2007-06-17T13:08:00.001-07:00</published><updated>2007-06-17T13:34:32.791-07:00</updated><title type='text'>Human Computer Interface</title><content type='html'>I watched this really cool 'talk' video about a way to improve accessing functionality on your computer.&lt;br /&gt;http://video.google.com/videoplay?docid=-6856727143023456694&amp;q=tech+talk&amp;total=878&amp;start=10&amp;num=10&amp;so=0&amp;type=search&amp;plindex=6&lt;br /&gt;&lt;br /&gt;Among other things it advocates the use of services, and I now understand the power of services. Applications are restricting use of their functionality by not providing it as a service. I think in this regard that the OSGI framework used for among other things RCP, is a good approximation.&lt;br /&gt;&lt;br /&gt;Having functionality segregated into reusable parts is an idea that has existed for a long time. Think toolkits. But these are so closed in and welldefined that they don't leverage creativity.&lt;br /&gt;&lt;br /&gt;I'm going to try out the enzo humanized interface, it looks really good!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-3477520469445432510?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/3477520469445432510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/3477520469445432510'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/human-computer-interface.html' title='Human Computer Interface'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-8531585124711736903</id><published>2007-06-17T12:17:00.000-07:00</published><updated>2007-06-17T12:18:56.822-07:00</updated><title type='text'>Second Life</title><content type='html'>Just entered Second Life and watched a video about it.&lt;br /&gt;&lt;br /&gt;I must admit its sounds intriguing.&lt;br /&gt;&lt;br /&gt;I dont' want to describe it here, you can to the website and read about it. What is interesting is that soon it will be able to feed xml and html into second life.&lt;br /&gt;&lt;br /&gt;That will be amazing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-8531585124711736903?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8531585124711736903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/8531585124711736903'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/second-life.html' title='Second Life'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-1693641132046495772</id><published>2007-06-17T11:08:00.000-07:00</published><updated>2007-06-17T11:19:23.065-07:00</updated><title type='text'>Everything is Miscellanous</title><content type='html'>This is really a good philosophical 'Talk', I'll give it a brief thinking through.&lt;br /&gt;http://video.google.com/videoplay?docid=2159021324062223592&amp;q=tech+talk&amp;total=878&amp;start=0&amp;num=10&amp;so=0&amp;type=search&amp;plindex=1&lt;br /&gt;&lt;br /&gt;In contructing computer systems I have discovered that categorization itself can be a constriction, that ultimately can lead to severe problems.&lt;br /&gt;&lt;br /&gt;For an example in java you have inheritance. As a rule in new generations of development processes everything should be refactorable with the least amount of effort. How can you then defend defining some objects parents, from which all attributes are set in stone. This really emphasizes the problem of the fragile base class. I have seen this sometimes and I have'nt really made any really programmed on any system of a size where changing the baseclass would cost more than a few days of work.&lt;br /&gt;&lt;br /&gt;So the definition of anything by it's mere name or conception is fundamnetally flawed in programming. Instead it should be defined by its behaviour. This is generally enforced in the java language, so I can't help wonder why the Class inheritance construct is still is use.&lt;br /&gt;&lt;br /&gt;In short, never think you have completely defined anything in you domain. Use interfaces always. Don't extend anything! Always assume that your definition of something will change.&lt;br /&gt;&lt;br /&gt;Currently I'm tackling problems with an old system, which really was not designed for the features it now supports. One problem is that in the system a 'Product' is very well defined. So well defined, that changing its structure is basically a rewrite. The product should instead have been defined through interfaces. So a function changing a products price would use it's interface to that extent. A 'pricable' interface perhaps. Define it by behaviour!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-1693641132046495772?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1693641132046495772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1693641132046495772'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/everything-is-miscellanous.html' title='Everything is Miscellanous'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-4836504659936468607</id><published>2007-06-17T10:53:00.000-07:00</published><updated>2007-06-17T11:08:31.406-07:00</updated><title type='text'>Human Computation</title><content type='html'>In this 'Talk' Louis unveils to the viewer his actually implemented tools for what I might call 'Making work fun'. Something I recently experimented with in using elements of a game in combination with an actual workproces.&lt;br /&gt;&lt;br /&gt;In my current employment I have this task of optimizing the flow of a editing images for real estate sales.&lt;br /&gt;&lt;br /&gt;How can I make this process feel like a game? - well first you'd have to watch the 'talk' : http://video.google.com/videoplay?docid=-8246463980976635143&amp;q=tech+talk&amp;total=878&amp;start=0&amp;num=10&amp;so=0&amp;type=search&amp;plindex=0&lt;br /&gt;&lt;br /&gt;I think I would first try to apply one of the game structures.. maybe the 'synchronous' approach. Have 1 worker edit the actual image and another verify it. This is how the process actual is implemented already. A worker edits the image to fulfill some specifications. Say make the sky appear blue, remove anything unwanted in the picture and so on. Then the QA guy looks at the image and comes with corrections of sorts.&lt;br /&gt;&lt;br /&gt;So, the worker gets paid for any image that can be used. He gets rewarded for some effort, with is a common gaming element. Although, how do we make this achievement more interactive and most important FASTER.&lt;br /&gt;&lt;br /&gt;Well, one thing we could do is have the QA and the worker, player 1 &amp; 2 if you will, work synchronously. But having 2 employees for a task that can be solved by just 1 is very expensive, therefore we would rather eliminate the QA as a postion and give that task to each of the workers.&lt;br /&gt;&lt;br /&gt;By eliminating the QA per se, we can have double the output, but this puts strain on the actual control of the work, because the workers are on the same level and authority is gone. Instead we HAVE to rely on the workers not to 'cheat'. Well this is not a big problem in this case, since in the end, the customers can really easily fulfill the QA task, we just have to have a means of backtracking to the workers involved.&lt;br /&gt;&lt;br /&gt;I have to find a concrete implementation of something similar, the ESP game is too simple to use as a model, not that it's no ingenious, it HAS to be simple, because any 1 should be able to do it.&lt;br /&gt;&lt;br /&gt;Now we have requirements for the players, that are:&lt;br /&gt;1. has to have skills with photoediting&lt;br /&gt;2. can read/write english and communicate with her peer&lt;br /&gt;&lt;br /&gt;In a scenario, the two workers would work on 1 input each parralel, but the tasks would not take an eqaul amount of time to complete, so there's our first problem to be solved. How do we align the proces of each worker and make sure that QA becomes an interactive/dynamic task done by the workers in one effort.&lt;br /&gt;&lt;br /&gt;I'll have to research this some more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-4836504659936468607?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/4836504659936468607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/4836504659936468607'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/human-computation.html' title='Human Computation'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-271307601067237017</id><published>2007-06-17T10:47:00.000-07:00</published><updated>2007-06-17T10:52:39.589-07:00</updated><title type='text'>Tech Talks</title><content type='html'>I've just started discovering the rich world of online seminars, when I was introduced to google tech talks.&lt;br /&gt;&lt;br /&gt;I must admit, the guys  doing these seminars are great inspiration to me.&lt;br /&gt;&lt;br /&gt;One thing I started out with was trying to watch seminars that I could use for something. So I started seeing some seminars on test-first development for an example. Quickly though, I ran out of interesting seminars on that topic, but still wanted more.&lt;br /&gt;&lt;br /&gt;My couriousity was tingled by the great seminar people who know how to motivate for any lecture. Though a possiblity for gaining knowledge on topics out of my interest, I tried out some new ones.&lt;br /&gt;&lt;br /&gt;In this blog I will probably comment on most of them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-271307601067237017?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/271307601067237017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/271307601067237017'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/tech-talks.html' title='Tech Talks'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-1301754415680689641</id><published>2007-06-10T09:38:00.000-07:00</published><updated>2007-06-10T09:51:49.274-07:00</updated><title type='text'>Getters and Setters are evil</title><content type='html'>In my current employment I am a part of a project that is founding a new system, root up.&lt;br /&gt;&lt;br /&gt;What I keep seeing myself doing is adding getters and setters allover my code, but only inside well-defined components. I ask you though, how well-defined must a component be to consider encupsulation for properties?&lt;br /&gt;&lt;br /&gt;I have come to the conclusion, that each and every class is a component in it's own right.. so I should drop getters and setter entirely. Ouch, some refactoring to be done.. hmm how to accomplish it, I wonder. &lt;br /&gt;&lt;br /&gt;Consider the case of Logging in. The usual way to go about this is to have a user obect compared to some stored data, and then doing some behind the scenes bullshit of connecting to this, and refering to that. What you essentially end up with is a function, like this&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;boolean login(String username, String password);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and it is placed somewhere on your mother of an application runnable. &lt;br /&gt;&lt;code&gt;&lt;br /&gt;Application{&lt;br /&gt;void run(){&lt;br /&gt;splashScreen();&lt;br /&gt;//Hack info from the User and crack away&lt;br /&gt;loginInfo = gatherLoginInfo();&lt;br /&gt;login(loginInfo.name, loginInfo.pass);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That doesn't seem at all like OO programming though. One would expect this method to be a method of a User. Then the application would ask the user to log themselves in. So instead the implementation would be&lt;br /&gt;&lt;code&gt;&lt;br /&gt;User{&lt;br /&gt;void login();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Application{&lt;br /&gt;void run(){&lt;br /&gt;splashScreen();&lt;br /&gt;//we have a new User here&lt;br /&gt;User user = new User();&lt;br /&gt;//user, could you please log ourself in?&lt;br /&gt;user.login();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Seems more accurately OO-like... right?&lt;br /&gt;&lt;br /&gt;Some good reading:&lt;br /&gt;http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?page=5&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-1301754415680689641?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1301754415680689641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/1301754415680689641'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/getters-and-setters-are-evil.html' title='Getters and Setters are evil'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-2104086343894631369</id><published>2007-06-10T08:31:00.001-07:00</published><updated>2007-07-01T03:52:31.945-07:00</updated><title type='text'>Comments can be bad and clutter code</title><content type='html'>Oh my heart bleeds for I have been deceived by my foulishness.&lt;br /&gt;What I usually tell people when I can't understand their code is:&lt;br /&gt;"Write lots of comments"&lt;br /&gt;&lt;br /&gt;Which would solve the problem at hand, but maybe the problem is not my lack of insight, I should be able to comprehend most code, shouldn't I?&lt;br /&gt;&lt;br /&gt;So instead lets take an example of some code I might misunderstand, an rewrite it so I could. I don't understand this(code segment randomly picked from http://www.google.com/codesearch):&lt;br /&gt;You can look through it, or just press 'Page Down', to skip to the point.. it's hilaroius, trust me ^^&lt;br /&gt;&lt;code&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        final int NUM_MSGS;&lt;br /&gt;        Connection connection = null;&lt;br /&gt;&lt;br /&gt;        if ((args.length &lt; 1) || (args.length &gt; 2)) {&lt;br /&gt;            System.err.println(&lt;br /&gt;                    "Program takes one or two arguments: "&lt;br /&gt;                    + "&lt;dest_type&gt; [&lt;number-of-messages&gt;]");&lt;br /&gt;            System.exit(1);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        String destType = args[0];&lt;br /&gt;        System.out.println("Destination type is " + destType);&lt;br /&gt;&lt;br /&gt;        if (!(destType.equals("queue") || destType.equals("topic"))) {&lt;br /&gt;            System.err.println("Argument must be \"queue\" or " + "\"topic\"");&lt;br /&gt;            System.exit(1);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (args.length == 2) {&lt;br /&gt;            NUM_MSGS = (new Integer(args[1])).intValue();&lt;br /&gt;        } else {&lt;br /&gt;            NUM_MSGS = 1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        Destination dest = null;&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            if (destType.equals("queue")) {&lt;br /&gt;                dest = (Destination) queue;&lt;br /&gt;            } else {&lt;br /&gt;                dest = (Destination) topic;&lt;br /&gt;            }&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            System.err.println("Error setting destination: " + e.toString());&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;            System.exit(1);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            connection = connectionFactory.createConnection();&lt;br /&gt;&lt;br /&gt;            Session session = connection.createSession(&lt;br /&gt;                        false,&lt;br /&gt;                        Session.AUTO_ACKNOWLEDGE);&lt;br /&gt;&lt;br /&gt;            MessageProducer producer = session.createProducer(dest);&lt;br /&gt;            TextMessage message = session.createTextMessage();&lt;br /&gt;&lt;br /&gt;            for (int i = 0; i &lt; NUM_MSGS; i++) {&lt;br /&gt;                message.setText("This is message " + (i + 1));&lt;br /&gt;                System.out.println("Sending message: " + message.getText());&lt;br /&gt;                producer.send(message);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            producer.send(session.createMessage());&lt;br /&gt;        } catch (JMSException e) {&lt;br /&gt;            System.err.println("Exception occurred: " + e.toString());&lt;br /&gt;        } finally {&lt;br /&gt;            if (connection != null) {&lt;br /&gt;                try {&lt;br /&gt;                    connection.close();&lt;br /&gt;                } catch (JMSException e) {&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;- okay I'm dumb I know, I know. In this case, the code was actually substanially commented, I just left out the comments, because then I would have a case. I found that several lines of comment could be left out, just be refining the code a bit. So I put away the code in little neat sections, and then embraced a form of procedural glamour. I came up with this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        handleInputArguments(args);&lt;br /&gt;        connect();&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now I understand what it does.. hooray for me! And no time wasted for comments.&lt;br /&gt;&lt;br /&gt;Spin-off'ed&lt;br /&gt;Trailing through the Internet with the great firefox add-on StumbleUpon.. I actually stumbled upon something extremely interesting:&lt;br /&gt;&lt;br /&gt;http://www.chrylers.com/top-ten-of-programming-advice-to-not-follow&lt;br /&gt;&lt;br /&gt;It is nice to hear what seasoned programmers think of advice given to me by various colleagues.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-2104086343894631369?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/2104086343894631369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/2104086343894631369'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/bleeding-heart-it-hurts-to-be-wrong.html' title='Comments can be bad and clutter code'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-2053795347223056113</id><published>2007-06-10T08:23:00.000-07:00</published><updated>2007-06-10T08:30:32.673-07:00</updated><title type='text'>Titles in software development</title><content type='html'>Why are so many titles popping up everywhere?&lt;br /&gt;Programmer is just not good enough for us anymore.&lt;br /&gt;How about 'Software Developer'?&lt;br /&gt;'Software Architect'&lt;br /&gt;'Software Engineer'&lt;br /&gt;&lt;br /&gt;or real bogus titles that sound more like a job description:&lt;br /&gt;'Software Qualtiy Assurance Team Leader'&lt;br /&gt;&lt;br /&gt;I'll settle for software developer for now, although my current job entails a great list of different tasks. Lets try it out:&lt;br /&gt;'Quality Assuring Software Architect Designer' - boo!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-2053795347223056113?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/2053795347223056113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/2053795347223056113'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/06/titles-in-software-development.html' title='Titles in software development'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-4160057893788245484</id><published>2007-05-25T00:34:00.001-07:00</published><updated>2007-05-25T00:42:40.182-07:00</updated><title type='text'>COBOL is not useless</title><content type='html'>I have a kind of friendship with COBOL.&lt;br /&gt;It was the first language I used to program professionally.&lt;br /&gt;&lt;br /&gt;Here's an article about COBOL's future. &lt;br /&gt;http://www.ddj.com/dept/architect/199602005&lt;br /&gt;&lt;br /&gt;So now a JAVA IDE is bringing COBOL into the new Millenium.. laugh, point. &lt;br /&gt;&lt;br /&gt;Thank God I went the JAVA route.&lt;br /&gt;&lt;br /&gt;COBOL arrowed!&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.hrwiki.org/images/0/02/arrowed.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px;" src="http://www.hrwiki.org/images/0/02/arrowed.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-4160057893788245484?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/4160057893788245484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/4160057893788245484'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/05/i-have-kind-of-friendship-with-cobol.html' title='COBOL is not useless'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-7022392959474709504</id><published>2007-05-24T08:12:00.001-07:00</published><updated>2007-05-24T08:25:12.129-07:00</updated><title type='text'>Sailing mishap!</title><content type='html'>This really got me thinking of how much time some people put into really wierd stuff.&lt;br /&gt;&lt;br /&gt;I love homestar++ though.&lt;br /&gt;&lt;a href="http://www.hrwiki.org/index.php/Arrow'd_Guy"&gt;Wierd link&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.hrwiki.org/images/3/37/sailingmishap.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px;" src="http://www.hrwiki.org/images/3/37/sailingmishap.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-7022392959474709504?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7022392959474709504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/7022392959474709504'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/05/sailing-mishap-this-really-got-me.html' title='Sailing mishap!'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry><entry><id>tag:blogger.com,1999:blog-2643514316523207801.post-604399837832733242</id><published>2007-05-24T08:05:00.000-07:00</published><updated>2007-05-24T08:11:02.079-07:00</updated><title type='text'>My Blog is up</title><content type='html'>I'm trying out blogging.&lt;br /&gt;&lt;br /&gt;Now..&lt;br /&gt;&lt;br /&gt;Many people blog because of pure exhibitionism.&lt;br /&gt;&lt;br /&gt;Not me...&lt;br /&gt;&lt;br /&gt;No..&lt;br /&gt;&lt;br /&gt;I Blog for the pure sake of getting all those tainted thoughts out of my head.&lt;br /&gt;&lt;br /&gt;Now a list of wicked sites I sometimes give a look:&lt;br /&gt;&lt;br /&gt;http://xkcd.com/&lt;br /&gt;http://www.dilbert.com/&lt;br /&gt;http://slashdot.org/&lt;br /&gt;http://newz.dk/&lt;br /&gt;http://politikken.dk/&lt;br /&gt;&lt;br /&gt;..ah... that feels better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2643514316523207801-604399837832733242?l=kennethhn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/604399837832733242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2643514316523207801/posts/default/604399837832733242'/><link rel='alternate' type='text/html' href='http://kennethhn.blogspot.com/2007/05/my-blog-is-up.html' title='My Blog is up'/><author><name>Kenneth Holm Nielsen</name><uri>http://www.blogger.com/profile/11033084110698373428</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp0.blogger.com/_tLGk_vv69BM/R2o9jNcoazI/AAAAAAAAAAg/gQAd0pp8790/S220/KHN.JPG'/></author></entry></feed>
