If you can’t decide, give the user more options — not!


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">I find my self in the middle of lots
of sticky API design issues. style="mso-spacerun: yes"> Usually we have a couple of pretty clear
options with well known pros and cons. style="mso-spacerun: yes"> Sometimes the battles get pretty heated
between people arguing for one option or another and some well meaning PM
suggests “let’s just do them both”… It is hard to seem reasonable and argue with
that – after all both sides got what they wanted right? style="mso-spacerun: yes">  Maybe, but the poor user is in a net
worse place.  If we’d just decide on
an option and get 100% behind it we could make the world SOO much better. style="mso-spacerun: yes">  There would be net fewer types and
methods in the system and the ones we’d have would be better! prefix = o ns = "urn:schemas-microsoft-com:office:office"
/>


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">I had another one of those issues
come up today.  A team coming in for
API reviews had a base class, let’s call it “Foo” (so as to not spoil any of the
fun from the PDC) and an interface called “IFoo” that represented exactly the
same contract.  So I ask why they
have both.  Well, it seems that some
clients wanted and interface and some wanted a base class. style="mso-spacerun: yes"> In other words, they couldn’t
decide.  So I ask, when you expose
methods that take with Foo’s what are you suppose to use? Foo or IFoo? When
would I use one over the other?  Do
your methods take Foo and IFoo?  We
had the same problem with Component and IComponent and eventually had to add
specific test cases to make sure IComponent kept working because most everything
derived from Component, it became the defacto standard. style="mso-spacerun: yes"> Having IComponent there to support a
niche scenario adds net complexity to the system. style="mso-spacerun: yes"> I think the same is true for today’s
Foo\IFoo case.  In the end we
decided to the vast majority of scenarios were satisfied by just using the Foo
base class.  


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">I think the world got every so
slightly better today because we took away an option…. Score another point for
addition through subtraction.


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


 

Comments (12)

  1. dom says:

    Glad to hear that simpicity has ruled the day! But how do you convince those who don’t understand the importance of simplicity in design?

    http://dotnetjunkies.com/weblog/d0m1/posts/1561.aspx

  2. RichardH says:

    I fully agree with that. The success of generics and templates in Standard C++, and the announced generics that will be incorporated in C# means that we all want to write lesser and simpler code, rather than copy paste the same thing in many places.

    But I think when it comes to User Interface, we should provide more options than one.

  3. Urs Muff says:

    I don’t see the problem for the user to decide which to use: Foo or IFoo. It should be very easy: if you use the concept (composition, parameters, or returns) always use the interface IFoo. If you want to extend/implement the base class and only want to use inheritance use Foo as base class. Usage is normally at least 10 to 1 compared to implementation, furthermore you allow others to aggregate (COM like) and be compatible to the concept of Foo even if they cannot derive from Foo (single inheritance restriction). In a framework that is very important in my opinion, if you want others to be able to make full usage of new concepts introduce in the framework, but they have already existing concepts and implementation hierarchy that is hard to change.

  4. mikelor says:

    I would agree with the usage of both. Whenever possible I *always* use the interface when creating references to instances of classes. Why, because you program to the interface, not the implementation.

    A second and I believe more important point is brought up by Urs Muff, C# like Java is limited to single inheritance (thank goodness). By not creating an interface to implement, I must always derive my class from Foo, well what if it makes more sense for my application to derive from Bar and implement IFoo. Single inheritance for classes, but multiple inheritance for interfaces. See
    http://www.javaworld.com/javaworld/jw-09-2001/jw-0921-interface_p.html

  5. mikelor says:

    I would agree with the usage of both. Whenever possible I *always* use the interface when creating references to instances of classes. Why, because you program to the interface, not the implementation.

    A second and I believe more important point is brought up by Urs Muff, C# like Java is limited to single inheritance (thank goodness). By not creating an interface to implement, I must always derive my class from Foo, well what if it makes more sense for my application to derive from Bar and implement IFoo. Single inheritance for classes, but multiple inheritance for interfaces. See
    http://www.javaworld.com/javaworld/jw-09-2001/jw-0921-interface_p.html

  6. Gerke Geurts says:

    I wholeheartedly agree with Urs. Especially when building (on top of existing) infrastructure code, it is useful not too be forced to use someone’s base class. The interface (including preconditions, postconditions, invariants) is the contract. Using a base class and inheritance is mere technical convenience.

    In VB6 days it was frustrating not to have this convenience. Now, I have already encountered several times the shear frustration of not having interfaces as well as base classes. I want both and need the freedom to decide whether I’ll implement the contract myself or use an easy base implementation!

    So, I find it rather short-sighted to take the decision to only use a base class, as any framework designer does not have full oversight of how others will use and extend the framework.

  7. Paul Walker says:

    Whenever I find myself w/ a similar choice in which my interface methods would map one to one w/ my base class methods I ask myself this question:

    Is the base class a candidate for run-time decoration?

    For example: I have a Division class that implements IDivision and contains all the state data that is used in almost all contexts of the application. This state data, being small/static/used enough, is cached in the application as instances of each division. Depending on the context, I often like to add run time capability to these division instances ( for example, add a collection employees ) by passing this instance to the constructor of a a Decorator class that also implements IDivision. The implemented methods of the Decorator delegate to it’s private instance of the Division class and the client can now treat the decorator as it’s IDIvision when needed or as the Decorator when needed for the specific runtime capability.

    Straight up inheritance is no good for me here…I already have an instantiated Division class. Keeping one to one mapping of the methods of the base class and interface allows for easier run time decoration of the base class when desired.

  8. Keith Hill says:

    Foo vs. IFoo aside, I think reducing and keeping the "surface area" of the .NET FCL as small as possible is a very worthwhile goal. As more functionality and more and more of the different MS groups start contributing to the FCL I worry about winding up with a complicated mess.

  9. Frank Hileman says:

    IComponent was essential. Component is a fat base class, and derives from MarshalByRefObject, which has performance issues (inlining) and other limitations. Without IComponent we would have been in trouble. So when you design low level abstractions such as these, please listen to the PM that says "the base is not for everybody". You picked a very bad example here.

    I would agree that sometimes you only need the base class. But not for the lowest level abstractions.

  10. Joe Cheng says:

    +1 on including both interface/base class.

    I’ve always wondered, why is it not possible to "implement" (in Java terminology) the contract exposed by a public class–that is, assert that my class fulfills the contract of Foo, without inheriting any of the implementation of Foo? That way, you never need an explicit IFoo. Most people could just extend Foo, but if you have a class that is part of another class hierarchy you could just implement Foo.

    Does any statically type-checked OOP language support this kind of thing?