views:

495

answers:

4

Hi Y'all,

I have just started to look at .NET 3.5 so please forgive me if this type of question have been asked before. I am struggling with a decent usage for extension methods, in that I have just downloaded suteki shop an MVC ecommerce offering. In this project there is a pretty standard Repository pattern that extends IRepository.

In order to extend the basic functionality exposed by this interface, extention methods are used i.e.:

public static class CategoryRepositoryExtensions
{
    public static Category GetRootCategory(this IRepository<Category> categoryRepository)
    {
     return categoryRepository.GetById(1);
    }
}

Now this is all well and good, but Interfaces, as far as I am concerned act as contracts to the objects that implement them.

The fact that the repository has been interfaced out suggests an attempt at a data layer agnostic approach. That said, if I were to create my own data layer I would be confused as to what extension methods I would have to create to ensure I have fulfilled the contractual requirement I have to the classes that implement my repository classes.

It seems that the older way of creating an IRepository and then extending that allows a much better visibility of what is required e.g.

ICategoryRepoitory : IRepository<Category>
{
     Category GetRootCategory();
}

So I guess my question is does this use of Extention methods seem wrong to anyone else? If not, why? Should I not be moaning about this?

EDIT:

The above example does seem to be a good example of why extention methods can be very helpful.

I suppose my issue is if data access specific implementations were stuck in the extention method in the data access mechanisms assembly.

That way if I were to swap it out for another mechanism I would have to create a similar extention method in that assembly.

+4  A: 

The point is that if you've implemented all of IRepository<T> appropriately, you (as the data layer implementor) don't have to know about root categories at all. For the scope of this extension method, it is assumed that any repository of categories will have a root category of ID 1. That may well be a perfectly reasonable assumption, and a useful one: no-one has to build a derived class (which may well be impractical - the data layer may have factories etc which make it tricky to derive from the implementations).

Now, the extension method is only applicable if its scope is appropriate - if it's in a namespace (or closely related one) where that assumption about root categories will be valid.

I don't think the "older" way would really be an interface extending IRepository<Category> - it would be a normal static method taking IRepository<Category>. That's where extension methods just make life more pleasant. If you really would have used inheritance instead, it may well be appropriate to do so now as well. Unfortunately we don't know enough about the architecture of your system to say that for sure.

Jon Skeet
Good point, I see more clearly the benifit of extention methods now. Cheers for the clarification.
Owen
+1  A: 

It's not the same thing. An extension method is a syntactic convenience, nothing more, and certainly not a contractual requirement. You don't "implement" them on your own classes. For your example above:

using CategoryRepositoryExtensions;
...
Category c = r.GetRootCategory();

is exactly the same as:

Category c = CategoryRepositoryExtensions.GetRootCategory(r);

and therefore there is no additional requirement on the implementer of the interface.

Sunlight
A: 

Yes in the example you mentioned it does seem counter-intuitive and the reason is because you are working with a single object at a single level. I find that extension methods are most useful when you are working with IQueryable / IEnumerable collections

For eg. lets consider 2 scenarios

Scenario 1 :You need to get list of all orders which contain product x

Scenario 2 : YOu need to get list of all orders which contain product x and have been shipped to zipcode y

If you were using the traditional/interface driven approach you might define 2 be tempted to define 2 different interfaces. If you use extension methods, you could use something like the following

Scenario 1

orders1Enumerable = OrderRepository.GetAllOrders().ContainingProductCode(x);

Scenario 2

orders2Enumerable = OrderRepository.GetAllOrders() .ContainingProductCode(x) .WithShippingZipCode(y);

When you do this, the framework creates the appropriate SQL on the fly by chaining these extension methods

Hope this helps

Thanks -RVZ

A: 

Extension methods concept is just syntactic sugar as some authors call it. It makes the code more readable though less understandable. Ultimately extension methods are just static ones which are the heritage of the procedural paradigm. They make the code tightly-coupled and less cohesive, harder to test and reuse.

I am biased against this tendency of the C# programming language. This feature is attractive but it doesn't bring any benefits, quite the contrary it increases the complexity of the code.

bsnote