Re: Experience with keyed archiving forward/backwards compatibility?
Re: Experience with keyed archiving forward/backwards compatibility?
- Subject: Re: Experience with keyed archiving forward/backwards compatibility?
- From: Maxthon Chan <email@hidden>
- Date: Mon, 02 Sep 2013 00:03:12 +0800
I use keyed coding with defaults to solve this issue, keys never change meaning after definition, app should ignore non-recognised keys and missing keys are defaulted or inferred from existing ones.
On Sep 1, 2013, at 23:07, Marcel Weiher <email@hidden> wrote:
> Hi Graham,
>
> thanks for sharing your experience, that’s really helpful!
>
> On Sep 1, 2013, at 11:54 , Graham Cox <email@hidden> wrote:
>> On 31/08/2013, at 6:48 PM, Marcel Weiher <email@hidden> wrote:
>>> 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.
>
> Exactly my thoughts. When I was using old-style archiving, I only provided for backwards compatibility, and it was easy enough:
>
> read base version info
> if ( version >= x ) {
> read version x info
> if ( version >= y ) {
> read version y info
> ...
> }
> }
>
> Alternatively, if the changes are more incompatible:
>
> if ( version == x ) {
> read version x info;
> } else if ( version == y ) {
> read version y info;
> } ...
>
> The code is pretty straightforward in both cases, as you already have the old code and just add the new code.
>
>> 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.
>
> Right. And if you want to preserve the ability to write older versions, just pass that info in and handle in a way that’s similar to the reading case.
>
>
>> 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).
>
> OK. Substituting classes does work in NSUnarchiver, but you can’t then easily ignore
>
>> 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.
>
> To achieve something like this with NSArchiver would definitely require more work and forethought, such as an extension “blob” that can optionally be unarchived separately.
>
>>
>> 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.
>
> Well, archiving in general is pretty convenient, I am just trying to figure out how significant the benefits of keyed archiving are in particular (as compared to, for example, old style archiving). If you’re on iOS you don’t have a choice, but otherwise it seems the benefits are fairly slim, considering the 2-4x performance penalty.
>
> Thanks again!
>
> Marcel
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> 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:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden