![]() |
|
|
|||
|
Changing an interface
I've seen 2 differnt approaches people take to interfaces and am just curious
on some other opinions. For purposes of this post I am talking about adding a new method to an existing interface. The first is that an interface can never change, once it's "published" it is fixed in stone and if a change needs to be made you should create a new interface that possibly inherits from the old one. The second is that it is ok as long as the change does not break the existing contracts, which wouldn't happen if a new method was added, since they were not using it before they wouldn't need to be aware of it now. thoughts? |
|
|||
|
Re: Changing an interface
On Jul 22, 7:54*pm, wdudek <wdu...@newsgroup.nospam> wrote:
> I've seen 2 differnt approaches people take to interfaces and am just curious > on some other opinions. For purposes of this post I am talking about adding a > new method to an existing interface. *The first is that an interface can > never change, once it's "published" it is fixed in stone and if a change > needs to be made you should create a new interface that possibly inherits > from the old one. The second is that it is ok as long as the change does not > break the existing contracts, which wouldn't happen if a new method was > added, since they were not using it before they wouldn't need to be awareof > it now. The second approach is incorrect since the interface can be implemented as well as used; in fact, it is the whole point of having an interface! If you change the interface, all existing implementations would immediately break. Just imagine what would happen if Microsoft added, say, a new method to IEnumerable tomorrow. If you do not want to allow users to implement your interfaces, then interfaces are the wrong tool for the job. Use abstract classes with internal constructors. Those can only be used but not derived from by code outside of your assembly (and friend assemblies, as needed), so there you can safely add new methods. Well, almost - keeping in mind that adding a new overload can break existing code; if you had a method Foo(double), and in your new version added an overload Foo(decimal), any code that called it passing an integer - e.g. Foo(123) - would now stop compiling because of ambiguity. |
|
|||
|
Re: Changing an interface
On Tue, 22 Jul 2008 09:34:45 -0700, Pavel Minaev <int19h@gmail.com> wrote:
> The second approach is incorrect since the interface can be > implemented as well as used; in fact, it is the whole point of having > an interface! [...] While I agree with pretty much everything else you wrote, I'll point out that allowing the client to implement the interface is not "the WHOLE point of having an interface". There are examples of interfaces that are read-only as far as the client is concerned. In those situations, it shouldn't be a breaking change to add a member to the interface. For example, using an interface to control accessibility (C# doesn't provide as fine-grained accessibility control as some other languages, and so an interface might be used to keep an entire class private except to some specific other class while allowing _some_ of the members of the class to be public to the rest of the world). Which is not the same as saying that doing so should be considered lightly. Just that there are in fact scenarios in which changing the interface after the fact wouldn't be disastrous. Pete |
|
|||
|
Re: Changing an interface
I understand Pavel's comments about if Microsoft added a method to
IEnumerable, and definately see how that would cause problems. From Peter's perspective I guess I need to provide more background information on what we are changing and why. Probably the most important piece to this is that we are writing this strictly in house, not that this should allow us to bend the rules and make changes we shouldn't. Secondly what I started off doing that caused me to post this was add functionality to an existing wcf service. The service currently has a method that returns a list of products a user can see. The new method did the same thing but also limited the list by an application name provided by the calling client. There are numerous applications using the old code so they need to see the interface with the current method. Meanwhile new applications need to see both methods. I didn't want to create a second service because the functionality is very integrated and people calling this wouldn't expect to look elsewhere for it. After doing some testing I found that I could add the new method and the existing code would work fine while the new code would get the additional method. I didn't seem to have much choice here. My dilema arose when I got to the library the service calls and how to handle this there. I originally added a new interface but then decided that since there wasn't a new interface in the wcf service that this was confusing. This led me to go back and add the method to the existing interface. I guess the one caveat about this all being in house code is that I know that the only code implementing the interface that was added to is the class inside the library containing the interface. All other references to the interface are to the return valeu of my factory class. Does this change anyone's opinion? "Peter Duniho" wrote: > On Tue, 22 Jul 2008 09:34:45 -0700, Pavel Minaev <int19h@gmail.com> wrote: > > > The second approach is incorrect since the interface can be > > implemented as well as used; in fact, it is the whole point of having > > an interface! [...] > > While I agree with pretty much everything else you wrote, I'll point out > that allowing the client to implement the interface is not "the WHOLE > point of having an interface". > > There are examples of interfaces that are read-only as far as the client > is concerned. In those situations, it shouldn't be a breaking change to > add a member to the interface. For example, using an interface to control > accessibility (C# doesn't provide as fine-grained accessibility control as > some other languages, and so an interface might be used to keep an entire > class private except to some specific other class while allowing _some_ of > the members of the class to be public to the rest of the world). > > Which is not the same as saying that doing so should be considered > lightly. Just that there are in fact scenarios in which changing the > interface after the fact wouldn't be disastrous. > > Pete > |
|
|||
|
Re: Changing an interface
On Tue, 22 Jul 2008 10:43:02 -0700, wdudek <wdudek@newsgroup.nospam> wrote:
> [...] Does this change anyone's opinion? Not mine. And I think you could use an occasional paragraph break. :) Basically, I think that there are times when you can get away with simply modifying an existing interface. But I agree with Pavel in the sense that I think one should consider those situations carefully. The usual way to deal with versioning issues like this is actually to create a second interface, either as a new version of the old interface (so includes both methods) or as a whole new interface (including only the new method). You can use casting or "is" and "as" (in C#) to convert a reference to the old interface to one of the new interface. I'm not aware of a better general-purpose versioning mechanism in .NET. I wish there were one, but I'm not sure what it would look like :). If you have a really good, compelling reason to avoid using the standard approach and just modify the existing interface, there are (as I said) situations in which that could be justified. But otherwise, I think it's better to stick with the "tried and true", clunky though it might be. :) Pete |
|
|||
|
Re: Changing an interface
On Jul 22, 8:50*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote: > While I agree with pretty much everything else you wrote, I'll point out * > that allowing the client to implement the interface is not "the WHOLE * > point of having an interface". I disagree, but do read on. > There are examples of interfaces that are read-only as far as the client * > is concerned. *In those situations, it shouldn't be a breaking change to * > add a member to the interface. *For example, using an interface to control * > accessibility (C# doesn't provide as fine-grained accessibility control as * > some other languages, and so an interface might be used to keep an entire* > class private except to some specific other class while allowing _some_ of * > the members of the class to be public to the rest of the world). That was precisely why I went on to explain how abstract classes can be used for the same purpose. The reason being, you can't force the client to avoid implementing an interface and passing it to your methods which take arguments of corresponding types; and with abstract classes, you have that option, and for the task you described (hiding implementation classes, exposing only a limited surface), they work just as well. Therefore, it would seem that using abstract classes for that purpose is more appropriate. |
|
|||
|
Re: Changing an interface
They really need a preview pane in here to prevent those run on paragraphs :)
Thanks though, in this case I did modify the existing interface, because adding the second did seem a bit clunky to me but your argument for not doing so does make sense and it's likely to be the direction I take going forward. Bill "Peter Duniho" wrote: > On Tue, 22 Jul 2008 10:43:02 -0700, wdudek <wdudek@newsgroup.nospam> wrote: > > > [...] Does this change anyone's opinion? > > Not mine. And I think you could use an occasional paragraph break. :) > > Basically, I think that there are times when you can get away with simply > modifying an existing interface. But I agree with Pavel in the sense that > I think one should consider those situations carefully. > > The usual way to deal with versioning issues like this is actually to > create a second interface, either as a new version of the old interface > (so includes both methods) or as a whole new interface (including only the > new method). You can use casting or "is" and "as" (in C#) to convert a > reference to the old interface to one of the new interface. > > I'm not aware of a better general-purpose versioning mechanism in .NET. I > wish there were one, but I'm not sure what it would look like :). If you > have a really good, compelling reason to avoid using the standard approach > and just modify the existing interface, there are (as I said) situations > in which that could be justified. But otherwise, I think it's better to > stick with the "tried and true", clunky though it might be. :) > > Pete > |
|
|||
|
Re: Changing an interface
On Tue, 22 Jul 2008 12:15:24 -0700, Pavel Minaev <int19h@gmail.com> wrote:
> [...] > That was precisely why I went on to explain how abstract classes can > be used for the same purpose. I don't really understand your comment. You recommended an abstract class with an internal constructor, but that assumes (to start with) you are satisfied with "internal" as an appropriate level of accessibility for the purpose of hiding the members from other classes. I'm not going to waste a lot of time debating the point though. The fact is, there are exceptions to the rule "don't modify the interface". You can disagree if you like, I don't mind. Pete |
|
|||
|
Re: Changing an interface
On Jul 23, 1:04*am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote: > On Tue, 22 Jul 2008 12:15:24 -0700, Pavel Minaev <int...@gmail.com> wrote: > I don't really understand your comment. *You recommended an abstract class * > with an internal constructor, but that assumes (to start with) you are * > satisfied with "internal" as an appropriate level of accessibility for the * > purpose of hiding the members from other classes. Yes. I am treating this from a reusable library design perspective here. Of course, it would be preferrable to have even more fine- grained control than just "internal", but we have what we have with .NET. When considering interfaces that are only used within an assembly and not outside it (or within a bunch of coupled assemblies which expose public members just so that they can interoperate, and not intended to be called from outside that group), the things are obviously different - if only because you can immediately fix all the classes broken by a refactored interface. |
|
|||
|
Re: Changing an interface
On Tue, 22 Jul 2008 14:53:23 -0700, Pavel Minaev <int19h@gmail.com> wrote:
> Yes. I am treating this from a reusable library design perspective > here. Of course, it would be preferrable to have even more fine- > grained control than just "internal", but we have what we have > with .NET. And that's my point. One exception to your statement is the use of interfaces to get around the lack of fine-grained control of accessibility. An abstract class does not necessarily address that issue (it also assumes no need for multiple interface implementations, but I don't think it's necessary to raise that as an issue to provide a useful counter-example). Pete |
![]() |
|
| Thread Tools | Search this Thread |
| Display Modes | |
|
|