views:

242

answers:

4

I have a property called "IsSecureConnection" that is part of my object's interface. This makes sense for most implementations of the interface, however, in some implementations I would like to make the property ReadOnly.

Should I omit this property from the object's interface even though it is required by all of the implementations (though slightly different on occasion)?

Thanks!

+6  A: 

Just add the getter in the interface.

public interface Foo{
  bool MyMinimallyReadOnlyPropertyThatCanAlsoBeReadWrite {get;}
}

Interfaces specify the minimum an object must implement; it doesn't say what an object cannot do. For that, you need to look into creating base classes.

Will
+5  A: 

Interfaces are like salt : sprinkle them everywhere:

public interface ICanBeSecure
{
    bool IsSecureConnection { get; }
}

public interface IIsSecureable : ICanBeSecure
{
    bool IsSecureConnection { get; set;}
}
James Curran
carefull for hardening arteries and higher blood pressure though ;-)
Newtopian
+3  A: 

You need to evaluate the case. If it doesn't make sense to have it always be writeable, separate it into a second interface.

public interface IFoo {
   bool SecuredConnection{ get; }
}

public interface ISecurableOptionFoo: IFoo {
   bool SecuredConnection{ get; set; }
}
Chris Marasti-Georg
You should have ISecurableOptionFoo inherit from IFoo, so you can use an ISecurableOptionFoo whereever an IFoo is called for.
James Curran
Thanks. It compiles now too!
Chris Marasti-Georg
+2  A: 

It really depends on what's most readable for your clients. I can think of a couple of options:

1) The inherited interface, though I'm not a fan of hiding, and I think it makes it a bit ugly for any VB.NET or explicit clients to implement:

interface IObject {
    bool IsSecureConnection { get; }
   // ... other interface definitions //
}

interface ISecurableObject : IObject {
   new bool IsSecureConnection { get; set; }
}

2) Split the set from the property, with an inherited interface:

interface IObject {
    bool IsSecureConnection { get; }
   // ... other interface definitions //
}

interface ISecurableObject : IObject {
   void SetConnectionSecurity(bool isSecure);
}

3) Changing the semantics to try and acquire a secure connection, which an implementer is free to just return false from:

interface ISecurable {
   bool IsSecureConnection { get; }
   bool TrySecureConnection();
}

4) Add an additional check property:

interface ISecurable {
   bool IsSecureConnection { get; set; }
   bool SupportsSecureConnection { get; }
}

All of these are, IMO, valid designs for certain contexts. Since I don't have any info on the use cases, except that almost all of the time a secure connection can be established - I'd probably vote for 3. It's easy to implement, there's only 1 code path for clients, and there's no exception mechanism (which is another form of coupling). You do have the danger of clients not checking the return from TrySecureConnection, but I think it has less issues than the other choices.

If clients prefer a secure connection, but don't require one - then 1 has the disadvantage of either requiring overloads or the client to check if their IObject is really a ISecurableObject. Both of which are kind of ugly. 2 has the same problem, but without the troublesome new/shadows trickery. However, if some clients require a secure connection, then this (or 2) is probably the way to go - otherwise, you can't really use type safety to enforce a securable connection.

4, while a valid design IMO (some would disagree - see reactions to IO.Stream) is easy for clients to get wrong. If 90% of implementers are securable, it's easy to not check the SupportsSecureConnection. There's also an implementer's choice of either throwing an exception or discarding the IsSecureConnection = true call if it's not supported, requiring clients to both catch and check the new value of IsSecureConnection.

Mark Brackett