Mike chews me out for including optional operations on an interface

Mike, another dev on the C# took issue (aka slapped me around) with the way my current interface is being built.  He doesn’t approve of an Add method that can possibly fail.  He thinks that if the interface declares it then it’s something that should be expected to succeed in most cases.  There may be times when it could fail, but having a method be optional and then always fail seems like a bad smell to him.  Because of this he thinks I should refactor the interface into a ICollection interface which presents a non-mutable view over the elements (i.e. Contains, IsEmpty) and a IMutableCollection which extends ICollection and adds the mutating operations.  What do you think about that pattern?  Note: each opreation (Clear, Add, Remove) is independently optional.  So would i need IGrowableCollection, IShrinkableCollection, etc.?  I.e. I might have a collection that implemented Add, but didn’t want to implement remove (like a Queue which only allowed removing of the head, not of arbitrary elements).

It seems to me that this explodes the interface hierachy immensely.  It also makes it difficult when you want to take an object that is an aggregate of many interfaces.  You could say:

void Foo<T>(T t) where T : IGrowableCollection, IShrinkableCollection

But this gets pretty unweildy fast.  Anyone have any pointers to work done in this area and the benefits/drawbacks they faced?

Comments (17)

  1. jaybaz [MS] says:

    There’s a similar question with our IOptional implementation – why does it include a Value property that is optional?

  2. Jesse Ezell says:

    You should include a boolean value that specifies whether optional members are supported. Not only does this allow components to modify their behavior for different implementions (for example, hiding or disabling menu options), but it also is far more performant when operations are not supported than is using try-catch blocks everywhere.

  3. Jesse: could you explain this a little more? Where do i include this boolean value?

  4. Jay: I agree. IOptional doesn’t need Value. The code should have been:

    Some<A> some = reference.Target as Some<A>;

    if (some != null)


    return some.Value;


  5. Jerry Pisk says:

    I agree with Mike. In your example, Queue which only allows removal of the head of the list is called a Stack and is its own class. Just create a few intarfaces that do not overlap (IGrowableCollection and IShrinkableCollection both imply they implement ICollection, which shouldn’t be).

  6. Jerry: Why is Stack it’s own class? Isn’t a stack a collection of elements? From CLR we can see: "Stacks and queues are dynamic sets in which the element removed from teh set by the Delete operation is prespecified.

    It seems completely reasonable to treat a Stack as an ICollection then. Many operations make sense including: Add, Clear, Contains, and even Remove. Although you would want a Remove() that took no arguments.

    Jerry: Would you instead want IGrowable that had teh Add method and IShrinkable which had the remove method?

  7. Jerry Pisk says:

    Cyrus, Stack is its own class because forcing its functionality into Queue would not make sense. Much like you introducing optional functionality into your base interface. Both Stack and Queue implement IColletion (among others) but are two separate classes, even though they differ in a single functionality.

    And yes, IGrowable with Add, IShrinkable with Remove and IYourCollection with whatever is going to be common and always implemented.

  8. Jerry: I’ll try this out. I’ll try to extract every optional behavior into it’s own interface that concrete implementations can use.

    However, how does someone consume it. Say they want a collection that is both IClearable and IGrowable, but not IShrinkable, what is the best way to do that?

  9. Jerry Pisk says:

    In CLR you can implement multiple interfaces, so in your case it would be:

    class MyClass: IClearable, IGrowable



    And I’m not saying extract every single optional piece into its own interface, just group them logicaly. Clearable interface would probably implement both Clear and Delete (where Delete would probably be inhereted from shrinkable interface).

    Just curious – could you go into a little detail how come all these operations are optional?

  10. Jerry: I know i can place whichever interface i want on a class :-)

    However, I’m referring to the fact that I generally want to pass around thigns through interfaces. I.e. I won’t have a method:

    void Foo(MyClass m);

    instead I’ll have:

    void Foo(ICollection c);

    However, when i break things out into multiple interfaces, then passing them around because quite difficult.

    These operations are optional because there are cases where it can be expected for them not to be supported. For example, consider a Set that only holds unique elements.

    if we do:



    We expect the first to succeed and the second to fail. However, it is an expected operation.

    Also consider what I said about:

    Hashtable.Values. Add/Remove would not be supported, however you could imagine Clear being a supported operation.

    On the other hand, if I have a SingletonCollection (a collection that wraps a single value and is optimized for that purpose) then i won’t support any of those operations.

  11. Brian Schkerke says:

    The bools might be a good idea if you’re looking to simplify implementation of your interface.

    public interface IInterface {

    bool SupportsAdd { get; }

    bool SupportsClear { get; }

    bool SupportsRemove { get; }

    bool Add();

    bool Clear();

    bool Remove();


    in code it’d be something like

    if( Foo.SupportsAdd == true )


    Of course you can implement Add so that it fails silently so that code that doesn’t care about the collection can simply call Foo.Add() and move on. (Of course you could also use functions instead of properties.)

    In my mind there would be times when you wouldn’t want the collection to act one way or another. In your example of a unique set I’d expect the set to discard any duplicates; I’m probably going to count on that type of behavior to filter input. The definition of the object that implements that interface suggests this behavior would be the norm.

    If you insist on normalizing the code (which is what this seems to me to be) then you probably need to sit back and refactor. Break it into component pieces, create aggregates out of the components, and design accordingly. Foo.Add doesn’t need to accept anything other than IGrowable interfaces in my mind. Foo.Remove should only accept IShrinkable interfaces. Each discrete operation you want to support is going to become an interface and that will become unwieldy quickly.

    While I’m not good enough to be a Microsoft programmer and probably shouldn’t argue with one, I take issue with Mike saying that an interface shouldn’t have operations that could expect to fail. An interface should define the operations an object will support. It is up to the class implementor how that class will support the interface — whether that is silently dropping the object passed, ignoring it, implementing a stub function that does nothing, whatever. Any of the prior actions ARE supporting the interface — the programmer makes a conscious decision as to what to do. These decisions should of course be clearly documented so that end users of the class don’t get burned.

    Just my two cents. :)

  12. Eric Wilson says:

    Follow the example set by System.ComponentModel.IBindingList, which includes explicit boolean properties for each optional operation.

  13. damien morton says:

    Hey if you want totally fine-grained classes, you could always build a class with delegates instead of methods. That way you could assign whichever methods you want on a class-by-class basis.

  14. damien morton says:

    er, make that instance-by-instance basis

  15. Damien: this is what I am doing with classes. However, do you have a recomendation on how to do this with the interface?

  16. Brian: Argue all you want. The reason I’m blogging about this is because I am unsure what the best design choices are. In fact, I’m becoming increasingly convinved that there are no best design choices here, only a set of tradeoffs to be made.

    The reason I am doing this is because I’m unsastisifed with the current set of BCL collections (that were written by MS programmers). I find them almost always not meeting my needs (which in general refer to flexibility, extensibility and consistancy). Getting feedback and different opinions are necessary so that when I make choices I can understand the issues involved.

    Thanks a lot for your advice! I’ll definitely be discussing it with Mike.