tags:

views:

99

answers:

5

Assuming the following domain entity :

public enum Role
{
    User = 0,
    Moderator = 1,
    Administrator = 2
}

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public Role Role { get; set; }
}

I need to know if the user can perform "Edit" action. So i've 2 solutions :

Create a CanEdit method inside the User entity

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public Role Role { get; set; }

    public bool CanEdit()
    {
        return Role == Role.Moderator || Role == Role.Administrator;
    }
}

Create a CanEdit Extension Method for User type :

public static class UserExtensions
{
    public static bool CanEdit(this User user)
    {
        return user.Role == Role.Moderator || user.Role == Role.Administrator;
    }
}

Both solution works, but the question is WHEN use standard methods vs using Extensions methods ?

+9  A: 

Extension methods are simply syntactic sugar for plain, ordinary static methods.

If you control the class structure, you should implement all the necessary functionality within the class. Where extension methods are really useful/necessary is if you don't own the class that you are trying to "extend."

For this example, I think you should put the logic inside the User class. It is a logical function of the user itself; consumers should be able to use the CanEdit() method without having to use or even know about the UserExtensions class.

Aaronaught
+1, Also, using extension methods on Interfaces is a good practice.
Ekin Koc
+1. Extension methods are also invaluable when dealing with interfaces.
Adam Robinson
@Aaronaught : Ok i agree, but so why Microsoft .NET Framework Team implements Extensions Methods on their own types classes ?? Why not implement functionnalities within the classes directly ?
Yoann. B
@Yoann. B - They generally don't, they implement extension methods on *interfaces* (like `IEnumerable<T>`), which makes sense because an interface can't have actual code (but at the same time, the operations are always exactly the same). Also in some cases because interfaces were from .NET 2.0 or earlier and extension methods are by definition non-breaking changes (thus easier to implement safely).
Aaronaught
Yoann: Most of the extension methods in the framework are on interfaces. The LINQ authors couldn't have added their extension methods to the BCL's `IEnumerable<T>` class because interfaces can't contain implementation, and LINQ needed implementations.
itowlson
Take `IEnumerable.Select` for example; the .NET team could either add it to the interface definition and then add copy-and-paste code to every single one of the dozens of classes implementing `IEnumerable<T>` - or they could add one extension method in one place to accomplish the same thing. The latter was a much cleaner design. If you had 20 different `User` classes all implementing an `IUser` interface then I might suggest adding an extension method to the `IUser` interface instead - if the same task couldn't be accomplished by an abstract base class.
Aaronaught
+1  A: 

There is very little point in using Extension methods for the sake of using them. If the method belongs to the class, use it there. Extension methods are for extending things, use them when you have no control over the class, or for giving functionality to an interface where the functionality should apply to all classes derived from that interface.

pdr
+1  A: 

if you do not have direct access to the source code for the class you should use Extensions methods if you do have access to the source code i see no reason to not use a standard methods...

Petoj
+1  A: 

I agree with Aaronaught here: Implement your own logic the old-fashioned way. Static method might cause issues (missing using statement and the method seems to be "missing") lateron.

Something inherent to your model should be part of your classes.

Benjamin Podszun
+2  A: 

I mostly agree with Aaronaught's answer, but consider this:

Maybe your CanEdit() method or other similar methods (business rules) might change more or less often or depend on some external factors. Or over time, you will have more and more such rules (for different concerns). In that case you might want to keep them in a different place, separated from the domain model to ensure that the domain model doesn't have too many different responsibilities and doesn't need to change very often.

Then, one way can be to implement them as extension methods, because this allows you to keep these business rules separate from your domain model (e.g. User class), but the method is still easily discoverable by users of the User class.

Another way to implement such business rules would be the specification pattern, where you implement each rule as a separate (specification-) class, e.g. demonstrated in this blog post.

M4N
@Martin: partial classes work well for keeping some code "in a different place" and yet to remain part of the class.
John Saunders
@John: I was more thinking of a separate, exchangeable assembly.
M4N
@Martin: I still don't think I'd use extension methods for this. I'd more likely have a separate business rules class that takes the business object as a constructor parameter, or which has methods that take the business object as a parameter.
John Saunders
@John: "separate business rules class": this is why I added the link to the specification pattern. I'll clarify my answer.
M4N
@Martin: thanks for the link. It would be good to see a real use of that, and it would be better if it used generics, and didn't take an `object` parameter.
John Saunders