Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Back to Basics: Interfaces

#karl_custom_4 code{color:#833;background:#fcfcfc;}
#karl_custom_4 h4{margin:30px 0px 0px 0px;font-color:#fff;font-weight:bold;border-bottom:1px dashed #ccc;font-variant: small-caps}


When it comes to object-oriented programming there are few concepts as basic and important as interfaces. Only recently though, and at a snails pace, have .NET developers started to take advantage of the simple benefits interfaces have to offer. This interest stems from the core role interfaces play in some pretty hot topics, including: dependency injection, unit testing and mocking (to name a few).


At first glance, interfaces can be pretty misleading: they are so simple and solve such a basic problem that developers often grossly underestimate their value. There is no magic to interfaces, no secret pattern that’ll let you squeeze incalculable gains of productivity, they are merely a fundamental part of sound software design which help you build better software.


What is an interface?


The role of an interface is to define the contract that implementers must follow. In other words, an interface says what a class must define. Importantly, an interface doesn’t specify (or care) how the implementation is actually achieved. As we move forward we’ll see how helpful this can be to us, for now, let’s look at a trivial example:

public interface IUserRepository
{
void User FindByCredentials(string userName, string password);
}

public class UserRepository : IUserRepository
{
public User FindByCredentials(string userName, string password)
{
return null;
}
}


The class UserRepository is said to implement the IUserRepository interface. This code will only compile if UserRepository implements all of the methods/properties defined in IUserRepository – with matching signatures (return type, member name, input parameters). If the code compiles, we are guaranteed that an instance of UserRepository can be treated as an IUserRepository.


An interface can define zero or more members (methods or propties) and a class can implement zero or more interfaces. Interface members are always public (I think it would be nice to allow them to be internal though!). An interface with zero members is is called a marker-interface – they don’t require implementers to do anything. For example, you might have an IImmutable interface which doesn’t have any members; however, your repository might have the following type of code to make use of it:

public void Update()
{
if (_entity is IImmutable)
{
throw new InvalidOperationException(“The object is immutable and cannot be updated”);
}
//continue with update
}

Decoupling


The raison d’être of interfaces is to provide developers with a language-level tool that allows classes to be decoupled from each other. Mocking frameworks and dependency injection frameworks rely on this core language feature – in a sense, interfaces serve as the main (though not the only) building block for decoupling.


The problem with using a concrete class from client code is that it ties the calling code to that specific implementation. The classic example is calling a data access layer, from:

SqlDataStore store = new SqlDataStore();

to:

IDataStore store = new SqlDataStore();

Many examples would use code like the above and simply state that the latter is better than the former. The problem with this example is that it’s rather contrived and doesn’t really result in better code. If our implementation changes, say to Oracle, all we need to do is change the first line to define and create an OracleDataStore. (In reality, the better approach to the above code would be to use a DI framework, which would rely on the presence of the IDataStore interface – but don’t think that interfaces are only for framework developers.)


I think a better perspective on interfaces is through the extensive presence of collection interfaces found throughout the .NET framework. You may be tempted to use a List<T> to expose the relationship between a user and the one or more roles he can have:

public class User
{
private List<Role> _roles;

public List<Role> Roles
{
if (_roles == null)
{
_roles = new List<Role>();
}
return _roles;
}
}


The problem with this approach is that you’re tied to a very specific implementation of a list collection, maybe in a future release you’ll find that a LinkedList<T> or a HashedSet<T> is more suitable.


Before we jump to an interface though, let’s take a realistic look at the last statement, which essentially boils down to: you may want to make a change in the future. If you and your team are the only people writing code that consumes the User class (which is likely), changing the roles implementation from a List<T> to a HashedSet<T> isn’t going to be a big deal. Its worth repeating that decoupling through interfaces leads to small incremental improvements of your system – it isn’t a silver bullet.


We can decouple client code from the specific List<T> implementation by making a dead-simple change to the User class:

public class User
{
public IList<Role> _roles;
public IList<Role> Roles
{
if (_roles == null)
{
_roles = new List<Role>();
}
return _roles;
}
}

Except in a few edge cases, there’s never a good reason to expose the concrete implemented over a an interface.


Promise Less


One of the benefits of exposing an interface is that you can promise the minimum amount of functionality needed by calling code. This may sound counter-intuitive, but the less functionality you promise, the less you need to maintain. In our above code we may use an ICollection<T> instead of an IList<T>, which defines even few methods (yet still offers all the core stuff you’d likely need with a collection). We might even take it a step further and expose an IEnumerable<T> which would only let calling code iterate through a user’s roles. Adding and removing roles might be accomplished through appropriate methods in the User class (in this case we’d likely find that IEnumerable is too limited though).


Yet another benefit of promising less is that it’s easier to build new implementations. Using a IList<T> allows us to change the implementation between a handful of built-in .NET classes (or write our own). Exposing an ICollection<T> allows us to use even more built-in classes; and of course exposing an IEnumerable<T> let’s us swap the collection implementation with virtually any of .NET’s collections.


Whether you ever actually build your own, or ever swap out the implementation isn’t really the point. The point is that the ability to painlessly do this is a symptom of a quality system. It isn’t the end of the world if you can’t, it’s just better if you can.


Abstract Classes vs Interfaces


There’s some overlap between abstract classes and interfaces. Sometimes it isn’t clear which tool you should use. A pragmatic factor that can help you decide is that a class can implement multiple interfaces, but only inherit from a single base class. Generally speaking though, an interface isn’t concerned with implementation, whereas an abstract class typically provides a set of common behavior to inheritors. The two often play quite well together. Take a look at a real implementation of the UserRepository we fist looked at:

public class UserRepository : BaseRepository<User>, IUserRepository
{
public User FindByCredentials(string userName, string password)
{
var query = new Query<User>().Where(“UserName”, Operations.Equals, userName).And(“Password”, Operation.Equals, password);
return FindOne(query); //FindOne is defined in the BaseRepository
}
}

Client code programs against the IUserRepository, while the actual implementation re-uses the base abstract class functionality.


What to Interface?


So where do we draw the line? Should we program against IString and IInt32? The answer to what should and shouldn’t be decoupled via an interface comes from experience and varies from system to system. There’s a realistic limit to what we can and need to do. As you can guess from my example, collections are generally worthy of decoupling, as is code that sits on a layer’s boundary or serves as part of a published API (whether or not you’re the only consumer).


It’s worth pointing out that one of the benefits of unit testing is that things that need to be decoupled quickly become evident.


Conclusion

Making use of interfaces today is a quick and easy way to make your system better for tomorrow – it costs absolutely nothing, yet rewards you with greater flexibility. Instead of returning Dictionary<T, K>, consider returning an IDictonary<T, K>; instead of having an input parameter of type SqlDataReader, maybe you’ll get more re-use from specifying an IDataReader or IDataRecord. Sadly you’ll notice that most of the documentation/books/guides you’ll find don’t make use of this simple pattern – even though it’s long been established in OOP circles (the concept of information hiding, which is essentially what we are talking about, was formally being discussed in the early 70s). Simply put, don’t expose implementation details unless you have to.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

28 Responses to Back to Basics: Interfaces

  1. Kris says:

    Hello,

    Please add your site at http://www.sweebs.com. Sweebs.com is a place where other people can find you among the best sites on the internet!
    Its just started and we are collecting the best found on the net! We will be delighted to have you in the sweebs listings.

    Regards
    Kris

  2. benny856694 says:

    void User FindByCredentials(string userName, string password);

    is this some kind of typo?

  3. Ronnie says:

    Don’t know if someone already mentioned it, but there is an error in your interface

    public interface IUserRepository
    {
    void User FindByCredentials(string userName, string password);
    }

    Void should be removed, because User is the return type

  4. Jim Cooper says:

    @karl

    I have a bit of an issue with this whole “favour interfaces/abstract classes over abstract classes/interfaces” thing. Doing either is making the design decision too early.

    I know that sometimes I will want an interface and sometimes an abstract class, and most of the time I don’t yet know which I want. In normal code* what I find better is to start with an abstract class, and discover the interfaces. But that’s only because I think it’s more difficult to start with interfaces and discover the abstract classes (there’s less tool support, for one thing).

    I have further issues over what many people perceive as meaningful decoupling, but discussing that would mean me starting a blog :-)

    I also have a bit of a problem with you saying that interfaces are “basic and important” to OOP, but that’s mainly an historical objection, as most current OOP languages have them. But it wasn’t always so, you know, young feller! .

    And there was at least one well known non-OO language that supported them :-)

    *slightly different rules might apply for frameworks used outside your team

  5. karl says:

    @Jim
    Sorry about the low-blow re learning from MSDN :)

    @Ed:
    I can mock FindOne, or mock the calls FindOne makes to the DB.

    The “can add a method without breaking consumers” argument is why MSDN guidelines [foolishly] say to favor abstract base classes over interface. It’s a valid concern (though a foolish reason to base such a broad statement), but whenever I hear Microsoft cry out “for the sake of backwards compatibility”, I shudder – it always comes off seeming like their way to fear people into following their way.

    I agree that if you want to add a method, but don’t have to have it implemented, an interface isn’t the way to go. It’s equally common though (if not more so) that you really do want to force people to provide implementations.

  6. Ed says:

    @karl

    yep it was me who asked whetther you were hitting the DB in a unti test. You said repositorybase didn’t get in the way of unit testing which sounded like findone was hitting the database during a unit test. Just wanted you to clarify :-)

    @Jim

    Yep you tend to lean towards abstract classes in frameworks since you don’t want to force a consumer of your framework having to recompile if you add another method, I see where your coming from.

    Agreed, too many mocks can be a sign or high-fan out or over specification in tests. If the creation of a mock makes the test easier to write (and therefore read) then I would happily place an interface over a single class and stub or mock it with Rhino

  7. Leyu says:

    Nice post Karl.

    CLR via C# book has a chapter on Interfaces which is a must read.

    Here are some points from the book

    – The CLR does allow an interface to define static methods, properties… but a CLS-compliant interface must not have any of these static members and C# doesn’t allow having static definitions in an interface.

    – The CLR requires that implemented interface methods be marked as virtual. If you do not explicitly mark
    the method as virtual in your source code, the compiler marks the method as virtual and sealed.

  8. Jim Cooper says:

    @karl

    That was Ed who asked that, not me :-)

    Further to my points above, reading that interview that Ed mentioned shows that Erich Gamma has much the same view as me, eg:

    “Fortunately, with today’s refactoring support you no longer have to come up with an interface up front. You can distill an interface from a concrete class once you have the full insights into a problem. The intended interface is just one ‘extract interface’ refactoring away.

    So this approach gives you flexibility, but it also separates the really valuable part, the design, from the implementation, which allows clients to be decoupled from the implementation. One question is whether you should always use a Java interfaces for that. An abstract class is good as well. In fact, an abstract class gives you more flexibility when it comes to evolution. You can add new behavior without breaking clients. ”

    I also think refactoring is usually easier without interfaces, and I tend to defer extracting them to as late as is responsibly possible (which means it often never happens)

  9. karl says:

    @Jim
    I have integration tests that hit the DB, but no? What suggested that I did?

  10. Jim Cooper says:

    @Ed

    “Interfaces bad, can’t agree with you here”

    I’m not suggesting they are, I’m counselling against overuse.

    “I encourage developers to unit test in isolation and we use Rhino mocks so interfaces are cleaneer and clearer.”

    Good idea. But IMO, if you require many mock objects, that is itself a code smell. And if you require a Rhino-produced mock object, then YAGNI doesn’t apply, because you do actually need the interface then.

    If you have other types of factories creating objects of various concrete classes implementing a given abstract type/interface, I wouldn’t immediately plump for an interface either – I’d let that decision be guided by the situation.

    An interface only implemented by one class (abstract or not) is another code smell, IMO.

    “Part agree with RoleList:”

    Yep, your definition might be better, and your name is fine too (although I do have a different naming convention – eg a property of type FurbleList I would tend to call Furbles, for example). As long as everyone is consistent and sensible it doesn’t matter that much, IMO.

  11. Jim Cooper says:

    @karl
    “I have a completely different perspective than you on YAGNI”

    Possibly. I think that you can add too much “flexibility” for no gain, and indeed, often for a loss.

    “I don’t see how exposing an interface makes the code more fragile – I think it makes it far more robust.”

    Think of it this way. Changing an interface (in the IInterface sense) will always break code. Changing a class definition might not. Ergo, interfaces are more fragile.

    “The simplest thing possible isn’t necessarily what you’re used to doing, or what MSDN says.”

    I might shoot that one right back at you :-) Just because “Effective C#” says to prefer interfaces to classes doesn’t make it a good idea. And I didn’t get my design skills from MSDN – that’s verging on an insult, isn’t it? :-)

    “Just because something adds flexibility doesn’t mean it violates YAGNI”

    In some cases that may be true. But I’m against adding “flexibility” before you need it. It’s easy enough to add IUserRepository when you need it. Why do it if you only ever instantiate it in one class?

    That’s what I mean by YAGNI.

    ” many things are simpler yet provide greater flexibility.”

    And many things are simpler but that don’t.

    Interfaces can be a good thing, but there is more than a touch of silver bullet to many discussions of them.

  12. Ed says:

    Jim:

    Interfaces bad, can’t agree with you here. I see such vile violations of the open closed principal when looking at a lot of .net code, I’m all for .net developers considering some flexibility. I encourage developers to unit test in isolation and we use Rhino mocks so interfaces are cleaneer and clearer.

    Part agree with RoleList:

    name : rolelist isn’t a domain concept to me

    public class UserRoles : IEnumerable
    {
    private List
    roleList;

    }

    The above lets you change List to a Dictionary under the covers without forcing all the callers to start using KeyValuePair in their foreach code.

    Agree with you that this helps isolate the implementation but will throw in that developers who maintain/extend this code have a class to put code into that deals with the users roles rather than putting code in the classes that depend on UserRoles

    Although YAGNI goes against this, I have moved to YJMDWDIWR (your junior maintenance developer won’t do it when required) doesn’t roll off the tongue though :-)

    Karl:

    Your unit tests hit the database?

    Ed

  13. karl says:

    @Sam
    Yes, good catch

    @Jim
    I have a completely different perspective than you on YAGNI – I think exposing the concrete type is a violation of YAGNI, and I don’t see how exposing an interface makes the code more fragile – I think it makes it far more robust. The simplest thing possible isn’t necessarily what you’re used to doing, or what MSDN says. Just because something adds flexibility doesn’t mean it violates YAGNI – many things are simpler yet provide greater flexibility.

  14. Jim Cooper says:

    “Making use of interfaces today is a quick and easy way to make your system better for tomorrow – it costs absolutely nothing, yet rewards you with greater flexibility.”

    I get concerned about statement like this. Remember when the great goal of OO was reuse? Even when it wasn’t necessary? I’m starting to feel that “flexibility” is the new reuse.

    YAGNI applies here too. And there **is** a cost to using interfaces – your code becomes more fragile (ie breaking changes are more frequent). It’s easier to refactor classes than interfaces, so my advice is usually to start with a class and let interfaces fall out of the refactoring process.

    And I also don’t think your IList example is a good one. If you truly want flexibility there, define a new class:

    public class RoleList : List
    {
    }

    It’s a much better solution that insulates your User class from changes to the list of roles implementation details much more effectively.

  15. Justin says:

    Another great article Karl, as usual. It is amazing how often we need to be reminded of these fundamental concepts.

  16. Garry says:

    Thanks Karl. I love these back-to-basic articles. They certainly help me as they often cover aspects from the real world which don’t always get covered in the textbooks.

  17. Hi Karl,

    thanks for this article. It has been a while since I got this part of software development explained to me so it got a bit rusty.

  18. Sam says:

    Hi, don’t you need the get{} part in this property?

    public IList Roles
    {
    if (_roles == null)
    {
    _roles = new List
    ();
    }
    return _roles;
    }

  19. Cool! How do I do that in IronRuby? :)

    It’s important to note that every class has an interface. An interface is any class’s signature. Static, pure virtual **types** like .NET interfaces are really just a specialized construct for these kinds of languages. This isn’t as much object-oriented design as it is class-oriented or type-oriented design. It really doesn’t have much to do with objects in essence.

  20. Petar Repac says:

    Nice article. Thanks Karl.

  21. bennyb says:

    Always try to “Interface” services. e.g. IOrderDeliveryService, INotificationEngine

  22. Other Rob says:

    With regards to abstract base classes vs. interfaces, it might be worth going back in the virtual time machine to see where this makes sense and how it got here. A lot of old object-oriented design theory (not necessarily related to programming, but rather modeling in general) concerned itself with generalization and specialization. That is to say that a class of thing was general and common, and that you had specialized classes of things that are subclassed from the general class (base class). That pretty much sums up inheritance, and is more or less where you get base classes from. Some of the earlier programming languages, because of these modeling principles, used base classes, but had no real independant notion of a purely abstract interface (take C++ for example). As a side effect, you gained polymorphism by inheriting base classes, and that was that. But people quickly discovered that there were cases where it made no sense to have an instance of a base class by itself – that it only represented common general state and behavior of other subclasses. That got people to deal with a notion of “abstract” vs. concrete classes. Abstract classes could only be inherited, but not instantiated. But further still, people began to notice that there was a seperate and distinct pattern evolving where you had a purely abstract “type” (class in the loose sense of the word) with zero implementation meant to define the interface for which you would talk to subclasses – a case where you had polymorphism with no inherited behavior or state. This scenario became so common and had such clear benefits in some cases that later OO languages (like Java, C#, and VB/VB.NET for example) took this concept to the next level and made it a first-class citizen of the language. In fact, COM was completely built around the notion, which is how it crept into classic VB. You could argue that COM was really a technology to publish interfaces across module boundries for C++, and since classic VB was built around COM, it only made sense to incorporate the notion.

    Other languages, like Object Pascal, for example, give hints to the segregation of the concepts. There, when you define a class “type”, you have a section where you describe the Interface and a separate section where you describe the Implementation, although it doesn’t actually treat the Interface as an entity seperate from the encompassing class “type”.

    The biggest distinction between abstract classes and interface in modern languages (unlike C++ where all you had were base classes) is that base classes (abstract or not) are used to define common, generalized state and behaviors which are inherited by subclasses. Interfaces don’t provide implementation, so you are simply defining the polymorphism mechanism of the classes implementing them – in other words, defining the “contract” of guaranteed members for those classes which can be accessed (without providing any implementation).

  23. karl says:

    @Brian
    Thinking about it, you’re right about internal interfaces. It likely doesn’t make sense to have an interface that mixes public deceleration and internal ones.

    @Rob
    I don’t use interfaces for domain objects. I’ve seen such implementation but never a benefit associated with it. Unless experience, or someone, corrects me, I’d almost consider it an anti-pattern. There me be some benefits when dealing with a “Summary” object.

    @Ed
    I think this one will come down to personal preference and your own experience. First, there’s no pain point in unit testing UserRepository based on it’s coupling to RepositoryBase – so there’s one major flag down. Second, I kinda want them to be tightly coupled – logically, I see the FindOne method as part of UserRepository – the fact that I use inheritance for re-use is an implementation detail to me. Maybe that doesn’t make sense, but when I conceptualize my code, I don’t think of BaseRepository.

    I agree that composition would work at least as well and that its generally right to favor it over inheritance.

  24. Ed says:

    a quick google and I found this:

    http://www.artima.com/lejava/articles/designprinciples.html

    An interview with Eric Gamma about programming to interfaces. He expresses far better than I did in my previous comment :-)

  25. Ed says:

    How about “favour composition over inheritence” and the fragile base class problem?

    Doesn’t the tight coupling to RepositoryBase contradict this?

    Anybody got an nDepend rule for classes with names ending in Base?

    Regards

    Ed

  26. You are at your best when you are writing with passion about the basics. I love this one, and I am going to be making sure every Jr. Developer in the office reads it.

    Regards,

    Roberto

  27. Rob says:

    Hi, nice back to basics article. Always raises lots of discussion.

    We make a point of placing our interfaces and implementation classes into two separate projects, and use IoC via Castle Windsor to resolve objects. We then use nDepend to ensure applications only reference the interface project and not the implemention directly.

    To make sure all the dll’s get pulled into the application’s bin dir, we fluently load our IoC container. This whole setup ensures everything is strongly typed so run time errors are less likely.

    One place we don’t have interfaces, is on our Model classes (ie, “User”). I often wonder whether we should though, as they contain a fair amount of implementation.

    Also the hardest thing I find with hiding implementation (encapsulation), is unit testing. I know you’re only supposed to test public methods, but that’s often not the smallest unit to test (and can mean mocking/stubbing a lot).

    I find there are two options, make the hidden implementation public (in another class) or make the method protected so you can unit test it using inheritance. I generally prefer the former, although sometimes the latter can make sense.

  28. Brian says:

    One distinction I bring about when to choose an interface over an abstract class is that an interface is move oriented towards defining “services” for other types (such as IDisposable offering a disposing service through the Dispose methods for any objects that should take care of its own disposing), whereas an abstract class is more oriented towards defining or encapsulating “behaviors” for other types (such as the Array class offering various instance and static methods to its derivatives).

    Another thing developers should be aware when either developing public interfaces is that they better be sure that those interface will not change in the future because applications depending on those interfaces will surely break.

    BTW, could you elaborate on your argument for making interface methods internal? I would suggest having those “internal methods” in an internal interface instead, but I’m still curious to know why you would suggest that a [public] interface should specify the scope of its methods other than public.