Re: Mantaining legacy APIs in a framework
Re: Mantaining legacy APIs in a framework
- Subject: Re: Mantaining legacy APIs in a framework
- From: Graham Cox <email@hidden>
- Date: Wed, 02 Sep 2015 10:18:56 +1000
> On 2 Sep 2015, at 4:41 am, Maxthon Chan <email@hidden> wrote:
>
> This seems like a bit of code smell - next time when you plan to ask the user of your libraries override a method, put it into a delegate protocol. By doing this the end user does not need to actually subclass you and hence internal call structure no longer is part of the contract you have to keep all the time and internal refactoring like this can be done easier.
I don’t think I agree. Taken to its logical conclusion, you’re saying that subclassing anything is a code smell.
If you end up making all of your “overridable” entry points delegate methods, you’re basically reimplementing the whole method table dispatch in an ad-hoc fashion, which really subverts the point of having on object-oriented framework. Delegate callbacks definitely have their place, but only where they really ease an implementation, not make it more trouble.
Let’s suppose Apple didn’t allow you to subclass NSView, but instead all of the customisation points were delegate callbacks. Creating even a trivial custom view would be a ton of work, and would likely underperform. That’s pretty much the case I have here - my GCBase class is a very fundamental class which implements many behaviours which are fairly non-trivial, but on its own doesn’t do very much. You need to override a few key methods to get it to do anything concrete. In simple cases this is probably only one or two methods, but in other much rarer cases it can end up being dozens.
One of these commonly overridden methods is to do with hit-testing against the mouse point. In my original design, the hit test method took only the local mouse point as a parameter. This was enitirely adequate for many years, but due to a new requirement, the state of the modifier flags and potentially other event state information is now needed when hit-testing, so the modern version of this method passes both the local mouse point and the original event as parameters. Trouble is, the client code that has been overriding the original hit test method only knows about the single parameter version, which is still adequate in almost all cases. So either the client code can be revved to include the event parameter (which it then usually ignores) or else the framework can arrange to fall back to the original method as necessary to keep all that client code working unchanged. Because the class in question is a key class analogous to NSView, revving client code represents a significant amount of work across a number of different applications, and there’s always the chance that you’d forget one that snuck through testing. So keeping the old APi alive is worth it.
If these were delegate methods it wouldn’t change the picture very much - you could extend the delegate protocol for the new methods easily, and arrange to call the old ones easily, and that probably represents the same amount of effort on the framework side of things. But on the client side, implementing these objects as delegates would always have been a lot more effort than subclassing. I don’t see that the effort is worthwhile just to avoid the possibility in the future that one of the override points turns out to need more parameters.
—Graham
P.S. Anyway, thanks to Jens and Ryan, I have got around the problem as needed.
_______________________________________________
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