<?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'><id>tag:blogger.com,1999:blog-3215278939917454572</id><updated>2009-11-07T20:02:28.538Z</updated><title type='text'>Crafting Software</title><subtitle type='html'>Musings on software and software development</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default?start-index=26&amp;max-results=25'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-8148959210023124837</id><published>2009-04-30T09:21:00.001+01:00</published><updated>2009-04-30T09:21:26.750+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><title type='text'>Programming in the small</title><content type='html'>A personal quick reminder of these excellent blog entries.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ivan.truemesh.com/archives/cat_programming_in_the_small.html"&gt;http://ivan.truemesh.com/archives/cat_programming_in_the_small.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-8148959210023124837?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/8148959210023124837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=8148959210023124837' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/8148959210023124837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/8148959210023124837'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2009/04/programming-in-small.html' title='Programming in the small'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-1560534078901913679</id><published>2009-04-03T15:00:00.001+01:00</published><updated>2009-04-03T15:04:00.709+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='coaching'/><category scheme='http://www.blogger.com/atom/ns#' term='TED'/><category scheme='http://www.blogger.com/atom/ns#' term='talks'/><title type='text'>John Wooden: Coaching for people, not points</title><content type='html'>I came across this really interesting talk by John Wooden about his coaching career and the measurement of success. Although the focus is basketball it is remarkable how many thoughts have relevance to other walks and works of life.&lt;br /&gt;&lt;br /&gt;"Success is peace of mind attained only through self-satisfaction in knowing that you made the effort to do the best of which you are capable."&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ted.com/talks/view/id/498"&gt;View the talk on TED&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="334" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt; &lt;param name="flashvars" value="vu=http://video.ted.com/talks/embed/JohnWooden_2001-embed_high.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/JohnWooden-2001.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=498" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="334" height="326" allowFullScreen="true" flashvars="vu=http://video.ted.com/talks/embed/JohnWooden_2001-embed_high.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/JohnWooden-2001.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=498"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-1560534078901913679?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/1560534078901913679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=1560534078901913679' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/1560534078901913679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/1560534078901913679'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2009/04/john-wooden-coaching-for-people-not.html' title='John Wooden: Coaching for people, not points'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-8534296040726086717</id><published>2009-03-01T16:07:00.001Z</published><updated>2009-03-01T16:07:21.789Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='deployment'/><category scheme='http://www.blogger.com/atom/ns#' term='modeling'/><title type='text'>Think about change</title><content type='html'>Over the last few years I have noticed a growing trend in software developers to constrain their thinking to static models.&lt;br /&gt;&lt;br /&gt;Static thinking is a great way of envisioning a system and we have many tools to support modelling systems in this way - class, deployment, network diagrams all fall into this category. But all these models are about a single state of the system - either historical, real (current) or imaginary (future).&lt;br /&gt;&lt;br /&gt;However many projects involve more difficult thinking. Typically these difficulties involve moving from one state to another and the most complex of these is migrating from one version of a system to another.&lt;br /&gt;&lt;br /&gt;It is at this point that I struggle to find an effective model that captures this transition. How do we model and capture the upgrade of a database, application and infrastructure requirements. And further these transitions occur at different times and are typically not instantaneous which can mean that the service is not available. How do we model this sequence of events so we can understand the effect of our evolving software design on the rolling out the new software.&lt;br /&gt;&lt;br /&gt;Quite often these rollout plans are written down (impact analysis, rollout network models, sequence diagrams, flow charts) and held in the minds of the project team. But these models are not easily tested. Organisations with a significant investment in their live environment often struggle to replicate that environment to allow the model and plans to be tested before hitting the production environment.&lt;br /&gt;&lt;br /&gt;I think finding an effective tool to model and execute software updates will be one of the key challenges for this decade - as it has for the last two.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-8534296040726086717?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/8534296040726086717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=8534296040726086717' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/8534296040726086717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/8534296040726086717'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2009/03/think-about-change.html' title='Think about change'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-3922588005353387550</id><published>2009-02-19T18:32:00.001Z</published><updated>2009-02-19T18:32:43.110Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='macs'/><category scheme='http://www.blogger.com/atom/ns#' term='train'/><category scheme='http://www.blogger.com/atom/ns#' term='trains'/><title type='text'>Macs on trains</title><content type='html'>On my current project I am travelling more that usual, mostly by train between London and the North West. The journey time is pretty manageable and the service (so far this year) has been pretty good leaving and arriving on time.&lt;br /&gt;&lt;br /&gt;The thing that struck me today was the number of Macs in coach B. Of the 10 computers in used well over half were macs. I remember some time ago that macs were a rarity for train travellers but no more. Ok most of them were MacBooks and not the shiny new aluminium ones but the trend was quite startling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-3922588005353387550?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/3922588005353387550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=3922588005353387550' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/3922588005353387550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/3922588005353387550'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2009/02/macs-on-trains.html' title='Macs on trains'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-1522332039180246622</id><published>2009-01-18T11:53:00.001Z</published><updated>2009-01-18T13:46:39.256Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>The Designful Company</title><content type='html'>&lt;h1&gt;&lt;a href="http://www.amazon.com/Designful-Company-culture-nonstop-innovation/dp/0321580060/ref=pd_bbs_sr_1?ie=UTF8&amp;s=books&amp;qid=1232279338&amp;sr=8-1"&gt;The Designful Company&lt;/a&gt; by Marty Neumeier&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I have to confess that when it comes to reading books related to work I have a short attention span. For technical books I tend to skim through the text and examples until I get a 'feel' for the content. Most of the time this is sufficient, after all if I need more details I can come back to the book and dig into them. The most important thing for me is to have a high level view of the technology and to know were to get more information.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So when it came to reading 'The Designful Company' by Marty Neumeier I kicked off with my usual skimming approach - but quickly found myself changing tack and putting my novel hat on - reading every word!&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Quoting &lt;a href="http://en.wikipedia.org/wiki/Thomas_Aquinas"&gt;Thomas Aquinas&lt;/a&gt; "Ad pulcritudenum tria requiruntur integritas, consonantia, claritas". Design requires 3 qualities&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;integrity&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;harmoney&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;radiance&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Reading this I was struck by the thought that these are the things I am looking for in the architecture and design of a software system.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In fact many of the ideas presented by the book (intended for a wide variety of companies) resonate with current agile software development trends.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The bit on agility (p21) brought a smile to my face&lt;/p&gt;&lt;br /&gt;&lt;p&gt;'The Designful Company' is an easy thought provoking read. Presenting a strong argument for corporate adoption of design to drive growth in the 21 century.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Given my reading habbits it also helps that the book is small and layed out well with large print.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;It may be just me but I am seeing a convergence in thinking across many different disciplines - or maybe software development practitioners are still learning from others.&lt;/p&gt;				   &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-1522332039180246622?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/1522332039180246622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=1522332039180246622' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/1522332039180246622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/1522332039180246622'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2009/01/designful-company.html' title='The Designful Company'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-9034590887972866382</id><published>2008-12-21T17:29:00.001Z</published><updated>2008-12-21T17:29:27.943Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='scmrss'/><category scheme='http://www.blogger.com/atom/ns#' term='Ramaze'/><title type='text'>SCMRSS reaches Alpha 1 release</title><content type='html'>&lt;p&gt;&lt;a href="http://rubyforge.org/projects/scmrss/"&gt;SCMRSS&lt;/a&gt; is a simple web application that turns Source Control events into an RSS feed. Written in Ruby using the &lt;a href="http://ramaze.net/"&gt;Ramaze&lt;/a&gt; web framework. Once configured the web server polls the source control repository for changes and when found delivers those changes as a simple RSS feed.&lt;/&gt;&lt;br /&gt;&lt;p&gt;This is the first alpha release so I would welcome any and all feedback either here or as issues at RubyForge&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-9034590887972866382?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/9034590887972866382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=9034590887972866382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/9034590887972866382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/9034590887972866382'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/12/scmrss-reaches-alpha-1-release.html' title='SCMRSS reaches Alpha 1 release'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-4155182094959872349</id><published>2008-12-20T13:33:00.001Z</published><updated>2009-01-06T20:40:46.604Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Paring'/><category scheme='http://www.blogger.com/atom/ns#' term='Distributed'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><category scheme='http://www.blogger.com/atom/ns#' term='Remote'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Remote Pair Programming setup</title><content type='html'> &lt;br /&gt;&lt;p&gt;For a few years now I have been looking for a solution that allows two or more people to share an editing session who are not sat side by side.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Each OS has its own preferred way of sharing a desctop/workspace for collaborative working. Some work cross platform (e.g. VNC) and some work via the internet (e.g. &lt;a href="http://www.gotomypc.com"&gt;GoToMyPC&lt;/a&gt;). But for much of my daily work I want a nice fast way of sharing the code that I am working on with a collegue. One or both of us are likely to be behind firewalls, proxies and all sort of important security that makes collaborative remote working so very very hard.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;On my current project we are using Eclipse as our development IDE, a local IRC server for ad-hoc team communication and point to point instant messaging. Backed up by Skype for person to person video and occasionaly more traditional email and phone for that personal touch.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;All in all this is working fiine and I have to admit I had forgotten how useful IRC is in comparison to IM when it comes to team working. Just having everyone aware of the conversations that are taking place can be a real boon.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I had some spare time last evening and decided to see if I could track down a viable solution to the remote pair programming. Confining my requirements to either complete desktop sharing or Eclipse based paring helped quite a bit because the other added complication is that we have a mixed OS development team including Windows, Linux and Mac OS X. The number of OSs is likely to settle down to just two but at the moment we have quite a mixed bag - which is actually quite refreshing.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So back to the remote pairing issue. I quickly realised that sharing the editing session is likely to be sufficient to our needs and that other tools could provide text, voice and video quite effectively and did not need to be replaced.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;My first efforts involved the Eclipse Communication Framework (ECF). I had played about with much earlier versions and concluded that it was a little fussy and difficult to work with for my tastes but decided to give it a go. Working behind a proxy with limited ports meant setting up and running a local server.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I can see a lot of promise in the ECF but it just feels far to heavy weight. I might have made some errors but I could not get it to work, connecting to the server seemed ok (although there were a lot of stack backtraces on startup - now I really cant understand why people still dump these things to the console with the idea that users - even developer users will have a hope of understanding what went wrong. With 3 pages of small text flying past it is just too easy to spot the line that tells you what when wrong. So after an unhappy hour or two trying to get two instances of Eclipse to open a shared editing setting I gave up and went back to searching for alternative.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;After a little bit more searching I cam up with &lt;a href="http://xpairtise.sourceforge.net/"&gt;XPairtise&lt;/a&gt; and open source project that seemed to do exactly what I now wanted - share an editing session. Unusually for an open source project the documentation is pretty good although it was early in the morning and I almost missed that there are two downloads; one for the eclipse plugin and the other for the server.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The setup which I eventually came up with involved the XParitise server and Eclipse running natively on my Mac and a Ubuntu VM mimicing a remote pair. The server is nice and quiet just reporting that it is up and running - a refreshing change. After setting up accounts through the Eclipse preferences pane (a little quirky on the UI the first time around) but it was heart warming to receive the 'account created' message.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Getting the shared editing session to work took some time. First when creating a shared workspace all the files from the project are shipped up to the server. When joining the shared workspace again the project files are brought down so take heed of the backup dialog or work in a different Eclipse workspace for shared working.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;It took at least 2 Eclipse restarts to get the shared editing to work and there is a note on the XPairtise site about using the eclipse -clean option to refresh all the plug-ins&lt;/p&gt;&lt;br /&gt;&lt;p&gt;But after this initial setup headache I have a configuration that will allow remote pair programming.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Result!!&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I have just rerun the setup within a distributed team (2 locations) and after a bit of a lag in synchronising the project contents everything worked fine with 3 concurrent users (Driver, Navigator and Spectator).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-4155182094959872349?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/4155182094959872349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=4155182094959872349' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4155182094959872349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4155182094959872349'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/12/remote-pair-programming-setup.html' title='Remote Pair Programming setup'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-1844376525838592576</id><published>2008-10-05T11:41:00.001+01:00</published><updated>2008-10-05T11:41:59.214+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Font'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Shell'/><title type='text'>Setting Windows Shell Font</title><content type='html'>I keep loosing track of this little tidbit&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont" /v 00 /d Consolas&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;logoff&lt;br /&gt;&lt;br /&gt;The full article can be found here &lt;a href="http://blogs.msdn.com/ie/archive/2008/04/22/give-your-eyes-a-treat.aspx"&gt;http://blogs.msdn.com/ie/archive/2008/04/22/give-your-eyes-a-treat.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-1844376525838592576?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/1844376525838592576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=1844376525838592576' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/1844376525838592576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/1844376525838592576'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/10/setting-windows-shell-font.html' title='Setting Windows Shell Font'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-7825757357083950517</id><published>2008-10-04T21:40:00.001+01:00</published><updated>2008-10-04T21:40:21.895+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><title type='text'>Timewarp</title><content type='html'>About a month ago I was asked to look at an application that has been&lt;br /&gt;under active development and support for quite some time. Written in C&lt;br /&gt;and C++ (my old stomping grounds for 20 years) I was really looking&lt;br /&gt;forward to getting stuck into the code.&lt;br /&gt;&lt;br /&gt;What I was not expecting was the lack of tool support. I sort of knew&lt;br /&gt;that refatoring tools, tests and code coverage would be a bit of a&lt;br /&gt;challenge but I did not think that it would be the challenge that it&lt;br /&gt;turned out to be.&lt;br /&gt;&lt;br /&gt;I have gotten used to being able to download tools, try them out and&lt;br /&gt;if appropriate buy them and add them to my toolbox. Ideally there&lt;br /&gt;would be an open source tool I could use instead to get the job&lt;br /&gt;done. Moving back into the C++ world also took me back in time to an&lt;br /&gt;era where evaluation downloads are not available. Instead I would have&lt;br /&gt;to register my interest and someone would be in touch to talk to me&lt;br /&gt;about the wonders of their application and to perhaps run the&lt;br /&gt;application over my source code. Well first I tend to get about a bit&lt;br /&gt;and at the time I was out of my home country and well away from the&lt;br /&gt;tool vendors timezone. I was up against the clock in putting together&lt;br /&gt;some initial findings and recommendations, and lastly it was not my&lt;br /&gt;source code so I could not offer it up to someone else to go poking&lt;br /&gt;around in anyway.&lt;br /&gt;&lt;br /&gt;Strike one - keep on searching for someone with a little less of a&lt;br /&gt;protectionist attitude.&lt;br /&gt;&lt;br /&gt;Unfortunately this seemed to become a theme. Other suppliers had no&lt;br /&gt;evaluations and insisted on money up front and land shipping. In a way&lt;br /&gt;they may have been doing me a favour, if the software is so complex&lt;br /&gt;that it needs to be demonstrated and the licencing enforcement so&lt;br /&gt;strong that it becomes difficult to use (I have been hit before by&lt;br /&gt;node locked liceses to machines that decide to die) then maybe this&lt;br /&gt;approach has just saved me a lot of heart ache and pain.&lt;br /&gt;&lt;br /&gt;On the plus side there are tools out in 'open source' land that can&lt;br /&gt;help and there *are* a few companies that have moved with the times&lt;br /&gt;and provide a more open licensing scheme. When I have time I will list&lt;br /&gt;out the toolkit that I came up with.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-7825757357083950517?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/7825757357083950517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=7825757357083950517' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/7825757357083950517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/7825757357083950517'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/10/timewarp.html' title='Timewarp'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-5871249317910112856</id><published>2008-09-25T16:55:00.001+01:00</published><updated>2008-09-25T16:55:52.238+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Virtualisation'/><title type='text'>Too many VMs</title><content type='html'>As part of my work life I regularly need to run windows development software on my Mac. Typically for a client engagement. This is a really convenient setup. I can take a snapshot before I start work on something new and then at the end roll back to the original state ready to work on the next project.&lt;br /&gt;&lt;br /&gt;One of the downsides I have encountered recently is the need to keep all these machines up to date with patches and other software updates that seem to be part of everyday life.&lt;br /&gt;&lt;br /&gt;Don't get me wrong I think its great that we have this steady stream of updates to make things better but when you start multiplying this up for the VMs I have on my machine the effort to keep them up to date starts to be become a bit of a pain.&lt;br /&gt;&lt;br /&gt;I think it is time to start rationalising to a smaller number - just so I can keep them up to date.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-5871249317910112856?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/5871249317910112856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=5871249317910112856' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/5871249317910112856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/5871249317910112856'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/09/too-many-vms.html' title='Too many VMs'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-4950490896094030424</id><published>2008-08-04T01:41:00.001+01:00</published><updated>2008-08-04T01:41:23.819+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='flying'/><category scheme='http://www.blogger.com/atom/ns#' term='bose'/><title type='text'>Quietly Does it</title><content type='html'>&lt;table&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;img src="http://www.bose.com/images/home_entertainment/products/p_qc3_m.jpg"/&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      I have had my eye on a pair of &lt;a href="http://www.bose.com"&gt;Bose&lt;/a&gt; headphones for some time but never managed to justify the cost. And to be honest I am not sure that I ever will. Except that they are truly fabulous and on my first tip with them on a plane left me feeling relaxed and comfortable. The noise onboard a plane seem to raise my tension levels but removing that noise really helped me enjoy the flight.&lt;br/&gt;&lt;br /&gt;I was told when I bought them that the batteries were fully charged and would each last 10 hours. I can only testify to 8 on one battery with almost continuous use.&lt;br/&gt;&lt;br /&gt;I will confess that I have tried a number of different headphones, both in and out of ear, with and without noise cancelling but nothing comes close to the peace that these phones bring with them.&lt;br/&gt;So maybe I have justified them :)&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-4950490896094030424?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/4950490896094030424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=4950490896094030424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4950490896094030424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4950490896094030424'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/08/quietly-does-it.html' title='Quietly Does it'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-4254199539283526124</id><published>2008-08-04T01:16:00.001+01:00</published><updated>2008-08-04T01:16:35.221+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conference'/><category scheme='http://www.blogger.com/atom/ns#' term='agile2008'/><title type='text'>Toronto - Sunday</title><content type='html'>&lt;br /&gt;&lt;table&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;img src="http://lh5.ggpht.com/wookie870/SJZJVZE17HI/AAAAAAAAAEM/W8gVq-Myx4s/DSC00146.JPG?imgmax=800" alt="DSC00146.JPG" border="0" width="116" height="155" /&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;p&gt;&lt;br /&gt;        Today is my first day in Toronto, preparing for &lt;a href="http://www.agile2008.org"&gt;Agile 2008&lt;/a&gt;. After a surprisingly smooth and peaceful crossing from the UK, and an even smoother journey to downtown Toronto I find myself preparing some slides for my short experience report 'TeamPace - Keeping the build times down' on Thursday.&lt;br /&gt;      &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;I am staying at the Hilton just across the street from the conference at the Sheraton Centre for an early morning start.&lt;/p&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-4254199539283526124?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/4254199539283526124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=4254199539283526124' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4254199539283526124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4254199539283526124'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/08/toronto-sunday.html' title='Toronto - Sunday'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-3568404576031494648</id><published>2008-08-01T21:35:00.001+01:00</published><updated>2008-08-01T21:35:51.844+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wordpress'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Code is Poetry</title><content type='html'>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"&gt;&lt;br /&gt;&lt;html&gt;&lt;br /&gt;  &lt;head&gt;&lt;br /&gt;    &lt;title&gt;&lt;/title&gt;&lt;br /&gt;  &lt;/head&gt;&lt;br /&gt;  &lt;body&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      On a recent visit to the &lt;a href="http://wordpress.org"&gt;Wordpress&lt;/a&gt; sight I was struck by their tag line "Code is poetry". I have been searching for some time for a phrase that would sum up how I feel about well crafted code; code that is easy to understand, read and generally feels 'just right'.&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;I am not completely convinced that code is poetry - but it comes pretty close.&lt;/p&gt;&lt;br /&gt;  &lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-3568404576031494648?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/3568404576031494648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=3568404576031494648' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/3568404576031494648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/3568404576031494648'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/08/code-is-poetry.html' title='Code is Poetry'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-2608070638222169828</id><published>2008-08-01T21:19:00.001+01:00</published><updated>2008-08-01T21:22:59.329+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conference'/><category scheme='http://www.blogger.com/atom/ns#' term='agile2008'/><title type='text'>Agile2008</title><content type='html'>&lt;p&gt;Next week I will be in Toronto for Agile 2008 to present a short experience report, catch up with friends and immerse myself in all things Agile :)&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.agile2008.org"&gt;&lt;br /&gt;&lt;img src="http://www.agile2008.org/images/Agile2008button.gif" border="0"/&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-2608070638222169828?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/2608070638222169828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=2608070638222169828' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/2608070638222169828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/2608070638222169828'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/08/agile2008.html' title='Agile2008'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-6628766495574758479</id><published>2008-05-19T15:49:00.001+01:00</published><updated>2008-05-19T16:02:29.439+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='train'/><category scheme='http://www.blogger.com/atom/ns#' term='wireless'/><title type='text'>Trains and WiFi</title><content type='html'>I am just returning from Leeds to London by train with power and free Wireless internet. Ok it is not the fastest link but works well - even for blogging &lt;img src="http://i32.photobucket.com/albums/d19/xdomains/smilies/small/1.gif" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-6628766495574758479?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/6628766495574758479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=6628766495574758479' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/6628766495574758479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/6628766495574758479'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/05/trains-and-wifi.html' title='Trains and WiFi'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-6914666290594806450</id><published>2008-05-13T13:26:00.001+01:00</published><updated>2008-05-13T13:26:46.506+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monitor'/><title type='text'>Keyboard touching</title><content type='html'>&lt;p&gt;I am definitely with &lt;a href="http://www.codinghorror.com/blog"&gt;Jeff Atwood&lt;/a&gt; on when it is appropriate to &lt;a href="http://www.codinghorror.com/blog/archives/001115.html"&gt;touch monitors&lt;/a&gt; - NEVER.&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-6914666290594806450?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/6914666290594806450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=6914666290594806450' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/6914666290594806450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/6914666290594806450'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/05/keyboard-touching.html' title='Keyboard touching'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-3377018980529808536</id><published>2008-04-29T11:26:00.001+01:00</published><updated>2008-04-29T11:26:41.186+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Further perf ruby, python C++ file reading</title><content type='html'>&lt;p&gt;Following on from the log files article I decided to do some basic perf checks of ruby and python reading text files. The results were a little disapointing - performance was roughly the same, so my ruby log file reading optimisation was complete rot.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Further experimentation required.&lt;/p&gt; &lt;br /&gt;&lt;table border="1"&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;by Lorenzo Bettini&lt;br /&gt;http://www.lorenzobettini.it&lt;br /&gt;http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;ARGV&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt; param &lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  cc &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  File&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;param&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'r'&lt;/font&gt;&lt;font color="#990000"&gt;).&lt;/font&gt;each_line &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;line&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    cc &lt;font color="#990000"&gt;+=&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"File has #{cc} characters"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Processing /Users/gcb/work/log-analysis/cc.rb ... created /Users/gcb/work/log-analysis/cc.rb.html&lt;br /&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      Realy simple script - and probably the most obvious - add up the length of all the lines in the file.&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;pre&gt;&lt;br /&gt;      File has 1673435763 characters&lt;br /&gt;&lt;br /&gt;real	0m56.035s&lt;br /&gt;user	0m33.873s&lt;br /&gt;sys	0m3.609s&lt;br /&gt;&lt;br /&gt;      &lt;/pre&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;by Lorenzo Bettini&lt;br /&gt;http://www.lorenzobettini.it&lt;br /&gt;http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;ARGV&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt; param &lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  cc &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  i &lt;font color="#990000"&gt;=&lt;/font&gt; File&lt;font color="#990000"&gt;.&lt;/font&gt;open&lt;font color="#990000"&gt;(&lt;/font&gt;param&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    line &lt;font color="#990000"&gt;=&lt;/font&gt; i&lt;font color="#990000"&gt;.&lt;/font&gt;readline&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;until&lt;/font&gt;&lt;/b&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;?&lt;/font&gt;&lt;br /&gt;      cc &lt;font color="#990000"&gt;+=&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;br /&gt;      line &lt;font color="#990000"&gt;=&lt;/font&gt; i&lt;font color="#990000"&gt;.&lt;/font&gt;readline&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; Exception &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; e&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;ensure&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    i&lt;font color="#990000"&gt;.&lt;/font&gt;close&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"File has #{cc} characters"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Processing /Users/gcb/work/log-analysis/cc1.rb ... created /Users/gcb/work/log-analysis/cc1.rb.html&lt;br /&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      Based on previoud observations this one uses the realine method from the IO library but did not affect the performance.&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;pre&gt;&lt;br /&gt;      File has 1673435763 characters&lt;br /&gt;&lt;br /&gt;real	0m55.569s&lt;br /&gt;user	0m35.506s&lt;br /&gt;sys	0m3.451s&lt;br /&gt;&lt;br /&gt;      &lt;/pre&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;by Lorenzo Bettini&lt;br /&gt;http://www.lorenzobettini.it&lt;br /&gt;http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;import&lt;/font&gt;&lt;/b&gt; sys&lt;br /&gt;cc &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;source &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;open&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;sys&lt;font color="#990000"&gt;.&lt;/font&gt;argv&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; line &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; source&lt;font color="#990000"&gt;:&lt;/font&gt;&lt;br /&gt;  cc &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;len&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;line&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;source&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;close&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;print&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'file has '&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; cc&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;' characters'&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Processing /Users/gcb/work/log-analysis/cc.py ... created /Users/gcb/work/log-analysis/cc.py.html&lt;br /&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      As a benchmark a simple python scrpt - again adding up all the line lengths in the file.&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;pre&gt;&lt;br /&gt;      file has  1673435763  characters&lt;br /&gt;&lt;br /&gt;real	0m53.462s&lt;br /&gt;user	0m23.147s&lt;br /&gt;sys	0m3.781s&lt;br /&gt;&lt;br /&gt;      &lt;/pre&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;by Lorenzo Bettini&lt;br /&gt;http://www.lorenzobettini.it&lt;br /&gt;http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;stdio.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;int&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;main&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;int&lt;/font&gt; argc&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#009900"&gt;char&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt; argv&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;  &lt;font color="#009900"&gt;int&lt;/font&gt; count &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;  FILE&lt;font color="#990000"&gt;*&lt;/font&gt; f &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;fopen&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;argv&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;while&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;getc&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;f&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;    count&lt;font color="#990000"&gt;++;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#000000"&gt;printf&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"File has %d characters&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; count&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Processing /Users/gcb/work/log-analysis/cc.cpp ... created /Users/gcb/work/log-analysis/cc.cpp.html&lt;br /&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      Baseline written in C++&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;pre&gt;&lt;br /&gt;      File has 1673392372 characters&lt;br /&gt;&lt;br /&gt;real	0m53.167s&lt;br /&gt;user	0m31.473s&lt;br /&gt;sys	0m3.094s&lt;br /&gt;&lt;br /&gt;      &lt;/pre&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;by Lorenzo Bettini&lt;br /&gt;http://www.lorenzobettini.it&lt;br /&gt;http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;stdio.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;int&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;main&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;int&lt;/font&gt; argc&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#009900"&gt;char&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt; argv&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;  &lt;font color="#009900"&gt;int&lt;/font&gt; count &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;  FILE&lt;font color="#990000"&gt;*&lt;/font&gt; f &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;fopen&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;argv&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;font color="#009900"&gt;char&lt;/font&gt; buffer&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;512&lt;/font&gt;&lt;font color="#990000"&gt;];&lt;/font&gt;&lt;br /&gt;  &lt;font color="#009900"&gt;int&lt;/font&gt; read &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;fread&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;buffer&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;512&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; f&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;while&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;read &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;    count &lt;font color="#990000"&gt;+=&lt;/font&gt; read&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;    read &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;fread&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;buffer&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;512&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; f&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;  &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#000000"&gt;printf&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"File has %d characters&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; count&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Processing /Users/gcb/work/log-analysis/cc1.cpp ... created /Users/gcb/work/log-analysis/cc1.cpp.html&lt;br /&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      A (poor) buffered version of the baseline written in C++&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;    &lt;td&gt;&lt;br /&gt;      &lt;pre&gt;&lt;br /&gt;      File has 1673435763 characters&lt;br /&gt;&lt;br /&gt;real	0m52.425s&lt;br /&gt;user	0m1.526s&lt;br /&gt;sys	0m4.473s&lt;br /&gt;&lt;br /&gt;      &lt;/pre&gt;&lt;br /&gt;    &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-3377018980529808536?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/3377018980529808536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=3377018980529808536' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/3377018980529808536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/3377018980529808536'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/04/further-perf-ruby-python-c-file-reading.html' title='Further perf ruby, python C++ file reading'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-4632624092668864034</id><published>2008-04-27T19:18:00.001+01:00</published><updated>2008-04-27T19:35:58.431+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='blogging'/><title type='text'>Blogging Code</title><content type='html'>&lt;html&gt;&lt;br /&gt;&lt;head&gt;&lt;br /&gt;&lt;title&gt;Blogging Code&lt;/title&gt;&lt;br /&gt;&lt;/head&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;p&gt;I quite often find myself blogging about program source code, that code is typically stored in source files which I then run through a pretty printer (something like source-highlight). Combining everyting together means some copy and pasting - not the most repeatable process and quite often the code and article evolve together - so I end up copying and pasting quite often.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So I came up with mashup. A small ruby program to process html files and handle include directives to do inline include of another file and for this purpose the results of a process&lt;p&gt;&lt;br /&gt;&lt;p&gt;The following source was include with&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;x:include value="source-highlight -o STDOUT ~/projects/mashup/mashup"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;By running:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mashup blogging-code.html &amp;gt; blogging-code-publish.html&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;by Lorenzo Bettini&lt;br /&gt;http://www.lorenzobettini.it&lt;br /&gt;http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#!/usr/bin/ruby&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;ARGV&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;arg&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  contents &lt;font color="#990000"&gt;=&lt;/font&gt; File&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;arg&lt;font color="#990000"&gt;).&lt;/font&gt;read&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  contents&lt;font color="#990000"&gt;.&lt;/font&gt;sub!&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF6600"&gt;/&amp;lt;s:include\s+value="([^"]*)"\s*\/&amp;gt;/&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;match&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    replacement &lt;font color="#990000"&gt;=&lt;/font&gt; File&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;$1&lt;/font&gt;&lt;font color="#990000"&gt;).&lt;/font&gt;read&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;    replacement&lt;font color="#990000"&gt;.&lt;/font&gt;gsub!&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF6600"&gt;/.*&amp;lt;body&amp;gt;/&lt;/font&gt;m&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;''&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    replacement&lt;font color="#990000"&gt;.&lt;/font&gt;gsub!&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF6600"&gt;/&amp;lt;\/body&amp;gt;.*/&lt;/font&gt;m&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;''&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    replacement&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  contents&lt;font color="#990000"&gt;.&lt;/font&gt;sub!&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF6600"&gt;/&amp;lt;x:include\s+value="([^"]*)"\s*\/&amp;gt;/&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;match&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    replacement &lt;font color="#990000"&gt;=&lt;/font&gt; `&lt;font color="#990000"&gt;#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#009900"&gt;$1&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;`&lt;br /&gt;    replacement&lt;font color="#990000"&gt;.&lt;/font&gt;gsub!&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF6600"&gt;/.*&amp;lt;body&amp;gt;/&lt;/font&gt;m&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;''&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    replacement&lt;font color="#990000"&gt;.&lt;/font&gt;gsub!&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF6600"&gt;/&amp;lt;\/body&amp;gt;.*/&lt;/font&gt;m&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;''&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    replacement&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  puts contents&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-4632624092668864034?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/4632624092668864034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=4632624092668864034' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4632624092668864034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/4632624092668864034'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/04/blogging-code.html' title='Blogging Code'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-6724376469884382325</id><published>2008-04-14T10:34:00.001+01:00</published><updated>2008-04-14T10:34:06.974+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='log files'/><title type='text'>Log files</title><content type='html'>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"&gt;&lt;br /&gt;&lt;html&gt;&lt;br /&gt;  &lt;head&gt;&lt;br /&gt;    &lt;title&gt;&lt;br /&gt;      Log Files&lt;br /&gt;    &lt;/title&gt;&lt;br /&gt;  &lt;/head&gt;&lt;br /&gt;  &lt;body&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      Log files are one of those must have things for any web application. It is just so hard to predict all of the possible ways users are going to interact with the site that gathering post live information about application behaviour is essential. It does however produce quite a lot of data.&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      On my current project, after a fairly significant release we resolved to check the log files to see if there were any unexpected incidents that required fixes or web content changes. The log files ran to several gigabytes containing entries not only from the application but also from a very noisy subsystems. After a quick look it became evident that it would not be effective just scanning through the log files but that some cleaning or automated analysis was required.&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      On the initial scan we noticed that there were some Java stack traces being repeated so something that could capture the distinct stack traces and then list the errors that caused them. In this was we could look at the general issues based on priority (number of occurrences).&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      Our first effort was to write a fairly simple ruby script using a hash map keyed on the text of the stack trace. Each map entry contained an array of error lines from the log files. We kicked the script off after testing with a small log file and went to lunch.&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      When we came back the script was still running. Sometime later it ran out of memory - not ideal.&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      It has been sometime since I have written any C++. Most of my work these days involves Java, C# and a little bit of Ruby for work around the codebase so it took a little while for my C++ brain to kick in. A colleague also took up the challenge by writing a solution in Python.&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      The results were quite startling with the Python script performing almost as well as the C++ at around 500,000 lines per second.&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;    by Lorenzo Bettini&lt;br /&gt;    http://www.lorenzobettini.it&lt;br /&gt;    http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;    &lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;fstream&amp;gt;&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;sstream&amp;gt;&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;string&amp;gt;&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;map&amp;gt;&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;#include&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;&amp;lt;vector&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;using&lt;/font&gt;&lt;/b&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;namespace&lt;/font&gt;&lt;/b&gt; std&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;progress&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;       &lt;font color="#009900"&gt;int&lt;/font&gt; count&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;public&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;:&lt;/font&gt;&lt;br /&gt;       &lt;b&gt;&lt;font color="#000000"&gt;progress&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;          count &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;       &lt;font color="#009900"&gt;void&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;ping&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;          cerr &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#CC33CC"&gt;\b&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"|/-&lt;/font&gt;&lt;font color="#CC33CC"&gt;\\&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;count&lt;font color="#990000"&gt;++%&lt;/font&gt;&lt;font color="#993399"&gt;4&lt;/font&gt;&lt;font color="#990000"&gt;];&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;typedef&lt;/font&gt;&lt;/b&gt; map&lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt;string&lt;font color="#990000"&gt;,&lt;/font&gt; vector&lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt;string&lt;font color="#990000"&gt;&amp;gt;*&amp;gt;&lt;/font&gt; error_map&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;void&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;print_errors&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;error_map&lt;font color="#990000"&gt;&amp;amp;&lt;/font&gt; errors&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;       &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;error_map&lt;font color="#990000"&gt;::&lt;/font&gt;iterator iter &lt;font color="#990000"&gt;=&lt;/font&gt; errors&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;();&lt;/font&gt; iter &lt;font color="#990000"&gt;!=&lt;/font&gt; errors&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;();&lt;/font&gt; iter&lt;font color="#990000"&gt;++&lt;/font&gt; &lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;          vector&lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt;string&lt;font color="#990000"&gt;&amp;gt;*&lt;/font&gt; reports &lt;font color="#990000"&gt;=&lt;/font&gt; iter&lt;font color="#990000"&gt;-&amp;gt;&lt;/font&gt;second&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;          &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;reports&lt;font color="#990000"&gt;-&amp;gt;&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;size&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;          &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;             string first &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;(*&lt;/font&gt;reports&lt;font color="#990000"&gt;)[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;];&lt;/font&gt;&lt;br /&gt;             cout &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n\n\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;             cout &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; reports&lt;font color="#990000"&gt;-&amp;gt;&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;size&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;" instances of&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;             cout &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"FIRST instance "&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; first &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;             &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;reports&lt;font color="#990000"&gt;-&amp;gt;&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;size&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;                cout &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"LAST  instance "&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#990000"&gt;(*&lt;/font&gt;reports&lt;font color="#990000"&gt;)[&lt;/font&gt;reports&lt;font color="#990000"&gt;-&amp;gt;&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;size&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;             cout &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; iter&lt;font color="#990000"&gt;-&amp;gt;&lt;/font&gt;first&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;          &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;void&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;process_file&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;char&lt;/font&gt;&lt;font color="#990000"&gt;*&lt;/font&gt; filename&lt;font color="#990000"&gt;,&lt;/font&gt; error_map&lt;font color="#990000"&gt;&amp;amp;&lt;/font&gt; errors&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;       progress p&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;       cerr &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#CC33CC"&gt;\b&lt;/font&gt;&lt;font color="#FF0000"&gt;Processing "&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; filename &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;       ifstream &lt;b&gt;&lt;font color="#000000"&gt;file&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;       string line&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;       string pending_error&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;       string pending_stack&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;       &lt;font color="#009900"&gt;int&lt;/font&gt; stack_lines &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;       &lt;font color="#009900"&gt;int&lt;/font&gt; line_number &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;       &lt;font color="#009900"&gt;bool&lt;/font&gt; skipping &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;false&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;       &lt;b&gt;&lt;font color="#0000FF"&gt;while&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;getline&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;file&lt;font color="#990000"&gt;,&lt;/font&gt; line&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;          &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;line_number &lt;font color="#990000"&gt;%&lt;/font&gt; &lt;font color="#993399"&gt;100000&lt;/font&gt; &lt;font color="#990000"&gt;==&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;             p&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;ping&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;();&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;          line_number&lt;font color="#990000"&gt;++;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;          &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;line&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;==&lt;/font&gt; &lt;font color="#FF0000"&gt;'#'&lt;/font&gt; &lt;font color="#990000"&gt;||&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;find&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Notice"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; string&lt;font color="#990000"&gt;::&lt;/font&gt;npos&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;          &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;             &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;pending_stack&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;size&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;             &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;                &lt;i&gt;&lt;font color="#9A1900"&gt;// Process stack trace&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;errors&lt;font color="#990000"&gt;[&lt;/font&gt;pending_stack&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;==&lt;/font&gt; NULL&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;                   errors&lt;font color="#990000"&gt;[&lt;/font&gt;pending_stack&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;new&lt;/font&gt;&lt;/b&gt; vector&lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt;string&lt;font color="#990000"&gt;&amp;gt;();&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;                errors&lt;font color="#990000"&gt;[&lt;/font&gt;pending_stack&lt;font color="#990000"&gt;]-&amp;gt;&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;insert&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;errors&lt;font color="#990000"&gt;[&lt;/font&gt;pending_stack&lt;font color="#990000"&gt;]-&amp;gt;&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(),&lt;/font&gt; pending_error&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;                pending_stack&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;clear&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;();&lt;/font&gt;&lt;br /&gt;             &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;             &lt;i&gt;&lt;font color="#9A1900"&gt;// Ignore lines from systems we are not interested in&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;             skipping &lt;font color="#990000"&gt;=&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;find&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"ignore-one"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; string&lt;font color="#990000"&gt;::&lt;/font&gt;npos&lt;br /&gt;             &lt;font color="#990000"&gt;||&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;find&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"ignore-two"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; string&lt;font color="#990000"&gt;::&lt;/font&gt;npos&lt;br /&gt;             &lt;font color="#990000"&gt;||&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;find&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"ignore-three"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; string&lt;font color="#990000"&gt;::&lt;/font&gt;npos&lt;br /&gt;             &lt;font color="#990000"&gt;||&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;find&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"INFO"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; string&lt;font color="#990000"&gt;::&lt;/font&gt;npos&lt;br /&gt;             &lt;font color="#990000"&gt;||&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;find&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"WARN"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; string&lt;font color="#990000"&gt;::&lt;/font&gt;npos&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;             &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(!&lt;/font&gt;skipping&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;                pending_error &lt;font color="#990000"&gt;=&lt;/font&gt; line&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;             stack_lines &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;          &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;          &lt;b&gt;&lt;font color="#0000FF"&gt;else&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;          &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;             &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(!&lt;/font&gt;skipping &lt;font color="#990000"&gt;&amp;amp;&amp;amp;&lt;/font&gt; stack_lines &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; &lt;font color="#993399"&gt;20&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;             &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;                pending_stack&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;append&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;line&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;                pending_stack&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;append&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#CC33CC"&gt;\n&lt;/font&gt;&lt;font color="#FF0000"&gt;"&lt;/font&gt;&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;             &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;             stack_lines&lt;font color="#990000"&gt;++;&lt;/font&gt;&lt;br /&gt;          &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;int&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;main &lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;int&lt;/font&gt; argc&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#009900"&gt;char&lt;/font&gt; &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;const&lt;/font&gt;&lt;/b&gt; argv&lt;font color="#990000"&gt;[])&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;       error_map&lt;font color="#990000"&gt;*&lt;/font&gt; e &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;new&lt;/font&gt;&lt;/b&gt; map&lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt;string&lt;font color="#990000"&gt;,&lt;/font&gt; vector&lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt;string&lt;font color="#990000"&gt;&amp;gt;*&amp;gt;();&lt;/font&gt;&lt;br /&gt;       error_map&lt;font color="#990000"&gt;&amp;amp;&lt;/font&gt; errors &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;*&lt;/font&gt;e&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;       &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;int&lt;/font&gt; i &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt; i &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; argc&lt;font color="#990000"&gt;;&lt;/font&gt; i&lt;font color="#990000"&gt;++)&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;br /&gt;          &lt;b&gt;&lt;font color="#000000"&gt;process_file&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;argv&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;],&lt;/font&gt; errors&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;       &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;       &lt;b&gt;&lt;font color="#000000"&gt;print_errors&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;errors&lt;font color="#990000"&gt;);&lt;/font&gt;  &lt;br /&gt;       &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;;&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    &lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      The Python solution is a little shorter however&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;!-- Generator: GNU source-highlight 2.9&lt;br /&gt;    by Lorenzo Bettini&lt;br /&gt;    http://www.lorenzobettini.it&lt;br /&gt;    http://www.gnu.org/software/src-highlite --&gt;&lt;br /&gt;    &lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;import&lt;/font&gt;&lt;/b&gt; os&lt;font color="#990000"&gt;,&lt;/font&gt; sys&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; &lt;b&gt;&lt;font color="#000000"&gt;is_valid&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;item&lt;font color="#990000"&gt;):&lt;/font&gt;&lt;br /&gt;        &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; token &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;'ignore-one'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'ignore-two'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'ignore-tree'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'NavigationLink instance'&lt;/font&gt;&lt;font color="#990000"&gt;]:&lt;/font&gt;&lt;br /&gt;            &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; token &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; item&lt;font color="#990000"&gt;:&lt;/font&gt;&lt;br /&gt;                &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;False&lt;/font&gt;&lt;br /&gt;        &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;True&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    directory &lt;font color="#990000"&gt;=&lt;/font&gt; sys&lt;font color="#990000"&gt;.&lt;/font&gt;argv&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    errors &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;{}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; filename &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; os&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;listdir&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;directory&lt;font color="#990000"&gt;):&lt;/font&gt;&lt;br /&gt;        last&lt;font color="#009900"&gt;_&lt;/font&gt;error &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;''&lt;/font&gt;&lt;br /&gt;        last&lt;font color="#009900"&gt;_&lt;/font&gt;stack &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;''&lt;/font&gt;&lt;br /&gt;        stack&lt;font color="#009900"&gt;_&lt;/font&gt;count &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;        file&lt;font color="#009900"&gt;_&lt;/font&gt;path &lt;font color="#990000"&gt;=&lt;/font&gt; os&lt;font color="#990000"&gt;.&lt;/font&gt;path&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;join&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;directory&lt;font color="#990000"&gt;,&lt;/font&gt; filename&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;        &lt;b&gt;&lt;font color="#0000FF"&gt;print&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'Processing'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; file&lt;font color="#009900"&gt;_&lt;/font&gt;path&lt;br /&gt;&lt;br /&gt;        source &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;open&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;file&lt;font color="#009900"&gt;_&lt;/font&gt;path&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; line &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; source&lt;font color="#990000"&gt;:&lt;/font&gt;&lt;br /&gt;            &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;startswith&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'#'&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;or&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'&amp;lt;Notice&amp;gt;'&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; line&lt;font color="#990000"&gt;):&lt;/font&gt;&lt;br /&gt;                &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;b&gt;&lt;font color="#000000"&gt;is_valid&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;last&lt;font color="#009900"&gt;_&lt;/font&gt;stack&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;and&lt;/font&gt;&lt;/b&gt; &lt;b&gt;&lt;font color="#000000"&gt;is_valid&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;last&lt;font color="#009900"&gt;_&lt;/font&gt;error&lt;font color="#990000"&gt;):&lt;/font&gt;&lt;br /&gt;                    errors&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;setdefault&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;last&lt;font color="#009900"&gt;_&lt;/font&gt;stack&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;[]).&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;append&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;last&lt;font color="#009900"&gt;_&lt;/font&gt;error&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;                last&lt;font color="#009900"&gt;_&lt;/font&gt;error &lt;font color="#990000"&gt;=&lt;/font&gt; line&lt;br /&gt;                last&lt;font color="#009900"&gt;_&lt;/font&gt;stack &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;''&lt;/font&gt;&lt;br /&gt;                stack&lt;font color="#009900"&gt;_&lt;/font&gt;count &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;            &lt;b&gt;&lt;font color="#0000FF"&gt;else&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;:&lt;/font&gt;&lt;br /&gt;                stack&lt;font color="#009900"&gt;_&lt;/font&gt;count &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;br /&gt;                &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; stack&lt;font color="#009900"&gt;_&lt;/font&gt;count &lt;font color="#990000"&gt;&amp;lt;=&lt;/font&gt; &lt;font color="#993399"&gt;20&lt;/font&gt;&lt;font color="#990000"&gt;:&lt;/font&gt;&lt;br /&gt;                    last&lt;font color="#009900"&gt;_&lt;/font&gt;stack &lt;font color="#990000"&gt;+=&lt;/font&gt; line&lt;br /&gt;&lt;br /&gt;        source&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;close&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;print&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'Writing report to grok.txt'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    out&lt;font color="#009900"&gt;_&lt;/font&gt;file &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#000000"&gt;open&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'grok.txt'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'w'&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; stack&lt;font color="#990000"&gt;,&lt;/font&gt; error&lt;font color="#009900"&gt;_&lt;/font&gt;list &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; errors&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;iteritems&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;():&lt;/font&gt;&lt;br /&gt;        &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;len&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;error&lt;font color="#009900"&gt;_&lt;/font&gt;list&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;and&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;len&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;stack&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;strip&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;())&lt;/font&gt; &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;):&lt;/font&gt;&lt;br /&gt;            out&lt;font color="#009900"&gt;_&lt;/font&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;write&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'Found %d items like: %s'&lt;/font&gt; &lt;font color="#990000"&gt;%&lt;/font&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;len&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;error&lt;font color="#009900"&gt;_&lt;/font&gt;list&lt;font color="#990000"&gt;),&lt;/font&gt; error&lt;font color="#009900"&gt;_&lt;/font&gt;list&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]))&lt;/font&gt;&lt;br /&gt;            out&lt;font color="#009900"&gt;_&lt;/font&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;write&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;stack&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;            out&lt;font color="#009900"&gt;_&lt;/font&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;write&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'\n\n'&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;            out&lt;font color="#009900"&gt;_&lt;/font&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;write&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'---------------------------------------------------------'&lt;/font&gt;&lt;font color="#990000"&gt;);&lt;/font&gt;&lt;br /&gt;            out&lt;font color="#009900"&gt;_&lt;/font&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;write&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'\n\n'&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    out&lt;font color="#009900"&gt;_&lt;/font&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#000000"&gt;close&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;()&lt;/font&gt;&lt;br /&gt;    &lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Both solutions limited the number of lines in the stack trace used for the key to 20. This was fine for non-reflected methods.&lt;/p&gt;&lt;br /&gt;  &lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-6724376469884382325?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/6724376469884382325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=6724376469884382325' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/6724376469884382325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/6724376469884382325'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/04/log-files.html' title='Log files'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-313835238374462203</id><published>2008-03-01T16:21:00.001Z</published><updated>2008-03-01T16:21:57.322Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Syntax'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Ruby initialise array and add in one step</title><content type='html'>I keep forgetting the syntax of this so perhaps this will help.&lt;br /&gt;&lt;br /&gt;Given a hash where each value is an array of values this gives a nice concise way of setting things up (even if it is a little obscure).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;map = {}&lt;br /&gt;&lt;br /&gt;(map[:key] ||= []) &lt;&lt; :value&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above results in a hash containing a key value of :key with an array containing :value&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-313835238374462203?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/313835238374462203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=313835238374462203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/313835238374462203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/313835238374462203'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/03/ruby-initialise-array-and-add-in-one.html' title='Ruby initialise array and add in one step'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-2066564228026336499</id><published>2008-02-26T11:34:00.001Z</published><updated>2008-02-26T11:34:15.943Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='cruisecontrol.rb'/><title type='text'>cruisecontrolrb and java</title><content type='html'>I have been meaning to setup a &lt;a href="cruisecontrolrb.thoughtworks.com"&gt;cruisecontrol.rb&lt;/a&gt; instance for some time. Cruisecontrol.rb is a implementation of continuous integration build server in ruby. It is a simple self-contained download with a really quick initial setup time.&lt;br /&gt;&lt;br /&gt;I have just started an open source java project for stack trance analysis called &lt;a href="https://sourceforge.net/projects/why/"&gt;why&lt;/a&gt; and wanted a build server so thought I would give cruisecontrol.rb a go.&lt;br /&gt;&lt;br /&gt;The download took a couple of minutes. Adding the project (cruise add why --url https://why.svn.sourceforge.net/svnroot/why) took a few more minutes to do the initial checkout.&lt;br /&gt;&lt;br /&gt;Started cruise (cruise start) in a command shell and...build failed.&lt;br /&gt;&lt;br /&gt;I needed to provide a custom build command in the cruise_config.rb file in projects/why:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Project.configure do |project|&lt;br /&gt;  &lt;br /&gt;  project.build_command = 'b'&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I already had a shell script called b to run ant and build the project. Result - build failed.&lt;br /&gt;&lt;br /&gt;Small scratching of head and a chmod +x b later and - build passed.&lt;br /&gt;&lt;br /&gt;From start to finish about 20 mins - most of which was download and initial checkout.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-2066564228026336499?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/2066564228026336499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=2066564228026336499' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/2066564228026336499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/2066564228026336499'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/02/cruisecontrolrb-and-java.html' title='cruisecontrolrb and java'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-269753133619905925</id><published>2008-02-03T22:23:00.002Z</published><updated>2008-02-14T15:10:32.878Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='build'/><category scheme='http://www.blogger.com/atom/ns#' term='ant'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Tagging builds in subversion</title><content type='html'>&lt;p&gt;At the end of every build I like to add a tag to the project source repository. Although the build log contains the revision of the source being built and so the build can be re-created, I like the fact that all the information about the source and the build is in one place.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;target name="tag-build" description="tag the build revision" &amp;gt;&lt;br /&gt;     &amp;lt;svn javahl="false"&amp;gt;&lt;br /&gt;        &amp;lt;status path="${basedir}" revisionProperty="svn.revision" /&amp;gt;&lt;br /&gt;     &amp;lt;/svn&amp;gt;&lt;br /&gt;     &amp;lt;echo message="Tagging revision ${svn.revision} as tag ${label}" /&amp;gt;&lt;br /&gt;     &amp;lt;svn username="cruise" password="cruise" javahl="false"&amp;gt;&lt;br /&gt;        &amp;lt;copy srcURL="http://repository/path/trunk" revision="${svn.revision}" destUrl="http://repository/path/tags/${label}" message="Cruise: Tagging build ${label}" /&amp;gt;&lt;br /&gt;     &amp;lt;/svn&amp;gt;&lt;br /&gt;  &amp;lt;/target&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-269753133619905925?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/269753133619905925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=269753133619905925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/269753133619905925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/269753133619905925'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/02/tagging-builds-in-subversion.html' title='Tagging builds in subversion'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-5029366979402237931</id><published>2008-01-21T11:52:00.001Z</published><updated>2008-01-21T11:52:59.467Z</updated><title type='text'>Project Kit List</title><content type='html'>&lt;body&gt;&lt;br /&gt; &lt;br /&gt;  &lt;p&gt;Essential Items for Software Projects&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;A recent conversation with a friend made me realise that things I have come to think of as standard practice for software projects are by no means universal and that problems I had thought not relevant any more are still around and causing mayhem and chaos around the world for developers and managers alike.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;So casting caution to the wind I thought I would draw up a list of things I find essential for a project&lt;/p&gt;&lt;br /&gt;  &lt;ul&gt;&lt;br /&gt;    &lt;li&gt;Version Control&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;Build server&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;Wiki&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;Issue tracking&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;Text Editor&lt;/li&gt;&lt;br /&gt;  &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;  &lt;h2&gt;Version Control&lt;/h2&gt;&lt;br /&gt;  &lt;p&gt;It is difficult to understand why any project would not use version control. No decision is final and no PC or server is 100% reliable. At the very least Version Control is a personal safety net for things that can and will go wrong&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;I like to take things a little further and make version control the only way of communicating changes to the build server. This ensures that &lt;strong&gt;everything&lt;/strong&gt; is under version control and that those little change that I will remember forever (hah) are written down somewhere. (The build server config should also be in version control - makes rebuilding a build server a breeze)&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;My personal preference is &lt;a href="http://subversion.tigres.org"&gt;subversion&lt;/a&gt;. Its free, open source and works really really well. If you are using a version control system with features not supported by subversion think seriously about whether you really need those features. No really many version control systems have features that promote complex processes and practices that can really get in the way.&lt;/p&gt; &lt;br /&gt;&lt;br /&gt;  &lt;h2&gt;Build Server&lt;/h2&gt;&lt;br /&gt;  &lt;p&gt;My second essential item of kit is a build server. Hardware is now so inexpensive that there are few excuses for not having one of these&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;If you cannot afford an additional server or it is not practical (on the road with a laptop perhaps) then invest in a good virtualisation system had run your build server on the same hardware or one of the dev boxes if you are working in a team.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;h2&gt;Wiki&lt;/h2&gt;&lt;br /&gt;  &lt;p&gt;If you are working in a team or even by yourself using a wiki to record things as the project goes along is great. Especially if your memory is anything like mine. Wikis are especially useful if you need to share information about the project or team with people out of your office.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Wiki's such as track also have a bug tracking system built in and integrate with a subversion version control&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;h2&gt;Issue Tracking&lt;/h2&gt;&lt;br /&gt;  &lt;p&gt;As your code base matures you are going to need something to keep track of the problems and changes that people want.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Don't go overboard. Putting too much reliance on an issue tracking system is that same as code generators and wizards in your ide - they stop you thinking about the problem and generate a lot of noise&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Having said that I am a great fan of code generators :)&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;&lt;br /&gt;    &lt;h2&gt;Text Editor&lt;/h2&gt;&lt;br /&gt;  &lt;p&gt;Ok so why put a text editor in the same rankings as version control wikis and such?&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;I am with the &lt;a href="http://www.pragmaticprogrammers.com"&gt;Pragmatic Programmers&lt;/a&gt; on this one. Having a &lt;strong&gt;good&lt;/strong&gt; text editor to call upon is essential. By good I mean it fits your work, you and the things you need do do. But like all good tools you need to spend time with it learning what it is good at. My personal choices are TextMate on the Mac and Emacs just about everywhere.&lt;/p&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;    &lt;h1&gt;Best Practice&lt;/h1&gt;&lt;br /&gt;  &lt;p&gt;Ok now the preachy bit. But as with tools make sure you need the practice before you use it. I have seen project adopt practices because they have seen them work well on other projects without considering the impact or relevance to the current project. Having said that some things really are universal.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;h2&gt;Build servers and pipelines&lt;/h2&gt;&lt;br /&gt;  &lt;p&gt;I have talked a bit about having a build server. If you hav'nt got one look into getting one.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;If you have one then there are some additional things you should consider.&lt;/p&gt;&lt;br /&gt;  &lt;ul&gt;&lt;br /&gt;    &lt;li&gt;Everything on the server came through version control. Ok maybe everything is a bit steep. Your going to need an OS, runtime and build software and other stuff that is just not practical to put through version control. But perhaps scripting the intallation and putting that script in version control would work. It would certainly make it easier to set up another build box.&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;Everything going to production comes from a build server. Yep no more quick file deployes and patches from dev boxes. If it is important enough to put through testing it is important enough to have traceability through the build.&lt;/li&gt;&lt;br /&gt;  &lt;/ul&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;p&gt;In some situations one build server is not enough. Perhaps you are maintaining multiple versions of the application or there are complex integration points that are tested as part of a different build. (It is often useful to have a fast developer build to provide rapid feedback to the developers and then a longer integration build that makes sure the application works in its intended envioronment.)&lt;/p&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;h2&gt;Integration builds&lt;/h2&gt;&lt;br /&gt;  &lt;p&gt;Having mentioned Integraion builds I had better expand on what I mean by integration builds and integration as a concept&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Integration and Continuous Integration (CI) (as part of build systems such as CruiseControl CruiseControl.net etc) are talked about a lot but what does this mean in practice and how best to make use of these tools.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;The word integration and continuous integration covers a lot of concepts. Perhpas the first level of integration and I believe the original intent for work integration of the changes made by eack developer in the team.&lt;/p&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-5029366979402237931?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/5029366979402237931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=5029366979402237931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/5029366979402237931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/5029366979402237931'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/01/project-kit-list.html' title='Project Kit List'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-2975392682361276249</id><published>2008-01-21T11:48:00.001Z</published><updated>2008-01-21T11:50:34.077Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Managing session state in persitent objects</title><content type='html'>&lt;html&gt;&lt;br /&gt;&lt;head&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.ln { color: rgb(0,0,0); font-weight: normal; font-style: normal; }&lt;br /&gt;.s0 { color: rgb(0,0,128); font-weight: bold; }&lt;br /&gt;.s1 { }&lt;br /&gt;.s2 { color: rgb(128,128,128); font-style: italic; }&lt;br /&gt;.s3 { color: rgb(0,128,0); font-weight: bold; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;/head&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;On my current web project, like most web projects, needed a way of managing user session state. We wanted a clean separation from the web tier and a way of managing warnings or annotations to the supplied user data incase the data was not valid.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;We decided to store information supplied in a GET or POST request in document objects. These document objects would then be used by the service tiers to perform the requested operation. Each document object was kept simple by only allowing fields/attributes. The documents would be validated by a validator for each document type, the validators using a utiltity class of validations to keep the duplicate code count low. The documents can be presisted for long running user transactions.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Perhaps the best way to illustrate how this works is with an example. Lets assume that we have a request handler for a registration service that takes a map of name/value pairs for the values the user has supplied on the registration form. For simpliity the response and error handling paths have been ignored.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="l1"&gt;&lt;span class="s0"&gt;import &lt;/span&gt;&lt;span class="s1"&gt;java.util.Map; &lt;br /&gt;&lt;a name="l2"&gt; &lt;br /&gt;&lt;a name="l3"&gt;&lt;/span&gt;&lt;span class="s0"&gt;public class &lt;/span&gt;&lt;span class="s1"&gt;RegisterRequestHandler { &lt;br /&gt;&lt;a name="l4"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private &lt;/span&gt;&lt;span class="s1"&gt;RegistrationService registrationService; &lt;br /&gt;&lt;a name="l5"&gt; &lt;br /&gt;&lt;a name="l6"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public &lt;/span&gt;&lt;span class="s1"&gt;RegisterRequestHandler(RegistrationService registrationService) { &lt;br /&gt;&lt;a name="l7"&gt; &lt;br /&gt;&lt;a name="l8"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;this&lt;/span&gt;&lt;span class="s1"&gt;.registrationService = registrationService; &lt;br /&gt;&lt;a name="l9"&gt;    } &lt;br /&gt;&lt;a name="l10"&gt; &lt;br /&gt;&lt;a name="l11"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public void &lt;/span&gt;&lt;span class="s1"&gt;handlePost(Map&amp;lt;String, String&amp;gt; params) { &lt;br /&gt;&lt;a name="l12"&gt;        RegisterDocument document = readDocument(params); &lt;br /&gt;&lt;a name="l13"&gt; &lt;br /&gt;&lt;a name="l14"&gt;        RegisterDocumentValidator validator = &lt;/span&gt;&lt;span class="s0"&gt;new &lt;/span&gt;&lt;span class="s1"&gt;RegisterDocumentValidator(); &lt;br /&gt;&lt;a name="l15"&gt; &lt;br /&gt;&lt;a name="l16"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;if &lt;/span&gt;&lt;span class="s1"&gt;(validator.validate(document)) { &lt;br /&gt;&lt;a name="l17"&gt;            registrationService.register(document); &lt;br /&gt;&lt;a name="l18"&gt;            redirectToSuccessfulConfirmation(); &lt;br /&gt;&lt;a name="l19"&gt;        } &lt;/span&gt;&lt;span class="s0"&gt;else &lt;/span&gt;&lt;span class="s1"&gt;{ &lt;br /&gt;&lt;a name="l20"&gt;            persistDocument(document); &lt;br /&gt;&lt;a name="l21"&gt;            redirectToRegisterPath(); &lt;br /&gt;&lt;a name="l22"&gt;        } &lt;br /&gt;&lt;a name="l23"&gt; &lt;br /&gt;&lt;a name="l24"&gt;    } &lt;br /&gt;&lt;a name="l25"&gt; &lt;br /&gt;&lt;a name="l26"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private void &lt;/span&gt;&lt;span class="s1"&gt;redirectToSuccessfulConfirmation() { &lt;br /&gt;&lt;a name="l27"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;// ...&lt;/span&gt;&lt;span class="s1"&gt; &lt;br /&gt;&lt;a name="l28"&gt;    } &lt;br /&gt;&lt;a name="l29"&gt; &lt;br /&gt;&lt;a name="l30"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private void &lt;/span&gt;&lt;span class="s1"&gt;persistDocument(RegisterDocument document) { &lt;br /&gt;&lt;a name="l31"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;// ...&lt;/span&gt;&lt;span class="s1"&gt; &lt;br /&gt;&lt;a name="l32"&gt;    } &lt;br /&gt;&lt;a name="l33"&gt; &lt;br /&gt;&lt;a name="l34"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private void &lt;/span&gt;&lt;span class="s1"&gt;redirectToRegisterPath() { &lt;br /&gt;&lt;a name="l35"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;// ...&lt;/span&gt;&lt;span class="s1"&gt; &lt;br /&gt;&lt;a name="l36"&gt;    } &lt;br /&gt;&lt;a name="l37"&gt; &lt;br /&gt;&lt;a name="l38"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private &lt;/span&gt;&lt;span class="s1"&gt;RegisterDocument readDocument(Map&amp;lt;String, String&amp;gt; params) { &lt;br /&gt;&lt;a name="l39"&gt;        RegisterDocument registerDocument = &lt;/span&gt;&lt;span class="s0"&gt;new &lt;/span&gt;&lt;span class="s1"&gt;RegisterDocument(); &lt;br /&gt;&lt;a name="l40"&gt;        registerDocument.name = &lt;/span&gt;&lt;span class="s0"&gt;new &lt;/span&gt;&lt;span class="s1"&gt;Field(params.get(&lt;/span&gt;&lt;span class="s3"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="s1"&gt;)); &lt;br /&gt;&lt;a name="l41"&gt;        registerDocument.password = &lt;/span&gt;&lt;span class="s0"&gt;new &lt;/span&gt;&lt;span class="s1"&gt;Field(params.get(&lt;/span&gt;&lt;span class="s3"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class="s1"&gt;)); &lt;br /&gt;&lt;a name="l42"&gt;        registerDocument.userName = &lt;/span&gt;&lt;span class="s0"&gt;new &lt;/span&gt;&lt;span class="s1"&gt;Field(params.get(&lt;/span&gt;&lt;span class="s3"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span class="s1"&gt;)); &lt;br /&gt;&lt;a name="l43"&gt; &lt;br /&gt;&lt;a name="l44"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;return &lt;/span&gt;&lt;span class="s1"&gt;registerDocument; &lt;br /&gt;&lt;a name="l45"&gt;    } &lt;br /&gt;&lt;a name="l46"&gt;} &lt;br /&gt;&lt;a name="l47"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The handlePost entry point turns the name/value pair of parameters into a registraion document representing the users application for an account. The document is validated and if valid a request for a new account is passed on the appropriate service. If the document is not valid the user is redirected to the registraion application form with any warnings identified int he persisted registrtion document.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The registration document contains the fields we expect from the UI and very simple helper methods.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="l1"&gt;&lt;span class="s0"&gt;public class &lt;/span&gt;&lt;span class="s1"&gt;RegisterDocument { &lt;br /&gt;&lt;a name="l2"&gt;    Field userName; &lt;br /&gt;&lt;a name="l3"&gt;    Field password; &lt;br /&gt;&lt;a name="l4"&gt;    Field name; &lt;br /&gt;&lt;a name="l5"&gt; &lt;br /&gt;&lt;a name="l6"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public boolean &lt;/span&gt;&lt;span class="s1"&gt;hasWarning() { &lt;br /&gt;&lt;a name="l7"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;return &lt;/span&gt;&lt;span class="s1"&gt;userName.hasWarning() || password.hasWarning() || name.hasWarning(); &lt;br /&gt;&lt;a name="l8"&gt;    } &lt;br /&gt;&lt;a name="l9"&gt;} &lt;br /&gt;&lt;a name="l10"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The field class manages the value and any warnings.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="l1"&gt;&lt;span class="s0"&gt;public class &lt;/span&gt;&lt;span class="s1"&gt;Field { &lt;br /&gt;&lt;a name="l2"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private &lt;/span&gt;&lt;span class="s1"&gt;String value; &lt;br /&gt;&lt;a name="l3"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private &lt;/span&gt;&lt;span class="s1"&gt;Annotation annotation; &lt;br /&gt;&lt;a name="l4"&gt; &lt;br /&gt;&lt;a name="l5"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public &lt;/span&gt;&lt;span class="s1"&gt;Field(String value, Annotation annotation) { &lt;br /&gt;&lt;a name="l6"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;this&lt;/span&gt;&lt;span class="s1"&gt;.value = value; &lt;br /&gt;&lt;a name="l7"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;this&lt;/span&gt;&lt;span class="s1"&gt;.annotation = annotation; &lt;br /&gt;&lt;a name="l8"&gt;    } &lt;br /&gt;&lt;a name="l9"&gt; &lt;br /&gt;&lt;a name="l10"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public &lt;/span&gt;&lt;span class="s1"&gt;Field(String value) { &lt;br /&gt;&lt;a name="l11"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;this&lt;/span&gt;&lt;span class="s1"&gt;(value, Annotation.none); &lt;br /&gt;&lt;a name="l12"&gt;    } &lt;br /&gt;&lt;a name="l13"&gt; &lt;br /&gt;&lt;a name="l14"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public &lt;/span&gt;&lt;span class="s1"&gt;String getValue() { &lt;br /&gt;&lt;a name="l15"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;return &lt;/span&gt;&lt;span class="s1"&gt;value; &lt;br /&gt;&lt;a name="l16"&gt;    } &lt;br /&gt;&lt;a name="l17"&gt; &lt;br /&gt;&lt;a name="l18"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public void &lt;/span&gt;&lt;span class="s1"&gt;addWarning(String warning) { &lt;br /&gt;&lt;a name="l19"&gt;        annotation = &lt;/span&gt;&lt;span class="s0"&gt;new &lt;/span&gt;&lt;span class="s1"&gt;Annotation(warning, Annotation.AnnotationType.warning); &lt;br /&gt;&lt;a name="l20"&gt;    } &lt;br /&gt;&lt;a name="l21"&gt; &lt;br /&gt;&lt;a name="l22"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public boolean &lt;/span&gt;&lt;span class="s1"&gt;hasWarning() { &lt;br /&gt;&lt;a name="l23"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;return &lt;/span&gt;&lt;span class="s1"&gt;annotation.getType() == Annotation.AnnotationType.warning; &lt;br /&gt;&lt;a name="l24"&gt;    } &lt;br /&gt;&lt;a name="l25"&gt;} &lt;br /&gt;&lt;a name="l26"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Perhpas choosing the most overloaded name (Annotation) this class models the validators response. Allowing warnings or infomation to be associated with the value. Used to report problems back to the user.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="l1"&gt;&lt;span class="s0"&gt;public class &lt;/span&gt;&lt;span class="s1"&gt;Annotation { &lt;br /&gt;&lt;a name="l2"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;enum &lt;/span&gt;&lt;span class="s1"&gt;AnnotationType { &lt;br /&gt;&lt;a name="l3"&gt;        warning, info, none &lt;br /&gt;&lt;a name="l4"&gt;    } &lt;br /&gt;&lt;a name="l5"&gt; &lt;br /&gt;&lt;a name="l6"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private &lt;/span&gt;&lt;span class="s1"&gt;AnnotationType type; &lt;br /&gt;&lt;a name="l7"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private &lt;/span&gt;&lt;span class="s1"&gt;String value; &lt;br /&gt;&lt;a name="l8"&gt; &lt;br /&gt;&lt;a name="l9"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public static &lt;/span&gt;&lt;span class="s1"&gt;Annotation none = &lt;/span&gt;&lt;span class="s0"&gt;new &lt;/span&gt;&lt;span class="s1"&gt;Annotation(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="s1"&gt;, AnnotationType.none); &lt;br /&gt;&lt;a name="l10"&gt; &lt;br /&gt;&lt;a name="l11"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public &lt;/span&gt;&lt;span class="s1"&gt;Annotation(String value, AnnotationType type) { &lt;br /&gt;&lt;a name="l12"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;this&lt;/span&gt;&lt;span class="s1"&gt;.value = value; &lt;br /&gt;&lt;a name="l13"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;this&lt;/span&gt;&lt;span class="s1"&gt;.type = type; &lt;br /&gt;&lt;a name="l14"&gt;    } &lt;br /&gt;&lt;a name="l15"&gt; &lt;br /&gt;&lt;a name="l16"&gt; &lt;br /&gt;&lt;a name="l17"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public &lt;/span&gt;&lt;span class="s1"&gt;AnnotationType getType() { &lt;br /&gt;&lt;a name="l18"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;return &lt;/span&gt;&lt;span class="s1"&gt;type; &lt;br /&gt;&lt;a name="l19"&gt;    } &lt;br /&gt;&lt;a name="l20"&gt;} &lt;br /&gt;&lt;a name="l21"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="l1"&gt;&lt;span class="s0"&gt;public class &lt;/span&gt;&lt;span class="s1"&gt;RegisterDocumentValidator { &lt;br /&gt;&lt;a name="l2"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;public boolean &lt;/span&gt;&lt;span class="s1"&gt;validate(RegisterDocument document) { &lt;br /&gt;&lt;a name="l3"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;if &lt;/span&gt;&lt;span class="s1"&gt;(isEmpty(document.name.getValue())) { &lt;br /&gt;&lt;a name="l4"&gt;            document.name.addWarning(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You must supply a name&amp;quot;&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br /&gt;&lt;a name="l5"&gt;        } &lt;br /&gt;&lt;a name="l6"&gt; &lt;br /&gt;&lt;a name="l7"&gt;        &lt;/span&gt;&lt;span class="s3"&gt;// ...&lt;/span&gt;&lt;span class="s1"&gt; &lt;br /&gt;&lt;a name="l8"&gt; &lt;br /&gt;&lt;a name="l9"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;return &lt;/span&gt;&lt;span class="s1"&gt;document.hasWarning(); &lt;br /&gt;&lt;a name="l10"&gt;    } &lt;br /&gt;&lt;a name="l11"&gt; &lt;br /&gt;&lt;a name="l12"&gt;    &lt;/span&gt;&lt;span class="s0"&gt;private boolean &lt;/span&gt;&lt;span class="s1"&gt;isEmpty(String name) { &lt;br /&gt;&lt;a name="l13"&gt;        &lt;/span&gt;&lt;span class="s0"&gt;return &lt;/span&gt;&lt;span class="s1"&gt;(name == &lt;/span&gt;&lt;span class="s0"&gt;null &lt;/span&gt;&lt;span class="s1"&gt;|| name.length() == &lt;/span&gt;&lt;span class="s4"&gt;0&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br /&gt;&lt;a name="l14"&gt;    } &lt;br /&gt;&lt;a name="l15"&gt;} &lt;br /&gt;&lt;a name="l16"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Any services use the documents as parameters. They are decoupled from the UI and can be more easily unit tested.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="l5"&gt;&lt;/span&gt;&lt;span class="s2"&gt;public interface &lt;/span&gt;&lt;span class="s1"&gt;RegistrationService { &lt;br /&gt;&lt;a name="l6"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;void &lt;/span&gt;&lt;span class="s1"&gt;register(RegisterDocument document); &lt;br /&gt;&lt;a name="l7"&gt;} &lt;br /&gt;&lt;a name="l8"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-2975392682361276249?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/2975392682361276249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=2975392682361276249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/2975392682361276249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/2975392682361276249'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2008/01/managing-session-state-in-persitent.html' title='Managing session state in persitent objects'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3215278939917454572.post-8198616289062919910</id><published>2007-12-10T00:00:00.001Z</published><updated>2007-12-10T00:00:13.823Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sony Ericsson'/><category scheme='http://www.blogger.com/atom/ns#' term='W850i'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Maps'/><title type='text'>Google Maps and the Sony Ericsson W850i</title><content type='html'>A friend of mine demoed &lt;a href="http://www.google.com/gmm/index.html"&gt;Google Maps&lt;/a&gt; My Location feature on his mobile phone. I had been using google maps for a while so downloaded the latest version - but alas no 'My Location' feature.&lt;br /&gt;&lt;br /&gt;Time for a firmware update&lt;br /&gt;&lt;br /&gt;Sony have a couple of apps required for the job. The PC Suite contains all the drivers and an update program for the firmware. Installation under &lt;a href="www.vmware.com"&gt;VMWare&lt;/a&gt; Fusion was seamless. The UI is quite flash but it still took me a couple of goes to realise that the 'C' button the instructions referred to was the Cancel button rather than the 3 button (it was late in the evening).&lt;br /&gt;&lt;br /&gt;Once the firmware was updated and GMM installed the location feature got me to within 100m - not bad as I was sitting in a basement flat! The directions feature is fab - working off a postcode the route to work (driving) was pretty good.&lt;br /&gt;&lt;br /&gt;As a bonus the software on the phone felt a lot more responsive - although some of the options had move around.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3215278939917454572-8198616289062919910?l=grahambrooks.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahambrooks.blogspot.com/feeds/8198616289062919910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3215278939917454572&amp;postID=8198616289062919910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/8198616289062919910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3215278939917454572/posts/default/8198616289062919910'/><link rel='alternate' type='text/html' href='http://grahambrooks.blogspot.com/2007/12/google-maps-and-sony-ericsson-w850i.html' title='Google Maps and the Sony Ericsson W850i'/><author><name>Graham Brooks</name><uri>http://www.blogger.com/profile/04938624738598367225</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08904043416841825201'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>