On 31/08/2013, at 6:48 PM, Marcel Weiher <[email protected]> wrote:

> 
> On Aug 29, 2013, at 11:54 , Graham Cox <[email protected]> wrote:
> 
>> 
>>> So the whole automagic forward/backward compatibility that we’re supposed 
>>> to get with keyed archives doesn’t actually pan out.  If you want 
>>> compatibility, you have to plan and code for it, just like with old-style 
>>> archiving.   And ideally, you have an externally defined format.
>> 
>> Yes, you have to plan for it, but on a class-by-class basis, and only as 
>> necessary. It's not auto-magic, but it's generally pretty easy.
> 
> So you’ve had good practical experience with forward/backward compatible 
> designs?


Yes.

But let me qualify it :) By 'backward compatible' I mean files created by an 
earlier version of the app can be opened in a newer version, 'forward 
compatible' means the inverse: newer files can be opened by an older version of 
the app.

Backward compatibility is much easier than forward compatibility, and typically 
as the app evolves, that is what the primary focus is on, because on the whole 
you expect people to upgrade your app to a newer version, but they may have 
files created by the earlier version. Going in the other direction is only 
important if users with a variety of versions of your app share the files 
amongst each other - it's very rare for a single user to downgrade to an 
earlier version of your app.

So ensuring backward compatibility is something that is typically handled on a 
class-by-class basis, where the -encodeWithCoder simply writes what data it 
currently needs to, possibly with flags or versioning info so that the 
corresponding -initWithCoder is able to know which particular items are of 
interest. -initWithCoder: should also, as necessary, deal with older-format 
items it encounters when handed an old file.

Going the other way requires more cunning, and usually needs some support from 
version 1.0 of your app. I mentioned using a keyed unarchiver delegate - one 
way that can be used is to handle entire classes that the older app doesn't 
know about. It can substitute something else, perhaps the nearest superclass, 
or a placeholder so that newer files can be opened with reduced functionality. 
This can also help with backward compatibility, for example by translating 
older classnames to newer ones if you ever change them (that sounds unlikely, 
but it did happen in one product I developed due to a client insisting on 
changing a whole bunch of classnames after version 1.0). Newer versions can 
also provide alternate objects which cover the functionality present in the 
older apps, even if it's just a way to communicate to the user that they ought 
to upgrade. Example: a newer version of an app wrote out image data differently 
from an earlier version (which fell into the classic trap of archiving an 
NSImage object), but the newer app also archived a placeholder NSImage which 
included the text "version xxx is required to view this image", so that opening 
the newer file in an old app at least gave the user the hint. In that case it 
would have been possible to include image data in both formats, but we 
preferred to encourage the user to upgrade. The newer app could dearchive an 
old file's NSImage and convert it without a problem so a subsequent save would 
promote the file to the newer format.

That's as far as I've ever gone on forward compatibility. If you need something 
more robust than that I'm sure it can be done. As you said, some externally 
defined format helps a lot but the convenience and flexibility of keyed 
archiving is very attractive.

--Graham



_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to