Lowry Media
Interfaces vs. Concrete Classes
May 26, 2008 8:24 PM
When designing architectures in .NET, I frequently use interfaces for parameter types in my method signatures. This post will help to explain why I choose to do this and the benefits of coding in this manner.

Let's just say that you had the following two methods implemented in your data-access layer. The first calls the database and returns a result set to the SqlDataReader. The second method fills the a list of articles by iterating through the result set in the SqlDataReader and adding an article to the list for each row in the result set. Let's assume it looked like this:

public IList<Article> Get()
{
    SqlConnection connection = new SqlConnection(_connectionString);
    SqlCommand command = new SqlCommand();
    command.Connection = connection;
    command.CommandType = CommandType.StoredProcedure;
    command.CommandText = "GetAllArticles";
 
    SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleResult);
 
    return FillArticles(reader);
}
 
private IList<Article> FillArticles(SqlDataReader reader)
{
    List<Article> articles = new List<Article>();
    while (reader.Read())
    {
        Article article = new Article();
        article.ArticleID = (int)reader["ArticleID"];
        article.Title = reader["Title"];
        article.Body = reader["Body"];
        article.Published = (DateTime)reader["Published"];
        articles.Add(article);
    }
    return articles;
}

As you can see, the FillArticles method is expecting a SqlDataReader (a concrete class). Now let's assume that you are told that articles will no longer be stored in the database, but rather in XML files. In order for you to make this change, you will need to refactor the Get() method to handle XML access and then pass an XmlDataReader to the FillArticles() method. Unfortunately, you will get an error because it is expecting a SqlDataReader.

How do we fix this? Well, in short, both SqlDataReader and XmlDataReader implement an interface called IDataReader which requires these methods to be defined: Read, NextResult, Close, RecordsAffected, etc. By changing the parameter type from SqlDataReader to IDataReader, you can still use the Read() method; however, you can now pass in any concrete class that implements IDataReader. Here is what the refactored code will look like:

private IList<Article> FillArticles(IDataReader reader)
{
    List<Article> articles = new List<Article>();
    while (reader.Read())
    {
        Article article = new Article();
        article.ArticleID = (int)reader["ArticleID"];
        article.Title = reader["Title"];
        article.Body = reader["Body"];
        article.Published = (DateTime)reader["Published"];
        articles.Add(article);
    }
    return articles;
}

There are many ways to determine which common base types are available to use as parameters. One feature you can use is the object browser provided by .NET (Alt + Ctrl + J); search for the concrete class and expand the base types folder to see which are implemented. Additionally, ReSharper will tell you if you can refactor the parameter type based on which methods you use. Finally, Lutz Roeder's .NET Reflector will allow you to find the base types for each class.

Thinking about future issues and maintenance problems while developing projects will save lots of heartache when design changes are made late in the process. I hope this made sense. If I can clarify anything, please let me know.

Update: as an astute reader pointed out, there is no XmlDataReader - only XmlReader - and it doesn't implement IDataReader. I'll make sure to do my research before posting next time - to help avoid any confusion. <s>
Return to Previous Page
Comments
Comment posted on May 27, 2008 2:41 PM
Jake Seward
Nice post explaining the use of interfaces and reducing dependencies while enhancing the reusability of code! Looking forward to more quality content like this in the future.
Jake Seward
Comment posted on Jul 24, 2008 2:31 PM
Rex Morgan
Great example of a solid case where using interfaces is worthwhile and a huge time-saver.

It seems like there's a large group of developers that can tell you what inheritance is, differences between an interface and an abstract class, etc but when put into a real-world scenario, they fail to use these concepts to their full potential.

As a side note, you could also use the Provider pattern for the Get method and have multiple implementations that can be switched back and forth. (Useful for when the client decides that they want to go back to SQL)
Rex Morgan
Comment posted on Jul 24, 2008 2:56 PM
superjason
I had a similar post - Using objects or repository interface in constructor:
http://www.ytechie.com/2008/07/using-objects-or-repository-interface-in-constructor.html
superjason
Comment posted on Jul 24, 2008 3:11 PM
Tim
Minor correction:

however, you can now pass in any concrete class that implements IDataReader <strike>as a base type</strike>.
Tim
Comment posted on Jul 24, 2008 4:06 PM
Brian Lowry
Thanks Tim, I'll make that correction.
Brian Lowry
Comment posted on Jul 24, 2008 4:54 PM
Xerxes
I'm surprised that noone has mentioned the benefit to Unit Testing by taking this approach.

By implementing via interfaces, you're decoupling your routine from the database and could easily inject your own mock IDataReader in order to test the FillArticles() method.

Its a very handy pattern for breaking dependencies.
Xerxes
Comment posted on Jul 24, 2008 4:58 PM
Brian Lowry
@Xerxes

I agree wholeheartedly. This article is going to be a lead-in to an article I'm working on now covering the advantages of dependency injection (i.e. unit testing) and how to implement DI using the Windsor framework.
Brian Lowry
Comment posted on Jul 25, 2008 12:55 AM
Hmmm
I searched for XmlDataReader found nothing...Are you making it up to suit your article?
Hmmm
Comment posted on Jul 25, 2008 1:02 AM
Brian Lowry
I didn't look it up before I wrote the article [it is XmlReader] and I really thought that XmlReader implemented IDataReader. Reflector says otherwise... let's just say I made it up for purposes of this article. <g>
The concept is the important part.
Brian Lowry
Comment posted on Jul 25, 2008 10:17 AM
Nikola Malovic
I agree with pasing most abstract form as a parameter but disagree with applying same principle on returning values.

IMHO, returning values have to be the most concrete types you can use (in this case Collection<Article>) so the user wouldn't have to guess what kind of collection cast to IList he would be getting

Nice article!


Nikola Malovic
Comment posted on Jul 25, 2008 12:09 PM
Brian Lowry
@Nikola

I believe returning values from a method follows the same principles. For example, IList, IEnumerable, etc. have generic definitions that you can use (IEnumerable<Article>), so the user won't have to guess what type of collection is being returned. Doing this allows me to return any type of collection that implements IEnumerable, which there are many.

The only exception I can think of is WCF or web services wherein you must return a concrete class or collection to the calling client.

Brian Lowry
Comment posted on Jul 25, 2008 5:22 PM
An Phu
I don't like passing IDataReader around as a parameter or return value, especially in a public API. You have not control over the lifetime of the instance. It also opens up a possible scenario where you're holding on to an opened connection to an scarce resource longer than you need to.

If you create the reader inside your method, you have control of the lifetime of the concrete reader. Not to mention you open the connection right where you need to and close the connection as soon as you done with the reader.

An

An Phu
Comment posted on Jul 25, 2008 5:29 PM
Brian Lowry
While this is just an example, I'm curious to know how you would map the datareader to objects in a repeatable way without passing IDataReader to a mapping method. I definitely agree that it should not be passed to another layer in the API, but in this instance, the FillArticles method is marked as private, so nothing else but that class can access it.

If you had three "Get" methods in the repository, I don't clearly see how you could avoid repeating logic.
Brian Lowry
Comment posted on Jul 25, 2008 5:32 PM
Brian Lowry
I was just reviewing the code and realized that there is no fake code in there to open and close the reader. My intentions were to have done this in the Get() method - not the FillArticles() method.

Typically, I would use a delegate that handled opening and closing the connection and the code that ran inside would be the FillArticles method... it is basically the same as a using statement.

Thanks for pointing out the lack of clarity there...
Brian Lowry
Comment posted on Jul 28, 2008 9:38 PM
Sam
I would like to know the difference between abstract classes and interfaces. One day I read several books for 5 hours on this and I still don't know :)
Sam
Comment posted on Jul 28, 2008 9:50 PM
Brian Lowry
I'll write an article about this topic soon, but here is a brief summary.

An interface has methods, properties, and such that an implementing class MUST define. The interface has no method body.

An abstract class is similar to some degree, but CAN contain method bodies, but can also contain interface-like definitions. What this means is that you could have a base abstract class that provides default functionality for one method and a definition for another method (with no body) that the inheriting class must implement.

public abstract class ArticleService
{
public abstract string GetTitle();

public virtual string GetName(Article article)
{
return article.Name;
}
}

The inheriting class must have an implementation for GetTitle() and can use GetName or override GetName to behave differently.

I'll cover more in the post.
Brian Lowry
Comment posted on Jul 29, 2008 3:06 AM
Deepak
Another benefit of using interfaces is realised while writing unit tests. Technologies such as mocking can be used to test methods which take in interfaces.
Deepak
Comment posted on Jul 29, 2008 3:19 AM
Brian Lowry
That is definitely a huge benefit. I feel many developers don't use unit testing, which is one reason I stayed away from going into detail about it. I would like to explain the benefits from another point of view and then show how easy unit testing can be implemented from that point forward.

Thanks for your feedback.
Brian Lowry
Comment posted on Jul 29, 2008 6:29 AM
Ian Marteens
The funny side of this is that Microsoft oficially (and wrongly, imho) favors classes over interfaces. I think that the oficial recommendation is a relic from COM times.

One more point: I have noticed there's some performance difference between calling virtual methods on a base class and calling those same methods via an interface. The latter is faster, but I haven't investigated the reason yet.
Ian Marteens
Comment posted on Jul 29, 2008 6:42 AM
Xerxes
@Ian: re COM being the reason that MS favours one over the other - that can't be right.

The whole essence of COM is based around working with interfaces because they are the only things that you can rely on in an interoperability platform.

The reason might be something else, but it certainly wouldn't be COM.
Xerxes
Comment posted on Jul 29, 2008 11:31 AM
Smitty
"I'll make sure to do my research before posting next time..."

That might just be a first for a .NET blogger !
Smitty
Comment posted on Aug 1, 2008 10:51 AM
Jody Breshears
"The funny side of this is that Microsoft oficially (and wrongly, imho) favors classes over interfaces. "

Well, I too don't really know WHY they do so, but Oh My God do they! I just finished 3 very frustrating days trying to get a mockable framework around the WPF Routed Command setup. I ran into an endless wall of concrete classes with no usable interface, non virtual methods, and sealed classes. SEALED CLASSES for God's sake! Why in the world would you EVER need a sealed class (other than to guarantee there was no easy way to mock it.)

Brian, I was extremely pleased to see this article on the VS start page. Now if you can just make it required reading over on the .Net Framework team....
Jody Breshears
Comment posted on Aug 4, 2008 3:21 PM
Edgar Cohen
I am a newbie learning OOP and C#. I understand some of what you are talking about. Question: what about say passing in SqlDataReader and OleDBDataReader. I looked and the only class they have in common is DdDataReader which is an abstract class. I would like to make this even more flexible. Is this possible and how would you do it? Thanks.

Ed Cohen
Edgar Cohen
Comment posted on Aug 4, 2008 3:22 PM
Edgar Cohen
Correction, I meant to say DbDataReader!
Ed Cohen
Edgar Cohen
Comment posted on Aug 4, 2008 4:41 PM
Rex Morgan
Edgar,

It's true that both of those classes inherit from DbDataReader, however according to http://msdn.microsoft.com/en-us/library/system.data.common.dbdatareader.aspx, DbDataReader implements the IDataReader interface.

So you should still be able to use IDataReader for the parameter type.

I hope this helps.
Rex Morgan
Comment posted on Aug 4, 2008 4:47 PM
Brian Lowry
Edgar,

Rex is right, you can still use IDataReader if the abstract class implements it. On the other hand, if there is a method that is part of DbDataReader that is not part of IDataReader, and you want to use that method, then you can use the abstract class as the parameter instead of the interface.

Really, you want to use the least common denominator for the methods you need.
Brian Lowry
Comment posted on Aug 4, 2008 6:50 PM
Edgar Cohen
Thank you!! One of these days, I'll really get all this right. Thanks again.

Ed Cohen
Edgar Cohen
Comment posted on Aug 5, 2008 12:28 PM
David Nelson
@Ian, Jody:

The reason why classes should be favored over interfaces has been described in numerous articles and blog posts (and it has nothing to do with COM). Here is a sampling:

http://blogs.msdn.com/abhinaba/archive/2006/02/13/530824.aspx
http://blogs.msdn.com/kcwalina/archive/2004/10/24/246947.aspx
http://kirillosenkov.blogspot.com/2007/08/choosing-interface-vs-abstract-class.html
http://blog.jpboodhoo.com/CodingToInterfaces.aspx

It is also discussed at length in the book "Framework Design Guidelines" by Krzysztof Cwalina and Brad Abrams, two of the primary architects of the .NET framework. I highly suggest you read this book, not just for this topic but for the many other design topics that are covered.

It is a very narrow perspective to say that the only reason to seal a class is to prevent mocking. The very functionality that allows you to easily create a mock is the same functionality that could allow malicious code to change the behavior of a base class in a manner that could harm end-users of a library. Class designers have to take these considerations into account when deciding whether or not to leave a class open for anyone to modify.
David Nelson
Comment posted on Aug 5, 2008 10:03 PM
jd
Brian,
I have to ask - as i am learning my way through the c# world. but what exactly does one gain with interface parameter? your example seems clear as its using in built objects.

say you built a custom interface and custom classes, how exactly is this beneficial then say delegates?
jd
Comment posted on Aug 17, 2008 4:58 PM
Brian Lowry
@JD,

The benefits of using interfaces is extensibility. If you build a custom interface and a custom class that implements the interface, you have two options for passing those through as a parameter.

You can make the parameter a class:

public GetArticlesFromReader(Reader reader){}

or you can make the parameter an interface:

public GetArticlesFromReader(IReader reader){}

In the first example, if you need to change the functionality of the reader, you will have to actually change the Reader class (which make break code elsewhere), because you've defined that parameter as only accepting a Reader class.

In the second example, if you need to change the functionality of the reader, you can create a new class that implements the IReader interface and pass that through instead.

Does this make sense?
Brian Lowry
Comment posted on Aug 29, 2008 11:32 AM
Chamy
Thanks,

This is a nice post. I have a doubt, I have read somewhere using interface is even though extensibility but its is performace overhead. The program have to decide what type and stuff on runtime. But using concrete class faster and efficient.

Am i missing something here?


Chamy
Comment posted on Sep 1, 2008 4:23 AM
jan smit
Chamy,

For most business apps, the dominant factors are: database access (for performance) and how fast you can develop the software (for cost), so I wouldn't worry too much about performance of interfaces.

Best regards, Jan
jan smit
Add Comment