Suicidal Code
July 13th, 2007Some code is not meant to live forever. In particular, during development phases of projects, it can be very reassuring to know that a particular release of an application will have a short life-cycle, because you’ll be (relatively) assured that users aren’t accidentally running crufty old (development!) versions of the app.
The basic means of accomplishing this is to put a date check in your code that determines if a certain time has come and, if it has, refuses to run any longer. Anecdotally, I can tell you that lots of developers do something like this. But I can also tell you that lots of developers do it the error-prone, labor-intensive way. I did too, until I picked up a great tip from Brian Cooke a while back, that completely automates the process.
The laborious and error-prone method involves manually typing into your code a particular date in the future, and using that date as the test for whether or not to keep running. Brian’s brilliant observation was that the future date is almost always some number of days from “now,” where “now” is the date the code is being compiled. Using a gcc predefined macro, __DATE__, the code can know for itself when it was compiled, and build in an expiration date based on that value.
// Two-week expiration #define EXPIREAFTERDAYS 14 #if EXPIREAFTERDAYS // Idea from Brian Cooke. NSString* nowString = [NSString stringWithUTF8String:__DATE__]; NSCalendarDate* nowDate = [NSCalendarDate dateWithNaturalLanguageString:nowString]; NSCalendarDate* expireDate = [nowDate addTimeInterval:(60*60*24* EXPIREAFTERDAYS)]; if ([expireDate earlierDate:[NSDate date]] == expireDate) { // Run an alert or whatever // Quit! [NSApp terminate:self]; } #endif
By putting code like this in all of your projects, you have at your disposal a simple, error-proof way of releasing a build that will stop working N days from now. When you’re ready to release a non-suicidal version, just change the EXPIREAFTERDAYS preprocessor macro to 0. Nifty, eh?
PS: Thanks to Jon Trainer for inspiring this entry by thinking the idea was cool when I told him about it.
Update: Rosyna points out that dateWithNaturalLanguageString might be a dangerous method to use here, because it will implicitly use a different locale to parse the string, depending on the user’s language settings. Furthermore, the documentation for that method strongly discourages its use. Ironically though, the reason its use is discouraged, because it’s got a limited vocabulary and favors English, is probably just about right for parsing the date from GCC.
The GCC documentation describes the contents of __DATE__ as “eleven characters and looks like ‘Feb 12 1996’.” I’m not really sure how many locales this will or will not work correctly for, so I’m thinking the safe bet is to use a more explicit string -> date conversion format. I’m busy with something else right now but if anybody has a good capsule solution for this, please share it in the comments! Rosyna suggests offline that perhaps some POSIX date string formatter will do the trick.