Showing posts with label mail. Show all posts
Showing posts with label mail. Show all posts

Tuesday, 14 July 2009

Expanding the Omniverse

Anybody who's worked with me in about the last 25 years knows that I've been preaching the idea that software craftfolk should never stop learning. Further, I've always believed that learning new languages or tools is one of the easiest ways to accomplish this, keeping the mind supple and open to new ways of doing things. And by and large, I've kept this up, learning enough of a new or long-neglected language to at least be able to read and patch code every two or three months. (You do the math.)

One of the languages that I learned rather early on in its lifecycle is Ruby. (Wikipedia has a rather good article summarizing the history, if you're unfamiliar with it.) Early 1.0-1.4 or thereabouts releases were interesting — they showed the power and promise of the concepts that Ruby is built on, without the bloated inscrutability of, say, perl. As so often has happened, I'd learned just enough to be dangerous, and then got sucked back into the charnel house that is Microsoft Windows development. By the time I had the time and inclination to start messing with Ruby again, an unfortunate thing happened.

Ruby on Rails.

Not that Rails isn't a great tool for building 37signals-type Websites; it clearly is. But it became a victim of its own hype and started being used for everything imaginable — famously including Twitter (a hype explosion in its own right.) Rails was enough to push me — and apparently a good number of other folks — away from Ruby and onto other languages, notably Python. And so I spent the bulk of the next couple of years in PHP, Python, C++, Objective-C, D (another bit of unsung genius), and managed to keep busy.

We developers have a well-known cliché for what drives us to do new things or participate in development projects; "scratching an itch". To scratch an itch in this context is to solve a problem that we ourselves are facing, or to do something that otherwise interests us. What got me motivated to get back up to speed in Ruby wasn't the Rails hype, or even seeing all the nice APIs that Twitter and Repertoire had made available. My problem was a bit simpler and more immediate.

Apple's Mail app started crashing under the load I was giving it. For about a year, I'd had a mail store that averaged about 2 GB and I was getting on the order of 600 to 800 emails a day. I don't mean to be critical of the app; it just wasn't designed to do what I was asking it to, certainly not when sharing 2 GB of RAM with the rest of the system. By the time I migrated away from Mail, I had over 400 filtering rules defined, to slice and dice incoming emails into appropriate folders where I could deal with them as I chose.

In late May, 2009, I up and migrated my email from Apple Mail to Microsoft Entourage. For those of you whose only exposure to Microsoft email software has been Exchange or Lookout! ("Outlook") Express, you're in for a pleasant shock. Entourage runs quite happily in the system as it is (even if I can't run certain other apps at the same time without upgrading RAM), and doesn't give me the maddening ten-minute freezes that were common with Apple Mail as it tried to figure out what to do next. Importing my existing mail store was a breeze. The filtering rules even came along for the ride, and Microsoft's rules editor is a real treat. There was, however, one small problem.

Somehow, the ordering of rules had become scrambled during the import, and after a few weeks of hand-editing to fix the biggest problems, I started looking for a program that would let me import, export, reorder and bulk-edit Entourage's rules. So far, I haven't been able to find one. (If anybody knows of anything useful, please add a comment or email me.) OK, I thought, no problem; nearly everything on the Mac is scriptable. I should just need to learn how to access Entourage's rule set from AppleScript or something similar, then I can write the tool I want. Not trivial, but certainly something that seemed conceptually quite practical.

So I started learning AppleScript, and casting about for tools and sample code that talked to Entourage from AppleScript. While searching, I ran across Matt Neuberg's site. Dr. Neuberg wrote the definitive guide on AppleScript — and then found something that worked better for him: rb-appscript. He's written an online book about it (eventually to be published on dead trees). At this point, I said "ok, let's get started with Ruby again and see what we can do."

If anybody has any pointers or suggestions, please comment. Thanks for reading.

Tuesday, 23 December 2008

Maybe not eating 'crow', specifically, but..... DUCK!!!

As in, "bend over, here it comes again..."

One of the things I have greatly appreciated about the Mac, especially with OS X, is how simple and straightforward software management is, compared to Linux and especially Windows (where every system change is a death-defying adventure against great odds). Operating system or Apple-supplied apps need an update? Software Update is as painless as it gets: the defaults Just Work in proper Mac fashion, but you can set your own schedule, along with a few other options. There is a well-established convention for third-party apps to check for updates via a Web service "phoning home" at app startup; this has been very easy to deal with. Application and file layout is regular and sensible; libraries and resources are generally grouped in bundles at the system or user level. After a few years of DLL hell in Windows and library mix-and-match in Linux, this was shaping up to be a real pleasure.

Then, as some of you know, I updated Mac OS X on my iMac from 10.5.5 to 10.5.6. As expected, that apparently went as smooth as glass. I even blogged about it. XCode worked; MS Office 2008 for the Mac worked; Komodo Edit worked; all my IM clients worked; all seemed customarily wonderful in the omniverse. I even started up Mail; it opened normally and happily downloaded my regular mail and Google mail, just as it had done every day for months. (I didn't actually open any messages then; that will turn out to be important.) Satisfied that everything Just Worked as always, I went back to working on a project for a few hours before turning in for the night.

Next morning, I went through the usual routine. Awake the Mac from hibernation; log in; start Yahoo, MSN and Skype; start Mail; open Komodo; open Web browsers (Safari, Opera and Camino) and I'm ready to get started. First thing...here's an interesting-sounding email message; let's open that up and... *POOF* — Mail crashes.

WTF? It started up just fine; I even got the "Message for you, Sir" Monty Python WAV I'd set Mail to use as my new-mail-received notification. I start Mail again. Picking a different message, I double-click it in the inbox. A window frame opens with the message title, sits empty for a few hundred milliseconds, then Mail goes away again. Absolutely, totally repeatable. Reboot changes nothing. Safe Boot (the Mac equivalent of Windows' "safe mode") changes nothing. The cold fingers of panic stroke my ribs like Glenn Gould at the piano. On a bad-karma scale of 0 to 10, initial reaction is an "O my God"; we're not dead, but we're hurt bad; the karma has definitely run over the dogma. 

The next couple of days are spent using my ISP's Webmail service, and a set of Python scripts I'd previously written to search mailbox contents — Apple Mail, like any sensible email program, adheres to established standard formats. If I'd been using Microsoft Lookout! in a similar situation, I'd have been up the creek.

Finally, I come across some Web-forum items that indicate that GPGMail needs to be updated; if it's not, Mail will crash under OS X 10.5.6 — which is exactly what was happening. (If you're not using GPGMail, GNU Privacy Guard, or any of the various GPG interfaces for Windows such as Enigmail for Mozilla Thunderbird, you don't know how many people are recording and/or reading your email — but if it transits a server in the US or UK, it's guaranteed that it will be.

Installing the upgraded GPGMail bundle was the work of less than two minutes (hint: remove or rename the old bundle before copying the new one over. You probably don't need the insurance, but consider how we got here...). Then start up Mail as usual. It should, once again, Just Work — complete with being able to read and reply to messages, with or without GPG signatures.

OK, so what lessons can we take away from this experience, both as users and developers?

Time Machine may well be the single most rave-worthy piece of software I've touched in 30 years, but it can't (obviously, easily) do everything, and in a crisis, even experienced users may well not want to risk bringing too much (or too little) "back from history". There's definitely a market for addons to TM to do things like "look in my user and system library directories, the Application directory structure, MacPorts, etc., and bring application Foo back to the state it was in last Tuesday morning, but leave my data files as they are." I almost certainly could do that with the bare interface -- but, especially since it was "broken" as part of an OS upgrade, and (with the Windows/Linux experience fresh in mind) not comfortable exploring hidden dependencies... I was without my main email system for three days. Sure, I had workarounds -- that I wouldn't have had if I'd been in a stock Windows situation -- but that's not really the point, is it?

Also, app developers (Mac or other), add this to your "best practices" list: If your software uses any sort of plug-in/add-on architecture, where modules are developed independently of the main app, then you can have dependency issues. The API you make available to your plugin developers will change over time (or your application will stagnate); if you make it easy for them (and your users) to deal with your latest update, you'll be more successful. There's (at least) two ways to go about doing this:

The traditional "brute force" approach. Have a call you can use to tell plugins what version of the app is running, and allow them to declare whether or not they're compatible with that version. Notify the user about any that don't like your new version. For examples of this, see the way Firefox and friends deal with their plugins. Yes, it works, but it's not very flexible; a new version may come out that doesn't in fact modify any of the APIs you care about — which means that the plugin should work even though it was developed against version 2.4 of your app and you're now on 4.2.

Alternatively, a more fine-grained approach. Group your API into smaller, functional service areas (such as, say, address-book interface or encryption services for an email program). Have your plug-in API support a conversational approach.

  1. The app calls into the plugin, asking it which services it needs and what versions of each it supports.
  2. The app parses the list it gets back from the plugin. If the app version is later than the supported range for a specific feature identified by the plugin, add that to a "possibly unsupported" list. (If the app version is earlier than the range supported by the plugin, assume that it's not supported and go on to check the next one.)
  3. If the "possibly unsupported" plugin list is empty, go ahead and continue bringing up the app, loading the plugins normally; you're done with this checklist.
  4. For each item in the "possibly unsupported" list, determine whether the API for each feature required for the plugin has changed since the plugin was explicitly supported. (This is how a plugin for an earlier release, say 2.4, could work just fine with a later version, like 4.2.) If there's no change in the APIs of each feature required by the plugin, remove that plugin from the "possibly unsupported" list.
  5. If any plugins remain in the list, check if there's an updated version of that plugin on the Net. This might be done using a simple web-service-to-database-query on your Web server. If your Web server knows of an update, ask the user for permission to install it. If the user declines, or no upgrade is available, unload the plugin. (You'll check again next time the app is started; maybe there's an update by then.)
  6. Once the status of each plugin has been established, and compatible plugins loaded, finish starting up your app.

Of course, there are various obvious optimisations and convenience features that can be built into this. Any presentation to the user can and likely should be aggregated; "here's a list of the plugins that I wasn't able to load and couldn't find updates for." Firefox and friends are a good open-source example of this. The checks for plugin updates can also be scheduled, so as not to slow down every app startup. This might be daily, weekly, twice a month, whatever; the important thing is to let the user configure that schedule and view a list of plugins that are installed but not active.

As I started this post by saying, I've been very favorably impressed by Mac apps' ease of use (including installation and maintenance). Mail fell down and couldn't get up again without outside assistance; this is unusual. The fact that this was caused by a plugin and that Mail could not detect and work around the conflict just amazes me; I expect more from Apple. I'm not ready to decrease my use of the Mac because this happened — but I am going to pay more attention to how things work under the hood. The fact that I have to even be aware of this -- which is one of the features that hitherto distinguished the Mac from the grubbier Windows and Linux alternatives -- is worrisome.

Again, your comments are welcome.