<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>craigaspinall.com blog</title>
 
 <link href="http:/craigaspinall.com/" />
 <updated>2011-11-24T04:02:33-08:00</updated>
 <id>http://craigaspinall.com/</id>
 <author>
   <name>Craig Aspinall</name>
   <email>craig.aspinall@gmail.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Craigaspinallcom" /><feedburner:info uri="craigaspinallcom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Can Kotlin K.O. contenders?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/UWp2e20lKUE/can-kotlin-ko-contenders.html" />
   <updated>2011-07-29T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2011/07/29/can-kotlin-ko-contenders</id>
   <content type="html">&lt;p&gt;If you follow my &lt;a href="http://twitter.com/aspinall"&gt;Twitter feed&lt;/a&gt; then you may have seen my initial reaction to &lt;a href="http://www.jetbrains.com"&gt;Jetbrains&lt;/a&gt; announcement that they were working on another &lt;span class="caps"&gt;JVM&lt;/span&gt; language was one of disdain. Not because I don&amp;#8217;t think Jetbrains can create a compelling language, but because I was concerned that the &lt;span class="caps"&gt;JVM&lt;/span&gt; language space is becoming saturated, and too much choice can be just as harmful as no choice at all!&lt;/p&gt;
&lt;p&gt;Having had a bit more time to look into it, I don&amp;#8217;t think my initial reaction was warranted, and I shouldn&amp;#8217;t have been so dismissive of &lt;a href="http://confluence.jetbrains.net/display/Kotlin/Kotlin"&gt;Kotlin&lt;/a&gt;. When you look closely at the successful &lt;span class="caps"&gt;JVM&lt;/span&gt; languages, all of them with the exception of Scala are dynamically typed. If you want a statically typed alternative to Java that has a reasonable chance of still being around in a few years, you really only have the choice of &lt;a href="http://www.scala-lang.org"&gt;Scala&lt;/a&gt;, &lt;a href="http://code.google.com/p/groovypptest/"&gt;Groovy++&lt;/a&gt; or &lt;a href="http://gosu-lang.org/"&gt;Gosu&lt;/a&gt;. There is clearly room for more choice in this space and Kotlin (and Red Hat&amp;#8217;s &lt;a href="http://en.wikipedia.org/wiki/Ceylon_Project"&gt;Ceylon&lt;/a&gt;) are trying to fill it. Hopefully the competition will be healthy and we&amp;#8217;ll end up with more than one good language to choose from.&lt;/p&gt;
&lt;p&gt;So far Scala has been the main contender to challenge for the position of &lt;em&gt;a better Java&lt;/em&gt;, yet it seems to divide opinion very easily. Jetbrains have labelled it too complex in their justification for creating Kotlin, a topic which Martin Odersky &lt;a href="http://lamp.epfl.ch/~odersky/blogs/isscalacomplex.html"&gt;has addressed before&lt;/a&gt;. I think the real problem is just that Scala is a different language to Java and therefore (as with all new languages) you have to put some effort into learning it and practicing with it before you can use it proficiently. Whether Kotlin is enough like Java to avoid the mental leap remains to be seen, but I wish JetBrains (and all the language creators) the best of luck in their battle royale for the title of &lt;strong&gt;The Better Java&lt;/strong&gt;. Without them, the Java ecosystem would be a very dull place!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/UWp2e20lKUE" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/07/29/can-kotlin-ko-contenders.html</feedburner:origLink></entry>
 
 <entry>
   <title>My technology radar</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/FpFWmsen7Do/my-technology-radar.html" />
   <updated>2011-07-28T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2011/07/28/my-technology-radar</id>
   <content type="html">&lt;p&gt;One of the things I learned at &lt;a href="http://uberconf.com"&gt;Uberconf&lt;/a&gt; was how to build your own &lt;a href="http://www.thoughtworks.com/radar"&gt;technology radar&lt;/a&gt;, a tool that &lt;a href="http://www.thoughtworks.com"&gt;ThoughtWorks&lt;/a&gt; use to decide what technologies they should (or would like) to use either internally or on customer engagements. I&amp;#8217;ve built two so far, one for myself and one for my day job, and in both cases I&amp;#8217;ve found it to be a really useful thought exercise.&lt;/p&gt;
&lt;p&gt;This is my personal radar:&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/technology-radar.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;It is split into four technology quadrants:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Tools&lt;/li&gt;
	&lt;li&gt;Techniques&lt;/li&gt;
	&lt;li&gt;Platforms&lt;/li&gt;
	&lt;li&gt;Languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And into four levels of interest (with my personal spin on the meanings):&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Hold &amp;#8211; do not use on anything new&lt;/li&gt;
	&lt;li&gt;Assess &amp;#8211; is it something I can use&lt;/li&gt;
	&lt;li&gt;Trial &amp;#8211; look for an excuse to use it on something&lt;/li&gt;
	&lt;li&gt;Adopt &amp;#8211; one of my &lt;em&gt;go to&lt;/em&gt; technologies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also things in red are on an outward trajectory and things in green are on an inward trajectory.&lt;/p&gt;
&lt;p&gt;So what I decided is that I&amp;#8217;m putting &lt;span class="caps"&gt;GTD&lt;/span&gt; on hold so I can try out personal kanban and see how that works out for me. I&amp;#8217;m also leaning much more heavily on Acceptence Test Driven Development and Test Driven Development and will be encouraging others to do the same, as well as learning and promoting functional programming.&lt;/p&gt;
&lt;p&gt;In the tools space, I&amp;#8217;ve dropped Subversion and Mercurial in favour of Git, and I&amp;#8217;ve dropped Maven in favour of Gradle, and I&amp;#8217;ll assess whether I need to use Leinengen to build my Clojure projects or whether I can do that in Gradle too. I&amp;#8217;m siding with Jenkins over Hudson and I want to use Sonar much more effectively.&lt;/p&gt;
&lt;p&gt;Groovy is now my &lt;em&gt;go to&lt;/em&gt; language and Clojure is the language I am most interested in learning. I don&amp;#8217;t want to write Java code if I can avoid it so I should be looking more closely at Groovy++, Scala and Gosu for the times when I need a statically typed &lt;span class="caps"&gt;JVM&lt;/span&gt; language. I&amp;#8217;m still interested in Haskell (primarily to learn functional programming) but I&amp;#8217;m also keen to get more into the web space, hence JavaScript and CoffeeScript being on my radar too.&lt;/p&gt;
&lt;p&gt;Finally in the platforms space, since I am moving more towards web applications, I am looking at the cloud computing offerings from EC2, AppEngine, NineFold and CloudBees (although I&amp;#8217;m also interested in CloudBees for the hosted Jenkins offering). I&amp;#8217;ve also dropped Bitbucket and Google Code in favour of GitHub in line with my change over to Git.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/FpFWmsen7Do" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/07/28/my-technology-radar.html</feedburner:origLink></entry>
 
 <entry>
   <title>Uberconf, Uber Geeks, Uber Tired!</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/Fvt_FdtIzFU/uberconf.html" />
   <updated>2011-07-15T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2011/07/15/uberconf</id>
   <content type="html">&lt;p&gt;My first &lt;a href="http://uberconf.com"&gt;Uberconf&lt;/a&gt; is over. Was it worth the 16,000 mile (26,000km) round trip and a week away from my family? It was definitely worth making the trip but now I need a holiday to get over it because I&amp;#8217;m exhausted and next time, I&amp;#8217;ll bring my family along for the ride!&lt;/p&gt;
&lt;p&gt;The conference is a learning and networking feast, with a wide variety of great content delivered professionally by awesome speakers that really understand their subject matter. The Westin Westiminster hotel was also a great vanue that catered well for a conference of this size, in terms of the rooms, the delegate accommodation and the food.&lt;/p&gt;
&lt;p&gt;Almost all of the sessions I went to were good, but if I had to pick my top three sessions it would be these:&lt;/p&gt;
&lt;h5&gt;&lt;em&gt;Encryption on the &lt;span class="caps"&gt;JVM&lt;/span&gt;: Boot Camp&lt;/em&gt; by &lt;a href="http://twitter.com/#!/matthewmccull"&gt;Matthew Mccullough&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Matthew completely blew me away with this talk. Not because of the subject matter but &lt;strong&gt;how&lt;/strong&gt; he delivered it. I have never seen anyone deliver a presentation as professionally as Matthew did. I attended two of his other talks and he was just as good in both of those, even when the wifi was conspiring against him! He is definitely the Steve Jobs of the No Fluff Just Stuff crowd!&lt;/p&gt;
&lt;p&gt;This is a subject that I knew next to nothing about before the session and I left feeling confident that I could go and implement encryption correctly and effectively afterwards. I also really enjoyed his &lt;em&gt;Thinking in Git&lt;/em&gt; presentation which gave me lots more reasons to love Git!&lt;/p&gt;
&lt;p&gt;I also got the chance to sit next to Matthew for dinner one evening and he is a really nice guy too. Very engaging, humble and friendly. A definite star in our industry.&lt;/p&gt;
&lt;h5&gt;&lt;em&gt;Complexity Theory in Software Development&lt;/em&gt; by &lt;a href="http://twitter.com/#!/tlberglund"&gt;Tim Berglund&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Like Matthew, Tim is an excellent presenter and this talk was probably the most thought provoking of all those I attended. It was a whistlestop tour of what &lt;em&gt;complexity theory&lt;/em&gt; is and what bearing is has on our daily lives and the software we write. It was both educational and challenging in exactly the right proportions.&lt;/p&gt;
&lt;p&gt;He also delivered a wonderful skit after dinner one evening, called &lt;a href="http://www.youtube.com/watch?v=xZKmmdCnTUY"&gt;Oh, The Methods You&amp;#8217;ll Compose&lt;/a&gt;, which almost got a standing ovation from the audience! It reminded me very much of Guy Steele&amp;#8217;s and Richard Gabriel&amp;#8217;s &lt;a href="http://blip.tv/file/1472720/"&gt;50 in 50&lt;/a&gt; keynote that I was fortunate enough to see live at &lt;a href="http://yowaustralia.com.au/"&gt;&lt;span class="caps"&gt;YOW&lt;/span&gt;!&lt;/a&gt; Brisbane last year.&lt;/p&gt;
&lt;h5&gt;&lt;em&gt;Towards a Humane Interface&lt;/em&gt; by &lt;a href="http://twitter.com/#!/venkat_s"&gt;Venkat Subramaniam&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;I wasn&amp;#8217;t able to make any of Venkat&amp;#8217;s other talks but I had been told that he was an excellent speaker and didn&amp;#8217;t want to miss out on the opportunity to see him. This subject wouldn&amp;#8217;t have been top of my list of his talks, but it was the only one where I didn&amp;#8217;t have a clash!&lt;/p&gt;
&lt;p&gt;As it happened it was the last session of the conference and Venkat was in excellent form! He engaged the audience with some great anecdotes and was animated and jovial throughout. He clearly has a passion for all the work that he does and it was a great privilege to see him in action.&lt;/p&gt;
&lt;p&gt;Narrowing it down to three talks was very difficult and the three I&amp;#8217;ve picked out are the ones I enjoyed the most, but these guys also deserve special mention:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;a href="http://twitter.com/#!/neal4d"&gt;Neal Ford&lt;/a&gt; for &lt;strong&gt;Build Your Own Technology Radar&lt;/strong&gt;, which was another very thought provoking session.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://twitter.com/#!/sansappsec"&gt;Frank Kim&lt;/a&gt; for &lt;em&gt;Tricks of the Trade: What Every Developer Should Know About Application Security&lt;/em&gt;, which was both educational and very scary as we worked through case studies of actual security breaches and Frank demo&amp;#8217;d how easy some of the common hacks are!&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://twitter.com/#!/HamletDRC"&gt;Hamlet D&amp;#8217;Arcy&lt;/a&gt; for &lt;em&gt;Effective Groovy&lt;/em&gt; which was my first Uberconf session and had some great lessons for intermediate Groovy developers such as myself to learn and improve from.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Last but not least I need to say thank you to &lt;a href="http://twitter.com/#!/nofluff"&gt;Jay Zimmerman&lt;/a&gt;, Mr. No Fluff himself. I know that he was very helpful in getting me to the conference and he made a point of coming over and checking how I was getting on, obviously remembering the e-mail exchange he had with my team leader. Now I know that is just typical of his attention to detail and the reason that the No Fluff Just Stuff conferences have the reputation that they do.&lt;/p&gt;
&lt;p&gt;The only criticisms I had from the conference (and I know other attendees had the same problems) were:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;There were 10 tracks and in many slots I wanted to attend five talks. Having too much good content is clearly an excellent problem to have, but I really feel like I missed out on more than I got (which was still a lot).&lt;/li&gt;
	&lt;li&gt;The multi session workshops meant you had the choice of missing out on 1-4 sessions at a time, or not attending the workshop.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Clearly the conference couldn&amp;#8217;t be any longer, neither the speakers or the delegates would survive! Maybe grouping the sessions so that all the beginner/introductory sessions ran concurrently, then the intermediate then the expert ones. Given everyone will be at different levels on different tracks, they could have the choice of going from beginner to expert in one track, or cut between them depending on their existing expertise level. Also grouping the workshops together might work better.&lt;/p&gt;
&lt;p&gt;Finally, I met a lot of very talented, very passionate and very friendly people at this conference, delegates and speakers alike. I cannot recommend it highly enough.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/Fvt_FdtIzFU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/07/15/uberconf.html</feedburner:origLink></entry>
 
 <entry>
   <title>What is functional programming?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/-0uqBn6dXBs/what-is-functional-programming.html" />
   <updated>2011-06-23T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2011/06/23/what-is-functional-programming</id>
   <content type="html">&lt;p&gt;I gave a talk at our &lt;a href="http://www.meetup.com/CodingByNumbers/events/21665201"&gt;Coding By Numbers meetup&lt;/a&gt; tonight that attempts to peel away some of the mystery surrounding that question. It was a small audience but they appeared to appreciate it and I hope I was able to show them that many of the benefits of functional programming are easily accessible.&lt;/p&gt;
&lt;p&gt;The slides and handouts are available &lt;a href="/talks/what-is-fp/what-is-fp.html"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/-0uqBn6dXBs" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/06/23/what-is-functional-programming.html</feedburner:origLink></entry>
 
 <entry>
   <title>I didn't get Git</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/HFPB4et_q0A/i-didnt-get-git.html" />
   <updated>2011-06-20T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2011/06/20/i-didnt-get-git</id>
   <content type="html">&lt;p&gt;OK, I admit it, I didn&amp;#8217;t get &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt; when I started playing around with distributed version control last year. In fact I dismissed it as being too complicated for my needs after about five minutes. Boy, what a mistake! .&lt;/p&gt;
&lt;p&gt;The main reason I was looking at distributed version control systems was because I was doing a lot of work on the train and I wanted something that could track changes locally so I could revert when I inevitably screwed something up. I also wanted to be able to push the changes to a hosted repository when I got home, so I had an offsite backup and to share the code with others. This ruled out the likes of &lt;a href="http://subversion.apache.org"&gt;Subversion&lt;/a&gt; and I ended up settling on &lt;a href="http://mercurial.selenic.com"&gt;Mercurial&lt;/a&gt; with &lt;a href="http://bitbucket.org"&gt;Bitbucket&lt;/a&gt; for free repository hosting.&lt;/p&gt;
&lt;p&gt;Whilst I still think that Mercurial and Bitbucket are fantastic tools, the process of moving this blog to &lt;a href="http://pages.github.com"&gt;GitHub Pages&lt;/a&gt; has forced me to learn Git properly and I&amp;#8217;ve had a bit of an epiphany with it. Now I&amp;#8217;m starting to think that Git is the way that all version control should be.&lt;/p&gt;
&lt;h5&gt;The staging area&lt;/h5&gt;
&lt;p&gt;At first, having to add changes to the staging area before each commit was bugging the life out of me. That was until I made changes for more than one reason at once. Of course, it makes sense to separate these changes, and git forces to operate that way by default. Of course you can do this with Subversion by committing specific files, but git forces you to think about it.&lt;/p&gt;
&lt;p&gt;And it doesn&amp;#8217;t end there. Using &lt;code&gt;git add -p&lt;/code&gt;, you can reduce the granularity of your commits to individual lines within a file. This is a huge get out of jail free card for me, as I often end up fixing one thing within a file whilst working on something else in the same file. Using this mechanism, the two changes can be committed separately, as they should!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/HFPB4et_q0A" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/06/20/i-didnt-get-git.html</feedburner:origLink></entry>
 
 <entry>
   <title>Welcome to the real world!</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/4a67n5NEZow/welcome-to-the-real-world.html" />
   <updated>2011-06-10T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2011/06/10/welcome-to-the-real-world</id>
   <content type="html">&lt;p&gt;To hijack and abuse yet another quote from &lt;a href="http://www.imdb.com/title/tt0133093/"&gt;The Matrix&lt;/a&gt;, &amp;#8220;welcome to the real world!&amp;#8221; (or at least my new home in the virtual one)! After being inspired by &lt;a href="http://twitter.com/TheColonial"&gt;@TheColonial&lt;/a&gt; and his adventures with &lt;a href="http://www.blogofile.com/"&gt;Blogofile&lt;/a&gt;, I decided that I needed to move my blog to a system that was backed by a version control system.&lt;/p&gt;
&lt;p&gt;I had a number of reasons for doing this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;I wanted to be in complete control of all of my data.&lt;/li&gt;
	&lt;li&gt;I wanted to be able to compose and edit posts offline.&lt;/li&gt;
	&lt;li&gt;I wanted to somewhere to host materials from the talks that I give.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The solution I ended up going with was &lt;a href="http://pages.github.com"&gt;GitHub Pages&lt;/a&gt;. Firstly because it is free. Secondly because it is awesome!&lt;/p&gt;
&lt;p&gt;Your entire site is a repository that you can clone like any other git repository. The difference is that when you push changes back to GitHub, it automatically runs &lt;a href="http://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; (a blog aware static site generator) and republishes the resulting site for you. The beauty of Jekyll is that a normal &lt;span class="caps"&gt;HTML&lt;/span&gt; site is also a valid Jekyll site, so normal &lt;span class="caps"&gt;HTML&lt;/span&gt; sites will pass through unchanged.&lt;/p&gt;
&lt;p&gt;If you do take advantage of Jekyll however, you can create &lt;span class="caps"&gt;HTML&lt;/span&gt; templates using &lt;a href="http://www.liquidmarkup.org/"&gt;Liquid&lt;/a&gt; and author content in &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; or &lt;a href="http://www.textism.com/tools/textile/"&gt;Textile&lt;/a&gt;. It even supports syntax highlighting courtesy of &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve moved the technical and technology related posts from &lt;a href="http://craigaspinall.tumblr.com"&gt;Tumblr&lt;/a&gt; over to here so anyone transferring over can still access my old content, and anyone arriving here for the first time has something to read.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/4a67n5NEZow" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/06/10/welcome-to-the-real-world.html</feedburner:origLink></entry>
 
 <entry>
   <title>Quitting Facebook</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/Lp8xM0tk_lU/quitting-facebook.html" />
   <updated>2011-04-24T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2011/04/24/quitting-facebook</id>
   <content type="html">&lt;p&gt;After listening to Mark Pesce&amp;#8217;s controversial keynote presentation at LinuxConf Australia 2011 (and giving myself a couple of months to think about it), I&amp;#8217;ve decided that the time has come to leave Facebook, and to encourage others to do the same. If you want to understand why, I strongly recommend you read &lt;a href="http://blog.futurestreetconsulting.com/2011/01/28/smoke-signals/"&gt;Mark&amp;#8217;s presentation&lt;/a&gt; but here are the reasons in a nutshell.&lt;/p&gt;
&lt;p&gt;The most valuable piece of information about you is your social graph and the communication that occurs across that graph. That reveals more about you, your personal interests, even your secrets, than anything else that you do online. And Facebook is watching and recording it all.&lt;/p&gt;
&lt;p&gt;This might not be so disturbing if Facebook had not repeatedly let members down with regards to the privacy of their data. Or if people actually understood what information they are divulging to Facebook. Whilst many have pointed to the likes of Microsoft and Google as potential dystopian &amp;#8220;big brother&amp;#8221; overlords, Facebook is probably much better poised in reality.&lt;/p&gt;
&lt;p&gt;So I&amp;#8217;m making my own (sadly insignificant) stand by quitting. I encourage you to do the same.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/Lp8xM0tk_lU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/04/24/quitting-facebook.html</feedburner:origLink></entry>
 
 <entry>
   <title>Extending classses at runtime with Groovy</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/DfMoQkeXdNY/extending-groovy-classes-at-runtime.html" />
   <updated>2011-03-03T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2011/03/03/extending-groovy-classes-at-runtime</id>
   <content type="html">&lt;p&gt;I gave an introduction to Groovy at our local &lt;span class="caps"&gt;JUG&lt;/span&gt; this week and didn&amp;#8217;t quite manage to make it through all the material I wanted to cover, so I decided to add the missing content here! The part I missed out in the meetup was how to extend a class at runtime via it&amp;#8217;s metaClass.&lt;/p&gt;
&lt;p&gt;If you add a named closure to the metaClass of an existing class, then it essentially becomes available as a method on that class. In this example, I&amp;#8217;ve added a &lt;code&gt;containsOnly(Collection anotherCollection)&lt;/code&gt; method to the &lt;code&gt;Collection&lt;/code&gt; class, which returns &lt;code&gt;true&lt;/code&gt; if two collections have the same content but not necessarily in the same order.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;metaClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt; &lt;span class="n"&gt;otherCollection&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otherCollection&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;otherCollection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsOnly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsOnly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;delegate&lt;/code&gt; is an implicit argument referring to the object on which the &lt;code&gt;containsOnly()&lt;/code&gt; method is being called.&lt;/p&gt;
&lt;p&gt;In the following case, I have extended the &lt;code&gt;Collection&lt;/code&gt; class again to add a &lt;code&gt;choose(int numberOfElements)&lt;/code&gt; method, which selects a supplied number of elements from the collection, chosen at random. Note that the &lt;code&gt;return&lt;/code&gt; keyword is optional, I&amp;#8217;ve used it here for clarity.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;metaClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;choose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numberOfElements&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;numberOfElements&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;delegate&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;List&lt;/span&gt; &lt;span class="n"&gt;previouslyUsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;List&lt;/span&gt; &lt;span class="n"&gt;chosen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chosen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;numberOfElements&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;nextInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;previouslyUsed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;chosen&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;previouslyUsed&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chosen&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;choose&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;five&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;choose&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;five&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;five&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;twelve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;choose&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// should only return 10!&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;twelve&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twelve&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;My final example extends the &lt;code&gt;String&lt;/code&gt; class so that you can easily cast it to a &lt;code&gt;Date&lt;/code&gt; instance using a fixed conversion format. Groovy uses this syntax for casting (which is much nicer than Java):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="s"&gt;&amp;quot;08/08/1988&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Under the hood, Groovy calls the &lt;code&gt;asType(Class targetType)&lt;/code&gt; method to perform the conversion, and that already supports casting to a number of different types. To add &lt;code&gt;Date&lt;/code&gt; casting I had to replace the existing method definition. So that I didn&amp;#8217;t lose the original functionality, I captured the original method and delegated to it if we&amp;#8217;re not trying to cast to a &lt;code&gt;Date&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;oldAsType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;metaClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMetaMethod&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;asType&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;[])&lt;/span&gt;
&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;metaClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="n"&gt;targetType&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dd/MM/yyyy&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;oldAsType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoke&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;targetType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Now we can call...&lt;/span&gt;
&lt;span class="s"&gt;&amp;quot;08/08/1988&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/DfMoQkeXdNY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2011/03/03/extending-groovy-classes-at-runtime.html</feedburner:origLink></entry>
 
 <entry>
   <title>The role of automated testing</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/7bsoPhJc-PI/the-role-of-automated-testing.html" />
   <updated>2010-11-28T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/28/the-role-of-automated-testing</id>
   <content type="html">&lt;p&gt;Over the last week I&amp;#8217;ve had a lot of discussions about the underlying motive of the roles that my colleagues and I are currently performing. We are responsible for improving the quality of software being produced by the teams we are involved with, and the main focus of our recent work has been creating automation tools to assist the testers. There are three possible motives for our roles:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;to reduce costs&lt;/li&gt;
	&lt;li&gt;to increase productivity&lt;/li&gt;
	&lt;li&gt;to improve quality&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For us it&amp;#8217;s a simple case of improving quality but that doesn&amp;#8217;t necessarily mean that our leaders have the same motives. In fairness they do overlap, but focusing too much on any one of them can be to the detriment of the others.&lt;/p&gt;
&lt;p&gt;For example, if you want to reduce costs and automated testing makes the testers four times more productive, then in theory you can remove three quarters of your testers without any loss of quality or productivity. Of course the theory and reality are quite different! Similarly, if you go all out for quality, you may need more people or tools or equipment which will result in increased costs, and progress may be slower.&lt;/p&gt;
&lt;p&gt;The catalyst for the discussions was that we just found out that the number of testers is being reduced on one of the projects we&amp;#8217;re working on and we were horrified. We were very concerned that the work we have been doing was being used to justify cost reductions but fortunately that isn&amp;#8217;t the case (at least not this time).&lt;/p&gt;
&lt;p&gt;Since our goal is to improve quality we expect that any cost savings we enable during development are re-investing into improving quality in other ways. This should include freeing up the testers to do more exploratory testing, but could also include things like performance, security or usability testing that often get overlooked.&lt;/p&gt;
&lt;p&gt;Even with that investment, we expect that there will still be an overall reduction in cost, simply because less defects will get to production. The cost of fixing defects increases exponentially the later in the process they are found, because more and more people become involved in the development, testing and technical support of the fix. Unfortunately the total cost of ownership is not easy to quantify and rarely gets the focus it deserves.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://goo.gl/Z69dl"&gt;Episode 18&lt;/a&gt; of the &lt;a href="http://www.codingbynumbers.com"&gt;Coding By Numbers&lt;/a&gt; podcast (which I co-host) has a much more in depth discussion on this subject if you want to hear more!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/7bsoPhJc-PI" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/28/the-role-of-automated-testing.html</feedburner:origLink></entry>
 
 <entry>
   <title>Is Haskell actually a simple language?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/YhVhKP3Sl6k/is-haskell-actually-simple.html" />
   <updated>2010-11-27T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/27/is-haskell-actually-simple</id>
   <content type="html">&lt;p&gt;Whilst I was writing the previous post about learning Haskell, I was reminded of &lt;a href="http://lamp.epfl.ch/~odersky/blogs/isscalacomplex.html"&gt;a post by Martin Odersky&lt;/a&gt; about the complexity or otherwise of Scala. In that post he tries several metaphors to determine what &lt;em&gt;simple&lt;/em&gt; really means, finally settling on Duplo versus Technics Lego. You can build anything with either (just as you can with turing complete languages) but a solution built with Duplo is unlikely to be as elegant as a solution built with Technics.&lt;/p&gt;
&lt;p&gt;I like his comparison because it shows how much &lt;em&gt;simplicity&lt;/em&gt; is a concept that means different things to different people. I&amp;#8217;m starting to think that Haskell is a really simple language, even though I&amp;#8217;m finding it difficult to learn!&lt;/p&gt;
&lt;p&gt;One of the relative measures of complexity used in the article is the number of keywords in a language. Carlos Quintanilla&amp;#8217;s &lt;a href="http://carlosqt.blogspot.com/2010/07/how-many-keywords-do-you-type-in-your.html"&gt;comparison of &lt;span class="caps"&gt;CLR&lt;/span&gt; and &lt;span class="caps"&gt;JVM&lt;/span&gt; languages&lt;/a&gt; ranges from 139 to 31 keywords. Haskell has just 20!&lt;/p&gt;
&lt;p&gt;And the more I use the language, the more it strikes me as being ruthlessly consistent. Take functions for example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="haskell"&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nominally you can read this as a function called &lt;code&gt;add&lt;/code&gt; that takes two &lt;code&gt;Int&lt;/code&gt; parameters and returns an &lt;code&gt;Int&lt;/code&gt;. Except it isn&amp;#8217;t. It&amp;#8217;s a function that takes an &lt;code&gt;Int&lt;/code&gt; and returns another function that takes an &lt;code&gt;Int&lt;/code&gt; and returns an &lt;code&gt;Int&lt;/code&gt;! Which means you can do this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="haskell"&gt;&lt;span class="nf"&gt;plusOne&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="nf"&gt;plusOne&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;ve defined a &lt;code&gt;plusOne&lt;/code&gt; function by fixing the first parameter of &lt;code&gt;add&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;, which returns a function that will always add 1 to whatever value is passed to it. By applying the same principle again we have a function that takes no arguments and returns an &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="haskell"&gt;&lt;span class="nf"&gt;two&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plusOne&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This concept is one of the reasons why I&amp;#8217;m struggling with Functors. It seems mind numbingly simple to me and yet so mind bogglingly powerful at the same time!&lt;/p&gt;
&lt;p&gt;And that is the paradox I keep banging my head against!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/YhVhKP3Sl6k" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/27/is-haskell-actually-simple.html</feedburner:origLink></entry>
 
 <entry>
   <title>Haskell's type system made me cry</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/AKKBuiqryM8/haskells-type-system-made-me-cry.html" />
   <updated>2010-11-26T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/26/haskells-type-system-made-me-cry</id>
   <content type="html">&lt;p&gt;My functional programming with Haskell journey continues and every time I think I understand something, I discover there&amp;#8217;s another layer of complexity underneath the one I just peeled off! There are so many metaphors that spring to mind that I&amp;#8217;m just going to avoid them all!&lt;/p&gt;
&lt;p&gt;What I&amp;#8217;ve found so far is that I typically go through three or four stages of learning functional concepts. In the first stage I don&amp;#8217;t understand it at all. In the second stage I start learning matched pairs of input and results, so I can start to use the concept but I don&amp;#8217;t understand how the input is transformed to the output. In the third stage I start to get that understanding of how it works as well as what it does. And in the fourth stage I realise how much more there is that I don&amp;#8217;t understand yet!&lt;/p&gt;
&lt;p&gt;This week I really started to understand type classes and monads, only to discover that monads are just the tip of the iceberg. My brain then started to melt as I went back to stage one and two with functors and applicative functors!&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s also beginning to dawn on me just how amazing the Haskell type system is. One of my friends once said that Haskell&amp;#8217;s type system made him cry. Not tears of pain but tears of joy at how elegant it is!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/AKKBuiqryM8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/26/haskells-type-system-made-me-cry.html</feedburner:origLink></entry>
 
 <entry>
   <title>Tackle the technical debt first</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/WEmpA21aZYM/tackle-technical-debt-first.html" />
   <updated>2010-11-23T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/23/tackle-technical-debt-first</id>
   <content type="html">&lt;p&gt;In my last post I talked about the large refactoring I am doing. One of the reasons that this is a large refactoring is because I have been putting it off. I wanted to deliver something to the customer. I kept telling myself that if I just went with what I had I&amp;#8217;d soon have something to give them and then I would have some breathing room to refactor. Of course thats a complete fallacy!&lt;/p&gt;
&lt;p&gt;What I actually did was rack up technical debt. I kept adding more code that was dependent on &lt;span class="caps"&gt;API&lt;/span&gt; that I knew needed to be refactored. That meant the new code would also have to be refactored when the &lt;span class="caps"&gt;API&lt;/span&gt; changed. The net result is that I still wasn&amp;#8217;t able to handover what I wanted when I wanted to, and now I am having to take a couple of days to perform this refactoring, which is delaying the delivery even more!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve made this mistake before and I should have known better, but the pressure I (it wasn&amp;#8217;t even the customer) was putting myself under to deliver got the better of me this time. Hopefully I learned from my mistake. I think I&amp;#8217;ll print the quote by basketball coach John Wooden: &amp;#8220;If you don&amp;#8217;t have time to do it right, when will you have time to do it over?&amp;#8221; and pin it on the wall of my cubicle!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/WEmpA21aZYM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/23/tackle-technical-debt-first.html</feedburner:origLink></entry>
 
 <entry>
   <title>The great thing about standards...</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/KegYD3pbC-8/the-great-thing-about-standards.html" />
   <updated>2010-11-22T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/22/the-great-thing-about-standards</id>
   <content type="html">&lt;p&gt;… is that there&amp;#8217;s so many of them to choose from. They&amp;#8217;re like Java frameworks, everyone has got one! I guess it&amp;#8217;s down to control. People don&amp;#8217;t want to invest in something that they don&amp;#8217;t have control over, so they create another standard, manage to get it ratified by some standards body, and then claim that they are standards compliant. But if we&amp;#8217;re not all using the same standard, how much value does the standard have?&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve spent a considerable amount of time this weekend creating alternative versions of the &lt;a href="http://www.codingbynumbers.com/"&gt;Coding By Numbers&lt;/a&gt; podcast. We have been using the &lt;a href="http://en.wikipedia.org/wiki/Advanced_Audio_Coding"&gt;&lt;span class="caps"&gt;AAC&lt;/span&gt;&lt;/a&gt; format since it gives you the best bang for your buck in terms of quality versus size, but we&amp;#8217;ve had a bunch of feedback asking for an &lt;a href="http://en.wikipedia.org/wiki/MP3"&gt;MP3&lt;/a&gt; version because not all media players support &lt;span class="caps"&gt;AAC&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;A few weeks ago, my co-host &lt;a href="http://dalts.net/"&gt;Steve&lt;/a&gt; was fortunate enough to meet with &lt;a href="http://stallman.org/"&gt;Richard Stallman&lt;/a&gt; from the &lt;a href="http://www.fsf.org/"&gt;Free Software Foundation&lt;/a&gt;, who won&amp;#8217;t listen to any digital audio unless it is recorded in an open format such as &lt;a href="http://www.vorbis.com/"&gt;Ogg Vorbis&lt;/a&gt;. In fact he thinks we shouldn&amp;#8217;t be offering anything but open formats and he&amp;#8217;s probably right, but if people are having problems with &lt;span class="caps"&gt;AAC&lt;/span&gt; support, can you imagine the problems people would have if we only offered Ogg Vorbis?&lt;/p&gt;
&lt;p&gt;So there&amp;#8217;s three standards that we now offer for the podcast, but those aren&amp;#8217;t the only standards we could choose from. There&amp;#8217;s also &lt;a href="http://flac.sourceforge.net/"&gt;&lt;span class="caps"&gt;FLAC&lt;/span&gt;&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/MP2"&gt;MP2&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/WAV"&gt;&lt;span class="caps"&gt;WAV&lt;/span&gt;&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Windows_Media_Audio"&gt;&lt;span class="caps"&gt;WMA&lt;/span&gt;&lt;/a&gt; and that&amp;#8217;s before we even start on the voice specific codecs we could use! And there&amp;#8217;s so little real difference between them that you have to question why they all exist. Perhaps standards would be better controlled by a benevolent dictator than committees?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/KegYD3pbC-8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/22/the-great-thing-about-standards.html</feedburner:origLink></entry>
 
 <entry>
   <title>Tackling big refactoring jobs</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/gNgQ8JQJa7I/tackling-big-refactoring-jobs.html" />
   <updated>2010-11-22T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/22/tackling-big-refactoring-jobs</id>
   <content type="html">&lt;p&gt;For the first time last week, I actually used a spreadsheet to keep track of a large refactoring that I needed to complete. We&amp;#8217;re not talking about a huge project, less than sixty classes in total, but they needed to be broken into three projects, and a number of the classes were going to disappear altogether as their functionality is absorbed into other classes. The two additional projects are going to be simple libraries that can be re-used, and the original project will retain the domain specific tests and configuration and have dependencies on the two new libraries.&lt;/p&gt;
&lt;p&gt;The spreadsheet itself isn&amp;#8217;t anything complicated. It has the following columns:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Class Name&lt;/li&gt;
	&lt;li&gt;Existing Package&lt;/li&gt;
	&lt;li&gt;Target Project&lt;/li&gt;
	&lt;li&gt;Target Package&lt;/li&gt;
	&lt;li&gt;Target Class&lt;/li&gt;
	&lt;li&gt;Completed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By setting filters on each of the columns and using some conditional formatting, I was able to manipulate the view to narrow the scope to the specific set of tasks I was working on or get a broad overview of where I was up to. It enabled me to take small steps and keep the codebase running whilst I was refactoring, which has usually been my downfall!&lt;/p&gt;
&lt;p&gt;The day to day refactoring I normally do is small enough to be held in my head and larger ones usually cause me some level of grief before they are completed, which is why I decided to take different approach this time around. What I found is that by taking the time to lay everything out first, I could see what needed to be done and in which order. It goes to prove that &amp;#8220;just enough&amp;#8221; planning goes a long way!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/gNgQ8JQJa7I" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/22/tackling-big-refactoring-jobs.html</feedburner:origLink></entry>
 
 <entry>
   <title>Dead trees are dead to me</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/Pb5brpM-ieQ/dead-trees-are-dead-to-me.html" />
   <updated>2010-11-19T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/19/dead-trees-are-dead-to-me</id>
   <content type="html">&lt;p&gt;I haven&amp;#8217;t bought a dead tree version of a book for years. If it&amp;#8217;s not available as either an ebook or an audiobook then I don&amp;#8217;t buy it. The same goes for music, and when the film industry realises that &lt;span class="caps"&gt;DRM&lt;/span&gt; is a fallacy, I&amp;#8217;ll be able to do the same with video too.&lt;/p&gt;
&lt;p&gt;Ideally I want to have my entire collection of books with me wherever I go, but not just books. I want to take my music and video collection too. The iPhone kickstarted a revolution in convergence devices that go a long way towards making this possible. Whilst I can&amp;#8217;t carry my entire music and video collection on my phone because they are too large, I can carry my favourites and still have enough space for all my ebooks.&lt;/p&gt;
&lt;p&gt;Recently I&amp;#8217;ve encountered a couple of situations where my phone doesn&amp;#8217;t suffice though. I write a lot of notes on paper (or 3&amp;#215;5 index cards) and they are prone to getting lost or recycled accidentally. For this the phone keyboard is too small, and I&amp;#8217;m not sure whether I would be more comfortable with a pen or stylus over a keyboard anyway. I also started playing the guitar again and printing guitar tab is a waste of paper and often difficult to read. Again the phone is too small to display this type of content effectively.&lt;/p&gt;
&lt;p&gt;I thought about getting an eReader like the Kindle or Nook to address this issue, but I&amp;#8217;m not convinced they will provide everything I need. I think they would be fantastic for replacing paper content, but I&amp;#8217;m not so sure about the note taking, even though the Kindle has a physical keyboard and the Nook has a virtual keyboard that would fill an iPhone screen.&lt;/p&gt;
&lt;p&gt;The elephant in the room is the iPad. It can do everything my phone can do but has a bigger screen. The battery life isn&amp;#8217;t as good as an eReader and the screen will get full of fingerprints, but it will do everything I want. When it came out, I said I couldn&amp;#8217;t see a need for one in my life because it didn&amp;#8217;t solve any problems for me. Then I chuckled to myself as I saw lots of people buy them, play with them for two weeks and then struggle to figure out what they were going to use it for! Now I do have a use for a 10” iPhone I feel like a bit of a dummy. I hate it when Apple are right!&lt;/p&gt;
&lt;p&gt;Even so, given my feelings towards Apple right now though, I am loathed to give them more of my hard earned cash. The only semi-viable alternative I have found is the Archos 10 internet tablet. There are plenty of cheap Chinese rip offs of the iPad, but I&amp;#8217;ve used Archos devices before and they were very good quality. Physically and technically it has very similar specifications to the iPad but it runs the Android 2.2 Froyo operating system. Given that Android phones have similar capabilities to an iPhone, I figure an Android tablet must have similar capabilities to an iPad!&lt;/p&gt;
&lt;p&gt;Only time (and finances) will tell whether I end up with an eReader, an iPad or another tablet device, but I wouldn&amp;#8217;t be surprised if one of them turned to be my next gadget purchase, so I can remove more dead trees from my life!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/Pb5brpM-ieQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/19/dead-trees-are-dead-to-me.html</feedburner:origLink></entry>
 
 <entry>
   <title>What's the value of free?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/rtc5NHSJlgo/whats-the-value-of-free.html" />
   <updated>2010-11-16T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/16/whats-the-value-of-free</id>
   <content type="html">&lt;p&gt;I was looking something up on &lt;a href="http://www.wikipedia.org/"&gt;Wikipedia&lt;/a&gt; when I saw this &lt;a href="http://wikimediafoundation.org/w/index.php?title=WMFJA1/AU"&gt;banner&lt;/a&gt; containing an appeal from Jimmy Wales for donations to the WikiMedia Foundation. It made me question how much we take services like Wikipedia for granted? If you decide that you should donate, how much would you give? How do you but a value on a free service?&lt;/p&gt;
&lt;p&gt;I have no problem discerning the value proposition with the &amp;#8216;&lt;a href="http://en.wikipedia.org/wiki/Freemium"&gt;Freemium&lt;/a&gt;&amp;#8217; services like &lt;a href="http://www.lastpass.com"&gt;LastPass&lt;/a&gt;, where the &amp;#8220;extra&amp;#8221; value I get from my $1/month are listed in bullet points before I hand over my money. However in this case you don&amp;#8217;t get any &amp;#8220;extra&amp;#8221; value in exchange for your cash. There is the possibility of less value being delivered if you don&amp;#8217;t make a donation, but that&amp;#8217;s not a certainty either.&lt;/p&gt;
&lt;p&gt;So how much should you donate? Perhaps it should be the cost of a reasonable &amp;#8220;dead tree&amp;#8221; encyclopaedia? On the other hand if every user gives a nominal $1 donation, it would raise $400,000,000, which I think would see them through for a while!&lt;/p&gt;
&lt;p&gt;Of course, just like free and open source software, there is more than one way to contribute. You could also contribute with your time, by adding, editing or reviewing articles.&lt;/p&gt;
&lt;p&gt;I decided that I&amp;#8217;d like Wikipedia to stick around, so I&amp;#8217;ll make a small donation and start contributing where I can. If you use it, what will you do?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/rtc5NHSJlgo" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/16/whats-the-value-of-free.html</feedburner:origLink></entry>
 
 <entry>
   <title>Play in your own sandbox</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/pC80qB58Q68/play-in-your-own-sandbox.html" />
   <updated>2010-11-15T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/15/play-in-your-own-sandbox</id>
   <content type="html">&lt;p&gt;Following on from my previous post, one of the other things I always strive to do from the outset of a project, is ensure that everyone has their own sandbox to play in. Every developer (and the CI machine) should be able to run the project independently of each other, without any reliance on common resources such as application servers or database instances.&lt;/p&gt;
&lt;p&gt;In previous projects that has always been fairly easy because the projects were either Java desktop or web applications using free and open source software. Right now I am spending a small amount of my time helping out a ColdFusion project. I thought it was going to be painful and expensive to create a sandbox for them but actually, thanks to some friendly developer licensing, I don&amp;#8217;t think it&amp;#8217;s going to be such an issue.&lt;/p&gt;
&lt;p&gt;What I want is for each developer to be able to launch their own their own test environment, which means running ColdFusion in a JRun instance with a &lt;span class="caps"&gt;SQL&lt;/span&gt; Server database that always starts in a known state. Adobe kindly provide free developer licenses for ColdFusion and JRun as do Microsoft for &lt;span class="caps"&gt;SQL&lt;/span&gt; Server, so licensing isn&amp;#8217;t an issue.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve already spent a little bit of time getting an Ant script together with a tool called MXUnit to give them a way of running unit tests against their code using a central server, so that is our starting point. My end goal is to have the Ant script launch all the services and execute the tests locally, thereby removing the dependency on the shared resource. I&amp;#8217;ll share any lessons learned here.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/pC80qB58Q68" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/15/play-in-your-own-sandbox.html</feedburner:origLink></entry>
 
 <entry>
   <title>Click. Click. Build.</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/FEcf53EQc_k/click-click-build.html" />
   <updated>2010-11-15T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/15/click-click-build</id>
   <content type="html">&lt;p&gt;These days, the first thing I do whenever I start a new project is figure out how to build it. It&amp;#8217;s a lesson I learned from &lt;a href="http://pragprog.com/titles/prj/ship-it"&gt;Ship It!&lt;/a&gt; by the &lt;a href="http://pragprog.com/"&gt;Pragmatic Programmers&lt;/a&gt; and a habit that I have gotten into.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not talking about clicking the &amp;#8220;build&amp;#8221; button in the &lt;span class="caps"&gt;IDE&lt;/span&gt; either. I&amp;#8217;m talking about a build that can be run independently on any machine, preferably with a single checkout from the version control system then a single command. If you can do that, then setting up new development machines and/or continuous integration builds is a cinch!&lt;/p&gt;
&lt;p&gt;Sounds great, but how do you do it? I&amp;#8217;ve only really got experience of doing it with Java projects, although they included a lot of &lt;span class="caps"&gt;JNI&lt;/span&gt; code and I was able to include that too.&lt;/p&gt;
&lt;p&gt;First up, you need to decide on a build tool. It could be as simple as a batch file but my current tool of choice is &lt;a href="http://maven.apache.org/"&gt;Maven&lt;/a&gt;. I&amp;#8217;ve also used &lt;a href="http://ant.apache.org/"&gt;Ant&lt;/a&gt; in the past and I&amp;#8217;m looking at &lt;a href="http://gradle.org/"&gt;Gradle&lt;/a&gt; for future builds. The reason I switched to Maven was for it&amp;#8217;s dependency handling and reporting, and now it&amp;#8217;s well integrated into the popular Java IDEs, meaning your developers can choose their favourite.&lt;/p&gt;
&lt;p&gt;Once you&amp;#8217;ve got a build tool, you need to ask yourself what you files do you need to build your project? Obviously the source code and build script will be needed but what about resource files, test environments or any other tools that assist with the build. In the past I&amp;#8217;ve taken this to the extreme of checking in a copy of the build tool itself and even the &lt;span class="caps"&gt;JDK&lt;/span&gt;. This meant that the only thing you needed to set up a new developer machine was a copy of Subversion, everything else came from the version control system!&lt;/p&gt;
&lt;p&gt;The only exception to this rule were the dependencies that I mentioned. When we were using Ant, our projects had a ‘lib&amp;#8217; folder and the dependencies were checked in with the code. With Maven, we set up our own internal repository and shared the dependencies from there. However if you&amp;#8217;re going to do this you need to make sure that your Maven repository is backed up with the same frequency as your source code repository!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/FEcf53EQc_k" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/15/click-click-build.html</feedburner:origLink></entry>
 
 <entry>
   <title>Oracle, the best thing to happen to OpenJDK?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/2X5n4qFt8_Y/oracle-the-best-thing-for-openjdk.html" />
   <updated>2010-11-14T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/14/oracle-the-best-thing-for-openjdk</id>
   <content type="html">&lt;p&gt;I can&amp;#8217;t believe I am writing this, but could Oracle be the best thing to happen to OpenJDK? I know that writing 30 posts in 30 days is driving me a little crazy, but have I really lost that many marbles before the halfway point? Just how can the company that is being &lt;a href="http://www.businessweek.com/news/2010-07-29/oracle-sued-by-u-s-in-case-claiming-overcharges.html"&gt;sued by the US government&lt;/a&gt; for their alleged dishonesty be doing good things with such an indispensable open source project?&lt;/p&gt;
&lt;p&gt;Well, despite my many misgivings about the &lt;a href="http://blogs.oracle.com/javaone/2010/09/plan_b_wins.html"&gt;delays&lt;/a&gt; to all the interesting content in JDK7, their willingness to take the flak and do what is necessary to steady the ship shows they have the guts to make tough decisions. Sun kept promising but never really delivered. If Oracle start delivering regularly then I&amp;#8217;ll be less critical of the additional delays to JDK7.&lt;/p&gt;
&lt;p&gt;They&amp;#8217;ve also persuaded &lt;a href="http://www-03.ibm.com/press/us/en/pressrelease/32708.wss"&gt;&lt;span class="caps"&gt;IBM&lt;/span&gt;&lt;/a&gt; and &lt;a href="http://www.apple.com/pr/library/2010/11/12openjdk.html"&gt;Apple&lt;/a&gt; to join the OpenJDK effort, something which Sun never managed to do. This brings all the major &lt;span class="caps"&gt;JDK&lt;/span&gt; vendors together in one place and hopefully we will see the best features of each of the &lt;span class="caps"&gt;JDK&lt;/span&gt; implementations (&lt;span class="caps"&gt;IBM&lt;/span&gt;, Oracle/&lt;span class="caps"&gt;BEA&lt;/span&gt;, Oracle/Sun and Apple) being merged into the open source offering.&lt;/p&gt;
&lt;p&gt;The only question that still nags in the back of my mind is their motive. Whilst it all seems rosy on the surface, persuading &lt;span class="caps"&gt;IBM&lt;/span&gt; to back OpenJDK instead of Apache Harmony could have an ulterior motive. Oracle are attempting to &lt;a href="http://www.reuters.com/article/idUSTRE67B5G720100813"&gt;sue Google&lt;/a&gt; over the use of Java in Android, and which class libraries do you suppose Android uses? You guessed it, Apache Harmony&amp;#8217;s! By getting &lt;span class="caps"&gt;IBM&lt;/span&gt; to switch to OpenJDK, it further isolates Google.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not quite ready to believe that is a co-incidence yet!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/2X5n4qFt8_Y" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/14/oracle-the-best-thing-for-openjdk.html</feedburner:origLink></entry>
 
 <entry>
   <title>Is Apple an abusive partner?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/_15o81qWnzY/is-apple-an-abusive-partner.html" />
   <updated>2010-11-14T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/14/is-apple-an-abusive-partner</id>
   <content type="html">&lt;p&gt;I have a dilemma. I love Apple products. I love the hardware. I love the software. I love the presentation. I love that their products are &amp;#8220;friendly&amp;#8221;. But I also see an ugly side to Apple. The side that is cold, ruthless and oppressive.The side that decides what is good for it&amp;#8217;s customers and what isn&amp;#8217;t. Do I want to continue is a relationship with a partner that gives me beautiful things but makes all my decisions for me?&lt;/p&gt;
&lt;p&gt;Alarm bells started ringing when Apple started making arbitrary decisions about approvals to the App Store. &lt;a href="http://techcrunch.com/2009/07/27/apple-is-growing-rotten-to-the-core-and-its-likely-atts-fault/"&gt;Blocking Google Voice&lt;/a&gt; was a big mental hurdle for me. Apple&amp;#8217;s excuse that it replicated functionality that already existed in the incumbent phone application seemed to be stretching the truth.&lt;/p&gt;
&lt;p&gt;The next warning was &lt;a href="http://daringfireball.net/2010/04/iphone_agreement_bans_flash_compiler"&gt;section 3.3.1&lt;/a&gt; of the &lt;span class="caps"&gt;SDK&lt;/span&gt; license, which prevented anyone from using anything other than sanctioned programming languages to create applications for iOS devices. This sent them into a bitter war with Adobe. Apple had already refused to allow Flash into iOS, prompting Adobe to invest in cross compiling to native iOS devices. Almost antagonistically, Apple introduced the new restriction just before Adobe launched their new Creative Suite!&lt;/p&gt;
&lt;p&gt;The latest slap in the face was the announcement to &lt;a href="http://developer.apple.com/library/mac/#releasenotes/Java/JavaSnowLeopardUpdate3LeopardUpdate8RN/NewandNoteworthy/NewandNoteworthy.html%23//apple_ref/doc/uid/TP40010380-CH4-SW1"&gt;drop support for Java&lt;/a&gt; from OS X 10.7. It felt like Apple was systematically removing anything but it&amp;#8217;s own technology from their system. Up until now, I liked being in Apple&amp;#8217;s walled garden because things just work there, but when the walls are closing in, it&amp;#8217;s time to find a way out!&lt;/p&gt;
&lt;p&gt;There are some positive signs however. The restrictions in section 3.3.1 &lt;a href="http://www.apple.com/pr/library/2010/09/09statement.html"&gt;have been relaxed&lt;/a&gt; and Apple is going to &lt;a href="http://www.apple.com/pr/library/2010/11/12openjdk.html"&gt;contribute to the OpenJDK effort&lt;/a&gt;, which I think is definitely the &amp;#8220;right thing&amp;#8221; to do. The question is whether these concessions are just to lull us into a false sense of security before the next sucker punch, like the Mac App Store for example?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/_15o81qWnzY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/14/is-apple-an-abusive-partner.html</feedburner:origLink></entry>
 
 <entry>
   <title>Mmmmm... Minty Macbook!</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/tTikuCOK-G8/minty-macbook.html" />
   <updated>2010-11-13T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/13/minty-macbook</id>
   <content type="html">&lt;p&gt;When I started on my current project and got a new developer workstation, I took advantage of an official &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; distribution sanctioned for use within the company. Apart from a few wrinkles with the authentication against the Windows domains, it has been a real pleasure to use, so when I rebuilt my MacBook recently, I decided that I would use &lt;a href="http://www.apple.com/support/bootcamp/"&gt;Bootcamp&lt;/a&gt; and tri-boot it (Max OS X, Windows 7 and Linux).&lt;/p&gt;
&lt;p&gt;I started out with the regular Ubuntu distribution, but it didn&amp;#8217;t seem to work all that well. It certainly wasn&amp;#8217;t a slick as it is on my workstation at work. I was having problems with the trackpad and the wifi adapter in particular. Then someone recommended &lt;a href="http://www.linuxmint.com/"&gt;Linux Mint&lt;/a&gt;, so I scrapped Ubuntu and installed that instead.&lt;/p&gt;
&lt;p&gt;It installed straight away and everything aside from the iSight camera worked immediately. It can access the OS X and Windows 7 partitions and even the MP4 video and MP3 audio codecs were installed so I could play back my media from my iTunes library.&lt;/p&gt;
&lt;p&gt;On top of that, it performs snappily and it still has the excellent package management of Ubuntu. I was even more pleasantly surprised when it paired with my iPhone and connected to the internet on the first attempt!&lt;/p&gt;
&lt;p&gt;So if you&amp;#8217;ve been thinking about giving Linux a whirl, then Linux Mint is a really good, low fuss candidate.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/tTikuCOK-G8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/13/minty-macbook.html</feedburner:origLink></entry>
 
 <entry>
   <title>Meetings are toxic</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/EfOMKKIuGJ8/meetings-are-toxic.html" />
   <updated>2010-11-12T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/12/meetings-are-toxic</id>
   <content type="html">&lt;p&gt;That is the title of a chapter in Jason Fried and David Heinemeier Hansson&amp;#8217;s (&lt;a href="http://37signals.com/"&gt;37signals&lt;/a&gt;) book, &lt;a href="http://37signals.com/rework/"&gt;Rework&lt;/a&gt;, and I have to admit that I agree with them. I&amp;#8217;ll also admit that I&amp;#8217;m a little jaded by the number of unproductive meetings that I&amp;#8217;ve attended in my career, so my view may be tainted!&lt;/p&gt;
&lt;p&gt;One of the key points in the book is that meetings are terribly expensive. A one hour meeting between 10 people is a 10 hour meeting. That&amp;#8217;s before you factor in the cost of stopping what your doing, or any preparation work. It&amp;#8217;s at least a day and a half of productivity gone! Sadly most people don&amp;#8217;t think about that when they book meetings.&lt;/p&gt;
&lt;p&gt;There are three problems with most meetings that I attend:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;The wrong people:&lt;/strong&gt; There are usually too many people and often key individuals (decision makers and/or subject matter experts) are missing. What&amp;#8217;s the point of holding a meeting if you can&amp;#8217;t get the information you need and reach a decision?&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Poor facilitation:&lt;/strong&gt; I cannot criticise anybody for not defining a clear agenda, with defined goals/outcomes, and time boxing effectively. I am not very good at it either. At least I&amp;#8217;m cognisant of that fact and try to mitigate it by not calling meetings! I use face to face discussion, phone calls, IM or e-mail instead.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;The length&lt;/strong&gt;: Most of the meetings I attend are at least an hour long. The majority of attendees are bored in half that time, because the outcomes can normally be reached in half the time if the right people are there and the meeting is well facilitated.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I don&amp;#8217;t agree with everything that David Heinmeier Hansson says, but there are some things where I think he is spot on, and this is one of them. Next time you go to book a meeting, please weigh up the cost and think about whether there is a better way to achieve the outcome you want!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/EfOMKKIuGJ8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/12/meetings-are-toxic.html</feedburner:origLink></entry>
 
 <entry>
   <title>Being a good FOSS citizen</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/bEjn1WRLc6c/being-a-good-foss-citizen.html" />
   <updated>2010-11-10T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/10/being-a-good-foss-citizen</id>
   <content type="html">&lt;p&gt;Do you use free and open source software? Do you contribute back? I have to hold my hands up and admit that I have not contributed back as much as I feel I should have and I feel bad about it.&lt;/p&gt;
&lt;p&gt;The obvious way to contribute is with code, be that feature enhancements or bug fixes, but there are many ways in which to contribute back. You can work on documentation or subscribe to the mailing list and help out by answering questions and helping people with problems that you might have already solved. Even evangelizing about free and open source software is contributing in some way, and the one in which I have been most active.&lt;/p&gt;
&lt;p&gt;However, twice in the last couple of months, I have found and fixed bugs in open source libraries. I depend very heavily on one of those libraries (&lt;a href="http://seleniumhq.org/"&gt;WebDriver&lt;/a&gt;) for my current project and despite the best of intentions, I still haven&amp;#8217;t submitted a patch for the fix. My &amp;#8220;excuse&amp;#8221; is that I haven&amp;#8217;t had the time to create the patch and a unit test example to demonstrate the problem and solution, but let&amp;#8217;s face it that is a poor excuse! If I have the time to learn to use someone else&amp;#8217;s software, and I expect it to be there in the future, then surely I can make the time to send them a fix I&amp;#8217;ve already written?&lt;/p&gt;
&lt;p&gt;So my conscience has finally got the better of me! Just as I committed to blogging once a day for 30 days to kill my procrastination about blogging, I am making a commitment to contributing patches for the fixes I have by the end of the week to kill my procrastination about contributing back too!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/bEjn1WRLc6c" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/10/being-a-good-foss-citizen.html</feedburner:origLink></entry>
 
 <entry>
   <title>Why doesn't everyone strive for better?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/wIjO0OhbCmw/why-doesnt-everyone-strive-for-better.html" />
   <updated>2010-11-09T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/09/why-doesnt-everyone-strive-for-better</id>
   <content type="html">&lt;p&gt;Why don&amp;#8217;t some people want to do better at their jobs? I don&amp;#8217;t understand. I&amp;#8217;m talking people involved in developing software here, but I&amp;#8217;m sure the same problem affects many occupations.&lt;/p&gt;
&lt;p&gt;I had one meeting last week where I made the case &lt;em&gt;very passionately&lt;/em&gt; that people should be actively seeking to improve the things that they find difficult. Sadly I think it fell on deaf ears, but the discussion certainly ruffled a few feathers and acted as a catalyst for other changes that needed to happen!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been discussing this problem with a number of different people recently and they are as baffled as I am. The only consensus of opinion I was able to gather is that people who don&amp;#8217;t want to improve don&amp;#8217;t really care about their craft. Unfortunately most employers are not very good at fostering an environment that inspires people to care either, which leaves the few of us that do care being frustrated by those that don&amp;#8217;t.&lt;/p&gt;
&lt;p&gt;Ordinarily I wouldn&amp;#8217;t post such an opinionated piece and I&amp;#8217;ve sat on this for a number of days. In the end I decided to post something because this issue occupied my mind a lot last week, and the purpose of of this exercise is to record what is occupying my mind. I don&amp;#8217;t expect that it will change anything, but it did make me re-evaluate what I was trying to achieve at work and why, which can only be a good thing!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/wIjO0OhbCmw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/09/why-doesnt-everyone-strive-for-better.html</feedburner:origLink></entry>
 
 <entry>
   <title>Take the red pill...</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/aD6OD6GCRjQ/take-the-red-pill.html" />
   <updated>2010-11-09T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/11/09/take-the-red-pill</id>
   <content type="html">&lt;p&gt;Right now I feel a bit like Neo being confronted by Morpheus and offered the choice of the blue pill or the red pill. Take the blue pill and I can go back to my comfortable world of Java and object orientation. Take the red pill &amp;#8211; I learn Haskell and see how deep functional programming goes!&lt;/p&gt;
&lt;p&gt;In a previous post I mentioned that I am in the process of learning functional programming in Haskell. The exercise this week was to write a monadic parser and what struck me about it was how much I was wrestling to keep a single function in my head. With Java I can hold several classes and the interactions between them in my head, and even do a half decent job with multi-threaded code (I&amp;#8217;m sure &lt;a href="http://blog.tmorris.net/"&gt;Tony&lt;/a&gt; would disagree and he&amp;#8217;s probably right, but for now I am no more disillusioned than most Java programmers).&lt;/p&gt;
&lt;p&gt;I think the part of the reason I struggled is because Haskell code is a lot more dense than Java code i.e. less code does more. The type system in particular, is so rich that trying to keep track of what types were in play at each point in the function was a challenge in itself. Whilst I was working on the exercises, I got to a point where I knew the understanding I needed was just beyond my grasp, and the penny dropped just as I answered the last question!&lt;/p&gt;
&lt;p&gt;It was at that point that I began to understand what one of the functions I had written early on actually did. That enabled me to clean up my code considerably because I had been rewriting the same function over and over in the subsequent questions. That in turn made the code a lot easier to reason about.&lt;/p&gt;
&lt;p&gt;It really shows the importance of understanding a function before you use it. At the end of today&amp;#8217;s lesson we had an interesting discussion about unwittingly misunderstanding code, because we think we understand it when actually we don&amp;#8217;t. Languages like Haskell can reduce the ambiguity which reduces the chance of misunderstanding. Unfortunately, it can also lead to non-understanding for beginners like me, which isn&amp;#8217;t much help either!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/aD6OD6GCRjQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/09/take-the-red-pill.html</feedburner:origLink></entry>
 
 <entry>
   <title>Mixin it up</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/frrOv3Voxco/mixin-it-up.html" />
   <updated>2010-11-05T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2010/11/05/mixin-it-up</id>
   <content type="html">&lt;p&gt;A couple of days ago I talked about using Groovy&amp;#8217;s &lt;code&gt;metaClass&lt;/code&gt; to add a method to the &lt;code&gt;Collection&lt;/code&gt; class at runtime. Today, I used Groovy&amp;#8217;s mixin mechanisms to share common functionality between two classes that don&amp;#8217;t share the same ancestry.&lt;/p&gt;
&lt;p&gt;In my original Java code, one of the classes was actually an inner class of the other. When I converted that code to Groovy I found that Groovy&amp;#8217;s inner class support was a little bit… iffy (at least in the sense that the behaviour is not exactly the same as Java)! So I promoted the inner class to a top level class. That left me with two functions that both classes needed to share.&lt;/p&gt;
&lt;p&gt;The obvious options were copy and paste (over my dead body), try and force a common parent (inheritance), or refactor the shared functions into their own classes (composition). I felt the only reasonable option was composition, but I didn&amp;#8217;t want my new concise code being messed up with lots of indirect method calls! Having used Scala traits before I figured I would look for the Groovy equivalent.&lt;/p&gt;
&lt;p&gt;My first port of call was Groovy&amp;#8217;s &lt;code&gt;mixin()&lt;/code&gt; method, which works like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;gt; $message&amp;quot;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mixin&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    
    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Foo.bar() called&amp;quot;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// prints &amp;quot;&amp;gt; Foo.bar() called&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;log called directly on Foo instance!&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Perfect! Easy to implement, not too difficult to follow, and no (source code) overhead to calling the mixed in methods. I committed the code and was about to get on with the next task when I discovered another mechanism…&lt;/p&gt;
&lt;p&gt;There is an &lt;code&gt;@Delegate&lt;/code&gt; annotation you can place on a field within a class. It triggers an &lt;span class="caps"&gt;AST&lt;/span&gt; transformation which injects the interface of the delegate into the enclosing class, giving me the same net result as the &lt;code&gt;mixin()&lt;/code&gt; method:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;gt; $message&amp;quot;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Delegate&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    
    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Foo.bar() called&amp;quot;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// prints &amp;quot;&amp;gt; Foo.bar() called&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;log called directly on Foo instance!&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I ended up going with the &lt;code&gt;@Delegate&lt;/code&gt; mechanism because the &lt;span class="caps"&gt;IDE&lt;/span&gt; (IntelliJ &lt;span class="caps"&gt;IDEA&lt;/span&gt; in my case) can resolve references to the delegated methods (because the transformation is applied at compile time) which it couldn&amp;#8217;t do using the &lt;code&gt;mixin()&lt;/code&gt; method (because it is applied at runtime). I imagine therefore, that it makes sense to use &lt;code&gt;@Delegate&lt;/code&gt; on your own classes and &lt;code&gt;mixin()&lt;/code&gt; on other peoples.&lt;/p&gt;
&lt;p&gt;I didn&amp;#8217;t delve into them, but there are more mechanisms available than the two I&amp;#8217;ve highlighted here. There are &lt;code&gt;@Category&lt;/code&gt; and &lt;code&gt;@Mixin&lt;/code&gt; annotations and you can roll your own &lt;span class="caps"&gt;AST&lt;/span&gt; transformations too. They might be the subject of another blog post!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/frrOv3Voxco" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/05/mixin-it-up.html</feedburner:origLink></entry>
 
 <entry>
   <title>Is meta better?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/3h6dcW4gYpg/is-meta-better.html" />
   <updated>2010-11-04T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2010/11/04/is-meta-better</id>
   <content type="html">&lt;p&gt;Yesterday I did my first bit of meta-programming in production code. It wasn&amp;#8217;t anything particularly fancy, but it does extend the functionality of a class (that I didn&amp;#8217;t write) at runtime, to provide an additional function.&lt;/p&gt;
&lt;p&gt;There is a really handy matcher method in the &lt;a href="http://fest.easytesting.org/"&gt;&lt;span class="caps"&gt;FEST&lt;/span&gt;-Assert&lt;/a&gt; library called &lt;code&gt;containsOnly()&lt;/code&gt;, which ensures that two collections have the same contents but doesn&amp;#8217;t care about the order. Now I&amp;#8217;m using &lt;a href="http://spockframework.org/"&gt;Spock&lt;/a&gt;, I&amp;#8217;m trying to stick to the basic Groovy assertions because Spock uses them implicitly, they are easier to read and write, and the output when an assertion fails is excellent:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;collectionA&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;collectionB&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
                   &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The Groovy &lt;span class="caps"&gt;JDK&lt;/span&gt; already adds a whole bunch of useful methods to the stock Java collections, but there isn&amp;#8217;t a &lt;code&gt;containsOnly()&lt;/code&gt; method. However it is easy to provide the function using two of the existing methods:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;containsOnly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;containsAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So I added it by modifying the &lt;code&gt;metaClass&lt;/code&gt; when my code is initialized:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;metaClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;containsOnly&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;containsAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And it works beautifully. The question is whether or not it is better than trying to solve the problem some other way, such as using a proxy class or a utility class to provide the extra function? It would certainly be easier to track where the &lt;code&gt;containsOnly()&lt;/code&gt; method is defined, rather than it appearing by magic as it does with meta-programming (unless you know in advance where the metaClass extension is being done). On the flip side, it takes a lot more code to do the same using a proxy or utility class, and only a proxy would allow me to keep the &lt;span class="caps"&gt;API&lt;/span&gt; I want in this case.&lt;/p&gt;
&lt;p&gt;I guess in the end it&amp;#8217;s a swings and roundabouts argument. What you gain with one you lose with the other. Both introduce some overhead to future maintenance of the code. It&amp;#8217;s just that it might not be obvious to the person that comes after you where that overhead is if you&amp;#8217;re using meta-programming!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/3h6dcW4gYpg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/04/is-meta-better.html</feedburner:origLink></entry>
 
 <entry>
   <title>Follow the types (not the white rabbit)!</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/OLK54rdO2xw/follow-the-types.html" />
   <updated>2010-11-04T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2010/11/04/follow-the-types</id>
   <content type="html">&lt;p&gt;For a while I have been trying to learn &lt;a href="http://www.haskell.org/"&gt;Haskell&lt;/a&gt; as a way of getting my head completely around functional programming. I started with &amp;#8220;&lt;a href="http://www.pragprog.com/titles/btlang/seven-languages-in-seven-weeks"&gt;Seven Languages in Seven Weeks&lt;/a&gt;&amp;#8221;, moved on to &amp;#8220;&lt;a href="http://www.realworldhaskell.org/"&gt;Real World Haskell&lt;/a&gt;&amp;#8221;, and now, &lt;a href="http://blog.tmorris.net/"&gt;Tony Morris&lt;/a&gt; is very kindly donating some of his time to help me and a few other guys to get to grips with the concepts that underpin the language.&lt;/p&gt;
&lt;p&gt;Every week, he sets exercises for us to complete, which involves writing solutions to a bunch of functions that pass the acceptance tests that he supplied. This week we are writing a parser, but the real challenge for me is that none of the tests will pass until all of the functions have been completed. Writing around 20 functions before being able to get any feedback is almost a bigger challenge than writing the functions themselves!&lt;/p&gt;
&lt;p&gt;Tony&amp;#8217;s advice was to &amp;#8220;follow the types&amp;#8221; and I&amp;#8217;m sure he is right. If you follow the type signatures and you have a vague notion of what the function is supposed to do, there are only a limited number of options open to you. The HaskellWiki also says that &amp;#8220;&lt;a href="http://www.haskell.org/haskellwiki/Why_Haskell_just_works"&gt;Once your code compiles it usually works&lt;/a&gt;&amp;#8221;. I&amp;#8217;m halfway through the functions and really hoping that is true! Perhaps I&amp;#8217;ll report back in a future post.&lt;/p&gt;
&lt;p&gt;In any case, I can already say that what I have learned so far has influenced the code I write, and I can only see good things coming from having a better understanding of type theory and functional programming.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/OLK54rdO2xw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/04/follow-the-types.html</feedburner:origLink></entry>
 
 <entry>
   <title>Consoling oneself</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/BEr28BoDc_A/consoling-oneself.html" />
   <updated>2010-11-02T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2010/11/02/consoling-oneself</id>
   <content type="html">&lt;p&gt;The last time I used the &lt;a href="http://groovy.codehaus.org/Groovy+Console"&gt;Groovy Console&lt;/a&gt; (several years ago) it was painful, but now I have to say that it is one of the most useful tools I&amp;#8217;ve come across.&lt;/p&gt;
&lt;p&gt;The thing I like about it is that you have an actual editor, so you can work multi-line statements. It means that you can write small classes and then refine them, which can be difficult in a genuine &lt;span class="caps"&gt;REPL&lt;/span&gt;. And because everything is there right in front of you, when you make the inevitable mistake, you can look back at what you have written and correct it far more easily.&lt;/p&gt;
&lt;p&gt;In fact I&amp;#8217;ve found it so useful, that I&amp;#8217;ve started using it whenever I want to do a quick spike to investigate an idea, or refresh my memory about some &lt;span class="caps"&gt;API&lt;/span&gt;. It&amp;#8217;s also ridiculously easy to embed a console into your application which allows you to access everything that is on your classpath (assuming that Groovy is also on your classpath of course!):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;groovy.ui.Console&lt;/span&gt;

&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setVariable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m using this as a debug aid in my current project, which uses a private in-memory database initialized from another system at startup. With the embedded console, I can run the initialization and then inspect the contents of the database when queries are not behaving as expected, to quickly find and fix the cause of the problem. I&amp;#8217;ve also been able to very quickly prototype new ideas, then cut and paste the code into the application proper, as a starting point for the production code. For me, being able to interactively execute code in my application at runtime has been a massive productivity boost.&lt;/p&gt;
&lt;p&gt;And of course, you don&amp;#8217;t have to programming in Groovy to use it. You could just include the Groovy jar and your Console bootstrap class in a debug build of your Java project!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/BEr28BoDc_A" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/02/consoling-oneself.html</feedburner:origLink></entry>
 
 <entry>
   <title>Groovy baby!</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/5W5jfV5Gt_M/groovy-baby.html" />
   <updated>2010-11-01T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2010/11/01/groovy-baby</id>
   <content type="html">&lt;p&gt;For the last few weeks, I&amp;#8217;ve been using &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; (and the &lt;a href="http://code.google.com/p/spock/"&gt;Spock&lt;/a&gt; &lt;span class="caps"&gt;BDD&lt;/span&gt; framework) on my current project at work, and after initially being reminded why I don&amp;#8217;t like dynamic programming languages, I have to admit that I&amp;#8217;m slowly being converted.&lt;/p&gt;
&lt;p&gt;Those of you who know me (or have listened to the &lt;a href="http://www.codingbynumbers.com/"&gt;podcast&lt;/a&gt;) will know that I am not a big fan of dynamically typed programming languages. I like knowing the fact my code compiles makes some statement about it&amp;#8217;s correctness. Obviously it doesn&amp;#8217;t mean that your code is right, but at least stupid mistakes like typos in names are picked up by the compiler. I&amp;#8217;ve always thought that people accept the compromise of dynamic typing a little too easily.&lt;/p&gt;
&lt;p&gt;In the past I&amp;#8217;ve used Groovy to script builds and deployments, but I&amp;#8217;ve never really used it to write production code before. The reason I have turned to Groovy this time is beacuse I am building a framework that is to be used by a team of testers to write their automated tests. I need something that will allow me to take the Java code I have (which includes a simple &lt;span class="caps"&gt;DSL&lt;/span&gt;), hide all the boilerplate and remove as much punctuation as possible. I evaluated &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; and Groovy and much as I like Scala, I settled on Groovy for two reasons:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Groovy 1.8 includes a new &lt;a href="http://docs.codehaus.org/display/GroovyJSR/GEP+3+-+Command+Expression+based+DSL"&gt;Command Expression Syntax&lt;/a&gt; that really lends itself to the &lt;span class="caps"&gt;DSL&lt;/span&gt; I have created.&lt;/li&gt;
	&lt;li&gt;Groovy is already in use in the organisation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And really it came down to the second of those. Using Scala and the &lt;a href="http://code.google.com/p/specs/"&gt;Specs&lt;/a&gt; &lt;span class="caps"&gt;BDD&lt;/span&gt; framework I am pretty sure that I could create something very similar, but Groovy seems like the more natural fit for the organisation.&lt;/p&gt;
&lt;p&gt;When I first started transitioning the codebase to Groovy I felt a lot of pain, which I have subsequently put down to my attempts to keep the static typing where I could. Things definitely got a lot easier when I jumped off the fence and planted myself firmly in the garden of dynamic typing!&lt;/p&gt;
&lt;p&gt;Another benefit of coming off the fence is that the code has become a lot more concise and less distracting (than the equivalent Java code). For example,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;became&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This example also shows how I&amp;#8217;ve been able to eliminate the use of interfaces and classes as substitutes for closures (action is treated as a closure), and replace generics with dynamics.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not completely sold on the dynamic typing argument yet, but I&amp;#8217;m certainly a lot less sceptical than I was a few weeks ago. Only time will tell whether I become completely comfortable with it!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/5W5jfV5Gt_M" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/11/01/groovy-baby.html</feedburner:origLink></entry>
 
 <entry>
   <title>Captain Sensible at the helm?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/WTjw-O_31FY/captain-sensible-at-the-helm.html" />
   <updated>2010-09-23T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2010/09/23/captain-sensible-at-the-helm</id>
   <content type="html">&lt;p&gt;My initial reaction to the announcements from this year&amp;#8217;s JavaOne was one of sadness, since it&amp;#8217;s clear that Oracle has sapped the pioneering spirit that made Sun special. Having had a few days to reflect on it though, I don&amp;#8217;t think it is as bad as my gut reaction would have me believe.&lt;/p&gt;
&lt;p&gt;Oracle obviously has a clear focus of it&amp;#8217;s intent with Java. It has been through all of Sun&amp;#8217;s projects like Captain Sensible, culling anything that does not align with their goals. I&amp;#8217;m guessing that Java the platform is much more important to them than Java the language, since they&amp;#8217;ve dropped JavaFX Script and the interesting language features from Java 7. It appears that they are happy for the likes of Groovy and Scala to continue innovating in that space.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not surprised that some key individuals left when Oracle took over if my interpretation is correct. It must have felt like the fun police arriving! On the whole though, I think Oracle&amp;#8217;s ruthless business mindset will put Java on a steady course, which means it will be around for a very long time&amp;#8230; I&amp;#8217;m just not sure I&amp;#8217;m all that interested anymore!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/WTjw-O_31FY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/09/23/captain-sensible-at-the-helm.html</feedburner:origLink></entry>
 
 <entry>
   <title>Flash - friend or foe?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/sjUQmIR13dA/flash-friend-or-foe.html" />
   <updated>2010-03-12T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2010/03/12/flash-friend-or-foe</id>
   <content type="html">&lt;p&gt;I attended &lt;a href="http://www.meetup.com/barcampqld/"&gt;Barcamp Gold Coast IV&lt;/a&gt; last weekend which was an awesome experience despite the low turn out. The lack of attendance did prompt me to host a couple of impromptu sessions though, one being a rehash of a blog post I wrote last year about &lt;span class="caps"&gt;RIA&lt;/span&gt; technologies and where I thought it was all heading.&lt;/p&gt;
&lt;p&gt;The most interesting thing was that I conducted a quick straw poll at the start of the session to gauge feeling towards Flash, with surprising results. There were a mix of people in the audience, from accountants to developers, and &lt;strong&gt;every single one of them&lt;/strong&gt; hated Flash! Some because of it&amp;#8217;s use in advertising, some because it hogs resources on their system, but nobody wanted it on their system and some people were actively blocking Flash content from their browsers.&lt;/p&gt;
&lt;p&gt;Now I&amp;#8217;m no fan of Flash but I was not expected such a landslide result! Given that I already thought Flash was under threat from &lt;span class="caps"&gt;HTML&lt;/span&gt; 5, this lack of consumer enthusiasm for it has to be another nail in the coffin.&lt;/p&gt;
&lt;p&gt;Since my last blog post, Google has also been successful in it&amp;#8217;s acquisition of On2, the company from whom the Flash video codec is licensed. Google can now do what they want with that codec, such as open source it or freely license it to other browser vendors, subject to any contractual obligations On2 have with Adobe and Oracle (who license the same codec for JavaFX). Is that the sound of another nail being readied?&lt;/p&gt;
&lt;p&gt;All told I think the developments of the last few months have been positive ones for internet consumers, since it should start to resolve some of the sticky issues with the &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 specification process. But I think it is more bad news for Adobe who, sooner or later, are going to have to stop shoving the Flash runtime down people&amp;#8217;s throats.&lt;/p&gt;
&lt;p&gt;The only runtime people seem to want in their browsers now is the JavaScript runtime and between &lt;a href="http://code.google.com/p/v8/"&gt;Google&lt;/a&gt;, &lt;a href="http://www.apple.com/safari/whats-new.html#performance"&gt;Apple&lt;/a&gt; and &lt;a href="https://wiki.mozilla.org/JavaScript:TraceMonkey"&gt;Mozilla&lt;/a&gt;, we have three great implementations competing against each other. If the &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 committee can reach an agreement on which video format the &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; tag must support, then I don&amp;#8217;t see any reason left for any content provider to use Flash (or &lt;a href="http://www.silverlight.net/"&gt;Silverlight&lt;/a&gt; or &lt;a href="http://www.javafx.com/"&gt;JavaFX&lt;/a&gt;) at all.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/sjUQmIR13dA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2010/03/12/flash-friend-or-foe.html</feedburner:origLink></entry>
 
 <entry>
   <title>Physical media is dead to me!</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/EXib4EXHpWI/physical-media-is-dead-to-me.html" />
   <updated>2009-11-18T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2009/11/18/physical-media-is-dead-to-me</id>
   <content type="html">&lt;p&gt;With the impending move to Australia coming up I decided to rip all of our music and video to the computer and abandon physical media altogether. We have a few hundred CDs and over a hundred DVDs so it wasn&amp;#8217;t a trivial nor insurmountable task to rip them all but the switch away from physical media raises a number of questions.&lt;/p&gt;
&lt;p&gt;The first decision I had to make was which format and quality to use to rip our existing content. I&amp;#8217;ve had a number of conversations with my dad over the last few years about the quality of the encoding versus the quality of the content. The argument basically boils down to this. If there&amp;#8217;s a song or piece of music you really love, you&amp;#8217;ll enjoy listening to it on an AM radio almost as much as you would from a CD. The same goes for your favourite film. You will enjoy watching it on an analogue 14&amp;quot; TV from a &lt;span class="caps"&gt;VCR&lt;/span&gt; almost as much as on a 50&amp;quot; &lt;span class="caps"&gt;LED&lt;/span&gt; backlit 1080p TV from a BluRay disc. The bottom line is that the quality of the content is the most important part of the equation because that&amp;#8217;s where you derive the majority of the enjoyment. So long as the quality of the encoding is good enough, then very little of the enjoyment will be lost.&lt;/p&gt;
&lt;p&gt;Whilst I would have liked to use the open source and patent free &lt;a href="http://flac.sourceforge.net/"&gt;&lt;span class="caps"&gt;FLAC&lt;/span&gt;&lt;/a&gt; or &lt;a href="http://www.vorbis.com/"&gt;Vorbis&lt;/a&gt; codecs to encode the audio, I also wanted to make it as easy as possible to play the files back on as wide a range of devices as possible. That really meant the only available choice was MP3, since &lt;span class="caps"&gt;AAC&lt;/span&gt; is probably better quality for the same size but is not as widely supported. As for quality, I chose 256kbps because I can&amp;#8217;t really hear a difference between that and a CD whereas I sometimes can at 128kbps. With the DVDs, I would have liked to use H.264, but it took 4x longer to encode than standard &lt;span class="caps"&gt;MPEG&lt;/span&gt; 4, and there are still a lot of devices that don&amp;#8217;t support it properly, so I opted for the latter. Ideologically I would have used &lt;a href="http://theora.org/"&gt;Theora&lt;/a&gt; (open source and patent free) but it is very poorly supported.&lt;/p&gt;
&lt;p&gt;Having liberated all of our content from it&amp;#8217;s physical medium, the ongoing challenge is to avoid acquiring any more physical media. With audio this is not too difficult, thanks to the likes of &lt;a href="http://www.amazon.co.uk/"&gt;Amazon MP3&lt;/a&gt; and &lt;a href="http://www.7digital.co.uk/"&gt;7Digital&lt;/a&gt; offering high quality, &lt;span class="caps"&gt;DRM&lt;/span&gt; free MP3 downloads, or if you&amp;#8217;re really pushed, iTunes &lt;span class="caps"&gt;DRM&lt;/span&gt; free &lt;span class="caps"&gt;AAC&lt;/span&gt; downloads. Video however is another matter.&lt;/p&gt;
&lt;p&gt;Just as the music industry has recognized that the only way to beat piracy is to make it easier to buy their content than to steal it, the TV and movie industry start making all the same mistakes! I can&amp;#8217;t find anywhere to legitimately download &lt;span class="caps"&gt;DRM&lt;/span&gt; free video content. The iTunes store offers the best choice, at least in the UK, but all the content is protected by Apple&amp;#8217;s Fairplay &lt;span class="caps"&gt;DRM&lt;/span&gt;, which means I can&amp;#8217;t play it on anything other than iTunes or Apple&amp;#8217;s portable media products. &lt;a href="http://www.tescoentertainment.com/store/browse/filmtvdownloads/"&gt;Tesco&lt;/a&gt; and &lt;a href="https://www.coolroom.com/"&gt;CoolRoom&lt;/a&gt; also offer video download but only in &lt;span class="caps"&gt;WMV&lt;/span&gt; format protected by Microsoft&amp;#8217;s PlaysForSure &lt;span class="caps"&gt;DRM&lt;/span&gt; technology that doesn&amp;#8217;t work on Mac or iPods!&lt;/p&gt;
&lt;p&gt;Case in point is the J. J. Abrams Star Trek movie that has just been released on &lt;span class="caps"&gt;DVD&lt;/span&gt; in the UK this week. I paid to watch this movie at the cinema and I enjoyed it so much I want to pay again to own a copy but I don&amp;#8217;t want any physical media. My first port of call was the iTunes store who have it for &amp;pound;10.99 including extras but with &lt;span class="caps"&gt;DRM&lt;/span&gt;. Next stop, Google. None of the top 10 Google results for &amp;#8220;star trek movie download&amp;#8221; were legitimate links. One of the sponsored links was &lt;a href="http://www.findanyfilm.com/"&gt;FindAnyFilm&lt;/a&gt; which lead me to CoolRoom where I can also download it for &amp;pound;11.99 without the extras but with &lt;span class="caps"&gt;DRM&lt;/span&gt; that won&amp;#8217;t work on anything I own!&lt;/p&gt;
&lt;p&gt;The simplest way for me to get this movie would be to bittorrent it, and I would have the option of a HD version to boot. When will the movie industry realise that it is currently easier to pirate their product than it is to buy it legitimately, and that is why piracy is rife? Why are they making it so hard for us to give them our money? The best legitimate option I have is to buy it on &lt;span class="caps"&gt;DVD&lt;/span&gt; (&amp;pound;8.00 from &lt;a href="http://www.morrisons.co.uk/"&gt;Morrisons&lt;/a&gt;), rip it straight to the computer and place the &lt;span class="caps"&gt;DVD&lt;/span&gt; in storage. That&amp;#8217;s time and effort I would gladly pay an extra &amp;pound;2.99 to avoid if they would just get rid of the stupid &lt;span class="caps"&gt;DRM&lt;/span&gt;!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/EXib4EXHpWI" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/11/18/physical-media-is-dead-to-me.html</feedburner:origLink></entry>
 
 <entry>
   <title>JavaFX - a case of closing the stable door?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/6m8vFzGvx0Y/closing-the-stable-door.html" />
   <updated>2009-11-05T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2009/11/05/closing-the-stable-door</id>
   <content type="html">&lt;p&gt;Since the news that Oracle was buying Sun, I&amp;#8217;ve not been convinced about the future of JavaFX. In the last couple of months I&amp;#8217;ve come to the conclusion that it doesn&amp;#8217;t matter what Sun or Oracle does with JavaFX, it&amp;#8217;s future as an &lt;span class="caps"&gt;RIA&lt;/span&gt; technology looks pretty bleak anyway. And it&amp;#8217;s not alone. Adobe Flash and Microsoft Silverlight are in the path of the same train that is starting to build up a head of steam, namely the combination of &lt;span class="caps"&gt;HTML&lt;/span&gt; 5, &lt;span class="caps"&gt;CSS&lt;/span&gt; 3 and JavaScript. Let&amp;#8217;s take a look at the evidence and see why I have jumped to this conclusion!&lt;/p&gt;
&lt;p&gt;Two of the biggest proponents of the &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 and associated standards are Google and Apple. Let&amp;#8217;s start by looking at their recent behaviour.&lt;/p&gt;
&lt;p&gt;About a year ago, Google launched their Chrome browser with the express intent of creating a platform to deliver &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 applications. A few months ago, they announced Chrome OS, a lightweight operating system whose whole user interface appears to be web based. The next release of their Android operating system for mobile devices is also going to feature a &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 browser. Apple have also been making sure that &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 support is in all their products. Version 4 of their desktop Safari browser supports &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 as does Safari on the iPhone. So they are both doing their utmost to ensure that people can use &lt;span class="caps"&gt;HTML&lt;/span&gt; 5.&lt;/p&gt;
&lt;p&gt;Google has been re-encoding all the YouTube content in H.264 instead of Flash video. &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 includes a &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element which will eventually mean that webpages can include video without the need for additional plugins, like Flash Player for example. Apple&amp;#8217;s iPhone has special support for YouTube so that the H.264 encoded content can be played, again avoiding the need for a Flash plugin. Apple&amp;#8217;s steadfast refusal to allow Flash on to the iPhone is creating a headache for Adobe, as the iPhone becomes ever more popular and web developers are forced to provide Flash free sites (or at least Flash free alternatives) to avoid losing potentially lucrative audiences.&lt;/p&gt;
&lt;p&gt;The only thing slowing down the adoption of &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 is bickering over the fine details. Everyone agrees that there should be a &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; tag, but no-one can agree which codec(s) should be supported in the standard, meaning that all browsers will have to include them. Most of the arguments are over potential patent claims but the three lead contenders are H.264 (an &lt;span class="caps"&gt;ITU&lt;/span&gt;-T standard), Flash Video (proprietary) and Theora (open source). As well as re-encoding YouTube content, Google has also been trying to buy On2, the company that owns the Flash Video codec (also used as the cross platform codec in JavaFX). Sounds to me like they are hedging their bets!&lt;/p&gt;
&lt;p&gt;So two of the most successful technology companies of this millennium would appear to be set on a course to rid the web of Adobe Flash and replace it with standards based &lt;span class="caps"&gt;HTML&lt;/span&gt; 5. If they are making headway against Adobe Flash then the relative minnows of JavaFX and Silverlight stand no chance. Fortunately Sun/Oracle and Microsoft don&amp;#8217;t have as much to lose as Adobe, who generate a significant income from Flash related authoring tools. In my humble opinion, they already ought to be thinking about how to leverage their well known and respected tool chain to produce &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 based solutions. I figure that&amp;#8217;s their best bet to keep their existing customer base if Flash use starts to decline.&lt;/p&gt;
&lt;p&gt;Sadly the same cannot be said for Sun and JavaFX. If it isn&amp;#8217;t going to be used for RIAs, what else can it be used for? There&amp;#8217;s set top boxes of course, but many of them already use &lt;span class="caps"&gt;HTML&lt;/span&gt; under the hood and &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 will probably do most of what they want. BluRay is another possibility, but you&amp;#8217;ve got to figure that the days of physical media are numbered. I think the best bet for JavaFX is as a replacement for the Java language itself. It&amp;#8217;s a modern language with some really nice features and would be a worthy competitor to the likes of Scala as the &amp;#8220;new&amp;#8221; Java. Here&amp;#8217;s hoping!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/6m8vFzGvx0Y" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/11/05/closing-the-stable-door.html</feedburner:origLink></entry>
 
 <entry>
   <title>A week with IntelliJ IDEA</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/YvdGgafICQU/a-week-with-idea.html" />
   <updated>2009-11-02T00:00:00-08:00</updated>
   <id>http://craigaspinall.com/2009/11/02/a-week-with-idea</id>
   <content type="html">&lt;p&gt;Since the start of last week I have been using the beta release of &lt;a href="http://jetbrains.org/"&gt;IntelliJ &lt;span class="caps"&gt;IDEA&lt;/span&gt; Community Edition&lt;/a&gt; and I have to admit I&amp;#8217;m really rather impressed. It hasn&amp;#8217;t been completely plain sailing but I&amp;#8217;m prepared to give it the benefit of the doubt given that it is still in beta and it&amp;#8217;s only fair to expect a few hiccups along the way.&lt;/p&gt;
&lt;p&gt;One of the things I like most about &lt;span class="caps"&gt;IDEA&lt;/span&gt; is it&amp;#8217;s keyboard centric and code centric approach. To call it a glorified text editor is doing it a disservice, but the feeling I get when I&amp;#8217;m using it takes me back to my first job using vi on HP-UX terminals to write software for telephony switches. I don&amp;#8217;t mean that it&amp;#8217;s primitive, far from it, just that it gets back to basics and puts the emphasis back on writing code.&lt;/p&gt;
&lt;p&gt;And yet it provides a tremendous amount of support. The code insight and refactorings are excellent. The inspections help keep you on the straight and narrow as far as good coding practice goes. It&amp;#8217;s Maven and version control support is top notch too. The biggest problem is remembering all the keyboard shortcuts in the mammoth keymap.&lt;/p&gt;
&lt;p&gt;The distraction free, code and keyboard centric approach means that it also works very well on my 13&amp;quot; MacBook screen, and for the first time I can remember, I&amp;#8217;m actually enjoying coding with it&amp;#8217;s limited screen real estate!&lt;/p&gt;
&lt;p&gt;In fact the only thing I&amp;#8217;m missing from &lt;a href="http://netbeans.org/"&gt;NetBeans&lt;/a&gt; is auto closing a line when you enter a semicolon!&lt;/p&gt;
&lt;p&gt;Will it sell more copies? I don&amp;#8217;t know. As I said in my last post, there&amp;#8217;s usually the best option and there&amp;#8217;s the option that&amp;#8217;s good enough. I think IntelliJ is probably the Apple of the Java &lt;span class="caps"&gt;IDE&lt;/span&gt; world, in that the attention to detail in &lt;span class="caps"&gt;IDEA&lt;/span&gt; is much better than Eclipse and NetBeans. But both those IDEs are good enough for the purposes of most developers. If IntelliJ ever make &lt;span class="caps"&gt;IDEA&lt;/span&gt; Ultimate Edition available for free then the others might be in serious trouble though.&lt;/p&gt;
&lt;p&gt;If I were writing web apps every day, then I would definitely trial the Ultimate Edition and if the extra plugins are as good as the Community Edition, I would pay for it out of my own pocket, which is about as big an endorsement as I can give it! I&amp;#8217;m also going to continue using it as my preferred Java &lt;span class="caps"&gt;IDE&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Having said all that I still doubt that this move will significantly increase it&amp;#8217;s market. I hope I&amp;#8217;m wrong, but in the current economic climate especially, people are going to be prepared to compromise!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/YvdGgafICQU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/11/02/a-week-with-idea.html</feedburner:origLink></entry>
 
 <entry>
   <title>Is it good enough or false economy?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/jIrvc0O10t4/is-good-enough-really.html" />
   <updated>2009-11-01T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2009/11/01/is-good-enough-really</id>
   <content type="html">&lt;p&gt;Throughout our lives we are told to do our best. We would all like to buy the best clothes, phone, car or house. We all want our football, rugby or team to be the best, not to mention our kids! But life is also full of compromise, and sometimes we have to make do with whatever is good enough since the best inevitably costs more of something, be that money, time or effort. There&amp;#8217;s also the possibility that you pay the additional cost unnecessarily because the &amp;#8220;good enough&amp;#8221; option would have met your needs.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s start with the device I am using to write this post, the iPhone. I don&amp;#8217;t even need to think about this one. As soon as I saw the first videos of it I knew I was going to buy one as soon as it came out. Two years later and I&amp;#8217;m still using my first generation phone and I&amp;#8217;ve yet to see another phone that is as well made or works as well as an iPhone. I&amp;#8217;ve had my moneys worth out of it many times over. Even when I replace it with the latest model I&amp;#8217;ll be keeping this one and using it as an iPod Touch.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m of a similar mind when it comes to computers. I haven&amp;#8217;t seen another computer as beautifully made as an iMac or MacBook, although the lead over the competition is not as great as with the iPhone, especially with Windows 7 having just been released. I&amp;#8217;ve been very happy with my Mac Mini and MacBook purchases and I think my next purchase will be an iMac, but I am by no means as certain as I am about my next phone!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve also had bad experiences when accepting the compromise and not going for the best option available. I&amp;#8217;ve struggled with my &lt;span class="caps"&gt;DSLR&lt;/span&gt; camera for months because I&amp;#8217;ve been using some no-brand-name 2600mAh rechargeable AA cells that I was previously using with other cameras. The problem is that this camera draws a lot of current and the batteries just can&amp;#8217;t cope. Plus if you leave them in the camera for more than a couple of days, they discharge so quickly that the camera isn&amp;#8217;t ready to use when you pick it up and inevitably you miss the shot you were trying to capture. I&amp;#8217;ve spent a small fortune on different batteries and chargers without any resolution to the problems. Finally I&amp;#8217;ve given in and purchased some Duracell rechargeable batteries instead. So far they have been in the camera for 2 weeks and I haven&amp;#8217;t had a single glitch, so this was clearly a case of false economy.&lt;/p&gt;
&lt;p&gt;But the biggest decision of our lives has been to move to Australia. This is a complex multifaceted decision but at the heart of it lies a desire for the best possible life for our family. The cost is also multifaceted. We are leaving behind friends and family, some of whom we know we will never see again. There&amp;#8217;s also a substantial financial cost on top of the emotional turmoil. We aren&amp;#8217;t there yet and only time will tell whether the cost of leaving the UK, which is a more than good enough place to live, is a price worth paying.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/jIrvc0O10t4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/11/01/is-good-enough-really.html</feedburner:origLink></entry>
 
 <entry>
   <title>The good, the bad, and the GUI</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/zRU2qHwwl3w/the-good-the-bad-and-the-gui.html" />
   <updated>2009-10-27T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2009/10/27/the-good-the-bad-and-the-gui</id>
   <content type="html">&lt;p&gt;As a desktop Java developer, I have access to one of the best desktop user interface libraries around, &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/swing/"&gt;Java Swing&lt;/a&gt;. Like it or loathe it, there isn&amp;#8217;t a cross platform user interface library that even gets close to what Swing can achieve, both in terms of platform fidelity and custom components.&lt;/p&gt;
&lt;p&gt;The biggest problem is that it is painful to use. It has a massive &lt;span class="caps"&gt;API&lt;/span&gt; which inevitably contains inconsistencies and leads to some pretty verbose code. In theory a good &lt;span class="caps"&gt;GUI&lt;/span&gt; editor should help ease the burden but I&amp;#8217;ve never been a huge fan of them. Whilst they promise to save you from writing reams of code (by generating it for you instead) I&amp;#8217;ve always found that somewhere along the way the tool screws up, and then you have to dig through all those reams of ugly machine generated code to fix the problem by hand.&lt;/p&gt;
&lt;p&gt;That was until project &lt;a href="http://wiki.netbeans.org/NBDemoGUIBuilder"&gt;Matisse&lt;/a&gt;, the latest NetBeans &lt;span class="caps"&gt;GUI&lt;/span&gt; editor, came along. Now here is a tool that actually works. So far I have not had to duck under the covers to fix a problem it has made. It allows me to design the user interface quickly and easily, and then expose the components that I need to access from my controller code. So far, so good.&lt;/p&gt;
&lt;p&gt;Except this week I&amp;#8217;m evaluating &lt;a href="http://jetbrains.org/"&gt;IntelliJ&lt;/a&gt; &lt;span class="caps"&gt;IDEA&lt;/span&gt; instead of using &lt;a href="http://netbeans.org/"&gt;NetBeans&lt;/a&gt;. And Matisse uses a .form file to store meta data about the UI forms so it doesn&amp;#8217;t have to infer from the code. That&amp;#8217;s great whilst you stay within the walls of the NetBeans garden, but when you want to go play in the neighbour&amp;#8217;s garden, the .form file can&amp;#8217;t come with you. In fact, IDEA&amp;#8217;s &lt;span class="caps"&gt;GUI&lt;/span&gt; builder has it&amp;#8217;s own .form file that it incompatible with the NetBeans one!&lt;/p&gt;
&lt;p&gt;So I&amp;#8217;m back to being of the opinion that you should hand code your user interface and stay away from &lt;span class="caps"&gt;GUI&lt;/span&gt; builder tools, unless you are really prepared to be locked into a single toolset for the life of the product you are working on.&lt;/p&gt;
&lt;p&gt;By way of an experiment, I converted one of the simpler application windows to use MigLayout, which promises much of the same magic that the GroupLayout does behind the smoke and mirrors of Matisse. It took me about an hour from start to finish but I now have the window behaving the way that I want it to, and with code that is reasonably easy to read, albeit still verbose (at least it is much less verbose than using GridBagLayout).&lt;/p&gt;
&lt;p&gt;Whilst MigLayout  is definitely a compromise, it might just be the best compromise if you&amp;#8217;re stuck with Java the language and have been bitten one too many times by so-called &amp;#8220;helpful&amp;#8221; &lt;span class="caps"&gt;GUI&lt;/span&gt; editors!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/zRU2qHwwl3w" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/10/27/the-good-the-bad-and-the-gui.html</feedburner:origLink></entry>
 
 <entry>
   <title>Chrome gleams on OS X</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/wrfd8_FGtS8/chrome-gleams-on-osx.html" />
   <updated>2009-10-24T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2009/10/24/chrome-gleams-on-osx</id>
   <content type="html">&lt;p&gt;At long last, Google has released an official version of it&amp;#8217;s Chrome browser for Mac OS X. It&amp;#8217;s only a &lt;a href="http://www.google.com/chrome/intl/en/eula_dev.html?dl=mac"&gt;developer preview&lt;/a&gt; but that won&amp;#8217;t stop me from making it my default browser! I&amp;#8217;ve been using Chrome as my default browser on Windows for months and I really like it.&lt;/p&gt;
&lt;p&gt;With the exception of Internet Explorer, the choice of browsers on Windows and Mac is now largely the same. As well as Google Chrome you have Safari, Firefox and Opera plus a slew of niche browsers. What I want from a browser is speed and standards compliance, plus a clean interface that doesn&amp;#8217;t get in my way. Being a developer I&amp;#8217;m more keyboard centric than most users and therefore I don&amp;#8217;t like having to resort to the mouse unnecessarily.&lt;/p&gt;
&lt;p&gt;Up until now, my preferred browser on the Mac has always been Safari. Whilst I use Firefox occasionally it is slower to start, slower to browse and slower to use because it&amp;#8217;s interface is less slick than Safari. I&amp;#8217;m not a plugin junkie so Firefox&amp;#8217;s greatest strength against it&amp;#8217;s competition does little to persuade me. I also found that it used to slow the rest of the system down although this seems less of a problem since V3.5. I like Safari because it is simple and fast, exactly the same reasons why I like Chrome. Except I like Chrome more!&lt;/p&gt;
&lt;p&gt;There are a few features that really make Chrome stand out from the pack. First of all it is the fastest of the browsers that I use. The &lt;a href="http://www2.webkit.org/perf/sunspider-0.9/sunspider.html"&gt;SunSpider&lt;/a&gt; benchmarks show that Safari is about 30% slower than Chrome, and Firefox is over 150% slower!  The &lt;a href="http://v8.googlecode.com/svn/data/benchmarks/v5/run.html"&gt;V8&lt;/a&gt; benchmark tests confirm these results.&lt;/p&gt;
&lt;p&gt;I built Chromium for the Mac a few months ago to try it out, and ran the SunSpider tests against Safari and Firefox too. Since then it appears that Chrome has gotten faster whilst both Safari and Firefox are going in the wrong direction! Both Safari and Chrome also score 100% on the &lt;a href="http://acid3.acidtests.org/"&gt;Acid3&lt;/a&gt; test (not surprising given that they are both WebKit based browsers) but Firefox is still lagging behind at 93%.&lt;/p&gt;
&lt;p&gt;The second thing I think Chrome has got right is it&amp;#8217;s implementation of tabs. I&amp;#8217;m quite a heavy user of tabbed browsing and Chrome&amp;#8217;s tab feel the most natural to use, and once I got over the initial shock of them invading the title bar area, I&amp;#8217;ve grown to really appreciate them.&lt;/p&gt;
&lt;p&gt;But the killer feature for me is the omnibox. One box into which you either type a &lt;span class="caps"&gt;URL&lt;/span&gt; or a search term. I don&amp;#8217;t know what else you would expect from the search company that is famous for it&amp;#8217;s minimal web search interface but in the very first releases the omnibox was a bit of a pain. You would enter a &lt;span class="caps"&gt;URL&lt;/span&gt; and it would incorrectly interpret it as a search term, but now it has lost it&amp;#8217;s rough edges and it is the one thing I miss more than anything when I have to use another browser. There is no need to have a separate search box, either I know the &lt;span class="caps"&gt;URL&lt;/span&gt; I want or I don&amp;#8217;t. If I don&amp;#8217;t enter a recognizable &lt;span class="caps"&gt;URL&lt;/span&gt; then send it to a search engine for me automatically. All other browsers need to implement this feature as soon as possible if they are to stay in the game.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/wrfd8_FGtS8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/10/24/chrome-gleams-on-osx.html</feedburner:origLink></entry>
 
 <entry>
   <title>Talking the talk ain't walking the walk</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/X11RYR6-zZE/talking-the-talk.html" />
   <updated>2009-10-23T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2009/10/23/talking-the-talk</id>
   <content type="html">&lt;p&gt;I was talking to a colleague yesterday about this blog and I realised that I am guilty of talking the talk without walking the walk! One of those people that says they are going to do something and you smile and roll your eyes, because you know it unlikely that they ever will.&lt;/p&gt;
&lt;p&gt;Well all that is changing. My family and I are following one of our dreams and moving from Blighty to Brisbane. We&amp;#8217;ve never even been to Australia and soon we will be residents there. Now our life is an adventure!&lt;/p&gt;
&lt;p&gt;One of my personal ambitions is writing hence this blog. One day I would love to be writing a tech column for a magazine or newspaper, but for now I can self publish whatever I like right here, in my own little corner of cyberspace.&lt;/p&gt;
&lt;p&gt;I have a laundry list of other things that I want to do before I die and I&amp;#8217;m starting to tackle them one by one. Hopefully the new friends I make in Australia will know me as someone who &lt;em&gt;walks&lt;/em&gt; more than he &lt;em&gt;talks&lt;/em&gt;!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/X11RYR6-zZE" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/10/23/talking-the-talk.html</feedburner:origLink></entry>
 
 <entry>
   <title>IntelliJ IDEA is open sourced. Why?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/DxGuJKZVm80/intellij-idea-open-sourced.html" />
   <updated>2009-10-21T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2009/10/21/intellij-idea-open-sourced</id>
   <content type="html">&lt;p&gt;The cool kid, &lt;a href="http://jetbrains.org/"&gt;IntelliJ &lt;span class="caps"&gt;IDEA&lt;/span&gt;&lt;/a&gt;, has finally come to play with the young upstarts, &lt;a href="http://netbeans.org/"&gt;NetBeans&lt;/a&gt; and &lt;a href="http://eclipse.org/"&gt;Eclipse&lt;/a&gt;, in the free and open source Java &lt;span class="caps"&gt;IDE&lt;/span&gt; playground. This is great news but the big question is why now? And why has he left his most shiny toys at home? Is he going to be accepted? Will he be sent packing with a bloody nose? Here&amp;#8217;s my initial thoughts.&lt;/p&gt;
&lt;p&gt;Firstly, let me make some disclaimers:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Sadly, I have never used &lt;span class="caps"&gt;IDEA&lt;/span&gt; before. The last paid &lt;span class="caps"&gt;IDE&lt;/span&gt; I used was JBuilder 7 and since then I have always used Eclipse and NetBeans.&lt;/li&gt;
	&lt;li&gt;I am not against paying for software. I&amp;#8217;ll spend my own money and my employers money on software that does a job right for me.&lt;/li&gt;
	&lt;li&gt;My day job involves mostly Java SE and Swing on the desktop.&lt;/li&gt;
	&lt;li&gt;My day job also means that I work mostly in Windows and Mac OS X, but also in Linux and occasionally Solaris.&lt;/li&gt;
	&lt;li&gt;At home, I only use a Mac.&lt;/li&gt;
	&lt;li&gt;I&amp;#8217;m not sold on massive plugins that do everything for you, at least not to begin with. I like to understand how things work so that I know what the plugin should do and can fix it if it goes wrong!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now I know that before this week I had never used &lt;span class="caps"&gt;IDEA&lt;/span&gt; but it is very highly rated by people whose opinion I respect. I have downloaded and installed it and will post again when I have been using it for a little while and have formed my own opinion of how it compares to NetBeans and Eclipse. For now I&amp;#8217;m assuming that it offers more than both of these and I have to ask myself why JetBrains have open sourced &lt;span class="caps"&gt;IDEA&lt;/span&gt; now?&lt;/p&gt;
&lt;p&gt;My gut reaction is that the commercial Java &lt;span class="caps"&gt;IDE&lt;/span&gt; market is dying. I suspect that &lt;span class="caps"&gt;IDEA&lt;/span&gt; sales are in decline and this is JetBrains last ditch effort to save &lt;span class="caps"&gt;IDEA&lt;/span&gt; as a commercial venture. NetBeans and Eclipse are more than ‘good enough&amp;#8217; for the majority of tasks that most Java developers face, so they have no need or desire to pay for an &lt;span class="caps"&gt;IDE&lt;/span&gt;, regardless of how good it may be. Listening to the &lt;a href="http://javaposse.com/index.php?post_id=537909"&gt;Java Posse interview&lt;/a&gt; with the &lt;span class="caps"&gt;IDEA&lt;/span&gt; evangelist, Roman Strobl, and lead developer, Dmitry Jemerov, JetBrains strategy is to win developers over with the free Community Edition and expect them to upgrade to the Ultimate Edition.&lt;/p&gt;
&lt;p&gt;Will it work? My gut reaction is no, for several reasons.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Borland failed. &lt;span class="caps"&gt;IDEA&lt;/span&gt; may be better than JBuilder ever was (although to listen to &lt;a href="http://joeracer.blogspot.com/"&gt;Joe Nuxoll&lt;/a&gt; on the &lt;a href="http://javaposse.com/"&gt;Java Posse&lt;/a&gt; you would think it was the best Java application ever written!) but Borland was the king of developer tools and it was beaten by Microsoft and the open source alternatives.&lt;/li&gt;
	&lt;li&gt;All the Java EE goodies haven&amp;#8217;t been open sourced, and the majority of Java developers they are trying to appeal to will be writing Java EE applications. If they can&amp;#8217;t switch over wholesale to the Community Edition, why should they even install it. Especially when the equivalent plugins are also free and open source for NetBeans and Eclipse. They can install the trial of the Ultimate Edition and use it for 30 days, but they can do that already and would have done so if they were so inclined.&lt;/li&gt;
	&lt;li&gt;Personally I find it very irritating when software vendors carve up their products so the free (or inexpensive) version has almost enough functionality to be useful but not quite. I think &lt;a href="http://adobe.com/"&gt;Adobe&lt;/a&gt; has hit the sweet spot with &lt;a href="http://www.adobe.com/products/photoshopelwin/"&gt;Photoshop Elements&lt;/a&gt;. It has all the functionality that 80% of Photoshop customers need, and the remaining 20% have to buy the full version. For me, &lt;span class="caps"&gt;IDEA&lt;/span&gt; will probably do everything I want but I am probably in the minority and if it does, I have no need to upgrade anyway.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I hope I&amp;#8217;m wrong and that JetBrains can continue to make money out of &lt;span class="caps"&gt;IDEA&lt;/span&gt;. Software doesn&amp;#8217;t get that much respect without reason. If they can&amp;#8217;t make money on &lt;span class="caps"&gt;IDEA&lt;/span&gt; I hope the make money on their other products because I would hate to see an innovative software vendor like them go out of business. I also hope that they fully open source &lt;span class="caps"&gt;IDEA&lt;/span&gt; if it doesn&amp;#8217;t work out for them. Competition drives innovation and neither NetBeans or Eclipse wouldn&amp;#8217;t be as good as they are if it wasn&amp;#8217;t for &lt;span class="caps"&gt;IDEA&lt;/span&gt; leading the way.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/DxGuJKZVm80" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/10/21/intellij-idea-open-sourced.html</feedburner:origLink></entry>
 
 <entry>
   <title>I'm glad I was wrong!</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/W5Ad2XGqZOg/im-glad-i-was-wrong.html" />
   <updated>2009-06-03T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2009/06/03/im-glad-i-was-wrong</id>
   <content type="html">&lt;p&gt;OK, I admit, I was wrong! Oracle are going to put their weight behind JavaFX and take the fight to Adobe and I&amp;#8217;m glad they are because I think it is a superior technology.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m also really pleased with what they have included in V1.2, primarily:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Proper UI components such as buttons and sliders and text boxes&lt;/li&gt;
	&lt;li&gt;Cross platform support that includes Linux and Solaris (Microsoft might get away with supporting only Windows and Mac OS X and calling it cross platform but Sun can&amp;#8217;t!)&lt;/li&gt;
	&lt;li&gt;Better startup and runtime performance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is what the 1.0 release should have included but better late than never.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/W5Ad2XGqZOg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/06/03/im-glad-i-was-wrong.html</feedburner:origLink></entry>
 
 <entry>
   <title>What will happen to JavaFX under Oracle?</title>
   <link href="http://feedproxy.google.com/~r/Craigaspinallcom/~3/9bCETeKwHhs/what-will-happen-to-javafx.html" />
   <updated>2009-04-24T00:00:00-07:00</updated>
   <id>http://craigaspinall.com/2009/04/24/what-will-happen-to-javafx</id>
   <content type="html">&lt;p&gt;One of the main reasons Oracle is buying Sun is to get it&amp;#8217;s hands on Java. Much of it&amp;#8217;s middleware stack is Java based and having control of Java the language and the default implementation makes sense for them. I don&amp;#8217;t really fear for Java or the &lt;span class="caps"&gt;JVM&lt;/span&gt;. If anything I think it will do better under Oracle&amp;#8217;s stewardship than Sun&amp;#8217;s, just because Oracle get things done. However, that also means that they will be prepared to do what Sun was not, kill off non-profitable areas of the business.&lt;/p&gt;
&lt;p&gt;Java targets three markets: enterprise, desktop, and mobile/embedded. Two of those markets have historically received a lot of attention from Sun and have flourished, namely enterprise and mobile/embedded, whilst until recently the desktop market has been left languishing. Obviously Oracle&amp;#8217;s main interest is in enterprise Java, that&amp;#8217;s the bread and butter of it&amp;#8217;s current business. I think Java&amp;#8217;s ubiquity on mobile phones and the associated licensing revenue means that Oracle will see a viable business unit there and keep it running.&lt;/p&gt;
&lt;p&gt;Unfortunately I don&amp;#8217;t see how they are going to make money out of desktop Java. They can&amp;#8217;t sell or license the technology, most of the best development tools are free and open source, and most enterprise UIs are heading more and more towards being browser based.&lt;/p&gt;
&lt;p&gt;Sun&amp;#8217;s decision to take on Adobe Flash with JavaFX has been driving improvements in whole desktop Java ecosystem. Whilst JavaFX has a lot more to offer than Flash because it runs on the &lt;span class="caps"&gt;JVM&lt;/span&gt;, the user experience is still has a long way to go before it even rivals Flash and Flash already plays very nicely with Java back end systems. meaning it can be used to provide compelling front end UI for Java enterprise systems already. I would be surprised if Oracle chose to continue fighting a battle that many people think was won by Adobe a long time ago.&lt;/p&gt;
&lt;p&gt;The only saving grace for JavaFX might be as part of the mobile phone strategy (although that already has some excellent UI options such as &lt;span class="caps"&gt;LWUIT&lt;/span&gt;) or on the new battlefield that is emerging, televisions and set top boxes. I believe the next release of JavaFX will add the television profile, and at &lt;span class="caps"&gt;NAB&lt;/span&gt; this week, Adobe demo&amp;#8217;d &amp;#8220;Flash for Digital Home&amp;#8221;. Here JavaFX might have a small head start, since every BluRay player already has a &lt;span class="caps"&gt;JVM&lt;/span&gt; capable of running JavaFX, a lot of set top boxes already run Java (I believe), and a lot of the TV manufacturers involved already have a relationship with Sun because they also manufacture mobile phone handsets (Sony, LG, Samsung etc.). Even if this saves JavaFX, it doesn&amp;#8217;t mean they will keep it as a desktop technology.&lt;/p&gt;
&lt;p&gt;The alternative is that they toss it out to the open source community, and whilst there is a lot of interest and enthusiasm, it&amp;#8217;s never going to get gain traction without a major corporation behind it. I hope I&amp;#8217;m wrong. I hope that Oracle keeps JavaFX and pushes it on the desktop as well as on TVs and phones. I wouldn&amp;#8217;t go betting my mortgage on it though!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Craigaspinallcom/~4/9bCETeKwHhs" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://craigaspinall.com/2009/04/24/what-will-happen-to-javafx.html</feedburner:origLink></entry>
 
 
</feed>

