Thursday, October 30, 2008

EasyMock Rock

Writing unit tests = good.

JUnit = good.

However...

Writing unit tests ≠ fun,

especially when dealing with classes that need a lot of stuff to work.

This is especially annoying when you are trying to test a relatively simple class, but it operates on a complex (in terms of data) class. You have to go through a lot of crap just to create the data that your relatively simple class needs to demonstrate that it works properly. This is the difference between unit testing examples in a book and unit tests in the real world.

Enter EasyMock.

Now very mature and well-liked in the Java community, EasyMock creates mock objects automagically and lets you get back to worrying about the class you're actually trying to test. Bravo!

Not only does it take HUGE amounts of pain out of writing JUnit tests, but it also has one of the most beautiful DSL-style APIs I've ever used. When you use it, your code reads like English. It's just a real pleasure to use, and thanks to the gorgeous API, the learning curve is very short.

I think every JUnit test I have written without EasyMock has shortened my life span.

Use EasyMock = Live Longer

Tuesday, October 07, 2008

Sunday, September 14, 2008

Backlog Gone!

It took more than a month, but that 5,000-email backlog is finally gone. It has been replaced by this huge stack of papers in my In Tray, but after 5,000 emails, this doesn't scare me so much. (Maybe it should...)

The feeling of release I feel is difficult to describe. Now I am at Zero-Point, I have a way to know when I've finished my work for the day.

Friday, August 08, 2008

The 5,000 email backlog

First, there was the big important software release - so important that I just had to stop reading email to get it done. Then, there was a trip to Hawaii for a friend's wedding (not that I'm complaining...) Then, another trip, this time to Australia for another friend's wedding and my brother's 30th birthday. And when I got back, all our big important projects were behind schedule and again needed my undivided attention. Not to mention my understandable addiction to playing with my new iPhone.

The result: over 5,000 unread emails in my inbox, and a 20cm-high stack of unread paper in my in tray. Panic sets in...

I am a devout believer in GTD and its core tenet - what Merlin Mann calls "Inbox Zero" - the importance of clearing the inboxes completely. So while some people routinely have hundreds or even thousands of read emails in their inbox with no intention of ever reading them again, for me, all of these emails need processing. It's a major backlog.

According to GTD, what I am supposed to do is go through each email, one by one, and decide what, if anything, needs to be done about it. Normally I would do this starting with the most recent first, because making decisions on the oldest email first might prove to be a waste of time or even a mistake when I see a later follow-up from someone else. But the key idea is to not try to sort or organise them - just grind through them one at a time until they're all gone.

Now, one of the problems with this is that at full-pace, I can process only about 100 emails per hour. If I go any faster than that, it's usually because I'm not really looking at them, so quality "Next Action" decisions aren't being made. Another big problem is that when I look at a recent email that's based on a long-running discussion, often the bottom of the email doesn't contain the full history of the discussion so far, because several email threads have been going on in parallel. So I find myself not being able to determine the next action, because I don't know what the hell everyone's talking about.

I have also read and enjoyed DIT, which includes a very interesting and simple solution to backlogs: Just move it all aside into a folder labelled "Backlog", and start from scratch. The idea is not to ignore all those emails, but to at least establish a baseline of processing everything completely each day, while chipping away at the backlog until it is gone. It's a great motivational approach, since you get the satisfaction of seeing an empty inbox immediately, and you have an easy way of knowing that at least it's not getting worse!

But the problem with the DIT backlog approach is the same as GTD, in that every time you get a new email about something, you don't have an easy way of getting "caught up" on the discussion so far. I've found this to be particularly difficult because I have about 200 projects (some big, many small) running in parallel.

So I'm trying something new, which is forbidden by both GTD and DIT: categorising my backlog.

Last weekend, I went into the office, sat down in front of Outlook for a marathon 12-hour session, and very quickly moved all 5,000+ emails out of my inbox and into folders created for each of the many projects, and for those that weren't specifically related to a project, I made folders for the team/department that it came from. For a long time, I've had my Outlook set up to display messages grouped by conversation thread, so I was able to just check the subject line and make a decision about which folder to stuff with each thread - sometimes moving 20 or 30 messages in one go. I got the whole lot sorted in just under 12 hours, so that's a bit over 400 emails per hour. (Note that the emails still weren't read/processed at this point, so in GTD & DIT terms, nothing had been achieved.)

So this got me the DIT-style "backlog", with the attendant instant gratification of seeing an empty inbox for the first time in weeks. So what was the point of sorting it all into folders? Well, now when I'm processing my inbox for the day, I can take a new conversation thread, move it into the appropriate folder, then read all of the backlog for that project in one go, from oldest to newest, so I am completely "caught up" on all discussions for the project before making any Next Action decisions. I would expect to make several NA decisions for the project, but then I can delete the entire folder because it's completely processed.

So this solves both the problem of not knowing the background of the discussion so far, and as a bonus gives me a nice feeling when I delete that folder, because I know that a big chunk of my backlog has disappeared. Before long, I expect to have few enough folders left in my backlog, that I get inspired to just crank through all of them and be done with it.

Anyway, that's the theory. Now let's see how it works in practice. Should be interesting... At any rate, if this doesn't work I'll just have to declare Email Bankruptcy.

Thursday, August 07, 2008

AppleScript to generate iCal events from email

I just figured out a way to get my work calendar copied onto my iPhone! Yay!!

A bit of background first:

My company doesn't have Exchange, or any other real "groupware". For email, there's just a simple POP server (uuurgh!) and for calendar, they have a custom-built intranet application (huh?!).

The intranet calendar system has a function to send an automatic email alert whenever somebody books an appointment with me in my calendar. The email goes to my work email account, but I have configured an Outlook rule to automatically forward it to my home email address.

When it arrives at my Mac at home (which is always on), I have a Rule in Mail.app which runs the below AppleScript. The script parses the contents of the email, and creates a new event in iCal.

iCal syncs with MobileMe, which in turn syncs with my iPhone. Hooray!!

I haven't used this in anger yet, so I'll be trying it out for the first time tomorrow.

Known limitations:

  • It's highly customised to the format of the emails I get from the intranet calendar system.
  • It doesn't automatically handle recurring events. The first event will be registered, but I have to set the recurring settings myself.
  • It doesn't handle updates or cancellations of events. If an event is moved, it will simply register it again at the new date/time. The old one will still be there.
I'm yet to discover just how long it takes for a new event to finally show up on my iPhone, but based on experience with MobileMe "push", I'm expecting at least a 15~20 minute delay.

How to install:
  1. Launch the application Script Editor and copy the code below.
  2. Save the script somewhere. I saved it in my Documents folder as "MailToCalendar".
  3. Open Mail and select Mail > Preferences... from the menu bar.
  4. Under Rules, click Add Rule.
  5. Give the rule a name (mine is "MailToCalendar").
  6. Create the conditions to recognise the alert emails (mine is Subject Contains "スケジュール予約状況案内").
  7. Add the actions Delete Message, Mark as Read, and Run AppleScript (pointing to the location of the AppleScript you saved).
  8. Click OK. That's it.
Many thanks to AK who gave me a sample AppleScript to get started with! :-)
(*
Make an iCal event from an email
AK  IT Carlow Ireland May 2005
and Will Hains Tokyo August 2008
*)

 

using terms from application "Mail" on perform mail action with messages MessageList for rule theRule -- say "Starting MailToCalendar" set OldDelim to AppleScript's text item delimiters

tell application "Mail" set ThisOne to item 1 of MessageList set TheDetails to content of ThisOne end tell --Mail

set AppleScript's text item delimiters to {"\n"} set TheDetails to text items of TheDetails set TheTopic to "" set TheStart to current date set TheEnd to current date set ThePlace to "" set TheDescription to ""

repeat with ThisDetail in TheDetails set AppleScript's text item delimiters to {"\n"} try -- find the date if "日付:" is in text item 1 of ThisDetail then set AppleScript's text item delimiters to {":"} set TheDateTimeRange to text item 2 of ThisDetail

set AppleScript's text item delimiters to {"-"} set TheStartDateTime to text item 1 of TheDateTimeRange set TheEndDateTime to text item 2 of TheDateTimeRange

set AppleScript's text item delimiters to {" "} set TheStartDate to text item 1 of TheStartDateTime set TheStartTime to text item 2 of TheStartDateTime set TheEndDate to text item 1 of TheEndDateTime set TheEndTime to text item 2 of TheEndDateTime

set AppleScript's text item delimiters to {"/"} set year of TheStart to text item 1 of TheStartDate set month of TheStart to text item 2 of TheStartDate set day of TheStart to text item 3 of TheStartDate set year of TheEnd to text item 1 of TheEndDate set month of TheEnd to text item 2 of TheEndDate set day of TheEnd to text item 3 of TheEndDate

set AppleScript's text item delimiters to {":"} set time of TheStart to (text item 1 of TheStartTime) * hours + (text item 2 of TheStartTime) * minutes set time of TheEnd to (text item 1 of TheEndTime) * hours + (text item 2 of TheEndTime) * minutes

-- say "the start is " & TheStart -- say "the end is " & TheEnd end if --Date

-- find the place if "利用設備:" is in text item 1 of ThisDetail then set AppleScript's text item delimiters to {":"} set TheMeetingRoom to text item 2 of ThisDetail set AppleScript's text item delimiters to {"会議室"} set ThePlace to text item 1 of TheMeetingRoom -- say "place is " & ThePlace end if --Place

-- find the topic if "予定:" is in text item 1 of ThisDetail then set AppleScript's text item delimiters to {":"} set TheTopic to text item 2 of ThisDetail -- say "the topic is " & TheTopic end if --Title

-- find the description if "内容:" is in text item 1 of ThisDetail then set AppleScript's text item delimiters to {":"} set TheDescription to text item 2 of ThisDetail -- say "the description is " & TheDescription end if --Description

on error errStr number errorNumber say "MailToCalendar error! " & errStr end try end repeat --iterate through fields

--set up the event in iCal tell application "iCal" -- say "Will now attempt to register in iCal" tell calendar 2 --CHANGE THIS to sequence number of target calendar set newItem to make new event at end of events with properties {start date:TheStart, end date:TheEnd} set summary of newItem to TheTopic set location of newItem to ThePlace set description of newItem to TheDescription -- say "registered in iCal" end tell --calendar end tell -- iCal

set AppleScript's text item delimiters to OldDelim -- say "finished MailToCalendar" end perform mail action with messages end using terms from

 

Wednesday, July 09, 2008

Hardware Software... aaaarrrgghh!!

Why do hardware manufacturers insist on writing custom software for their installers and driver settings? As long as I have connected things to computers (Win or Mac), I have been stunned and appalled at the inexplicable attempts made by printer, camera, phone, and video card manufacturers to produce the computer-side part of their products.

After all the hard work put in by OS and software vendors to make it easy for them to "fit in" comfortably with the rest of the platform, they apparently just can't keep their crap software developers down.

Take a look at this (admittedly unremarkable) example from Epson:

Never mind that Mac OS X (like Windows) provides a lovely, user-friendly, painstakingly researched and usability-tested solution for software installation - no no no, Epson, like their equally software-braindead competitors, decided it would be much better to pay some software industry rejects gobs of cash to develop a custom installer, packed with confusing screens with too many images, cryptic sub-product names, and custom controls (like what the hell does that progress bar bring to the table???)

Why oh why do they find this necessary? Someone somewhere must feel there is a real business case for this, because it ain't free to develop this excrement. Surely hardware manufacturers have close enough ties with the OS vendors to have been informed of the recommended approach. Why haven't they noticed that almost all software vendors - actual experts in software development - opt for the OS-provided solutions to install their products?

If you are reading this and you know someone who works for a peripherals manufacturer, please take action. Friends don't let friends distribute crap software!