views:

172

answers:

2

I have a little dilemma that maybe you can help me sort out.

I've been working today in modifying ASP.NET's Membership to add a level of indirection. Basically, ASP.NET's Membership supports Users and Roles, leaving all authorization rules to be based on whether a user belongs to a Role or not.

What I need to do is add the concept of Function, where a user will belong to a role (or roles) and the role will have one or more functions associated with them, allowing us to authorize a specific action based on if the user belongs to a role which has a function assigned.

Having said that, my problem has nothing to do with it, it's a generic class design issue.

I want to provide an abstract method in my base RoleProvider class to create the function (and persist it), but I want to make it optional to save a description for that function, so I need to create my CreateFunction method with an overload, one signature accepting the name, and the other accepting the name and the description.

I can think of the following scenarios:

  1. Create both signatures with the abstract modifier. This has the problem that the implementer may not respect the best practice that says that one overload should call the other one with the parameters normalized, and the logic should only be in the final one (the one with all the parameters). Besides, it's not nice to require both methods to be implemented by the developer.

  2. Create the first like virtual, and the second like abstract. Call the second from the first, allow the implementer to override the behavior. It has the same problem, the implementer could make "bad decisions" when overriding it.

  3. Same as before, but do not allow the first to be overriden (remove the virtual modifier). The problem here is that the implementer has to be aware that the method could be called with a null description and has to handle that situation.

I think the best option is the third one...

How is this scenario handled in general? When you design an abstract class and it contains overloaded methods. It isn't that uncommon I think...

+1  A: 

I feel the best combination of DRYness and forcing the contract is as follows (in pseudocode):

class Base {
  public final constructor(name) {
    constructor(name, null)
  end

  public abstract constructor(name, description);
}

or, alternatively:

class Base {
  public abstract constructor(name);

  public final constructor(name, description) {
    constructor(name)
    this.set_description(description)
  }

  private final set_description(description) {
    ...
  }
}

There's a rule in Java that supports this decision: "never call non-final methods from a constructor."

James A. Rosen
A: 

To answer the first part of your post, check out AzMan (Authorization Manager), which, incidentally, is built into windows. It has the capability to specify operations which can be recombined into roles or assigned directly to users.

http://msdn.microsoft.com/en-us/magazine/cc300469.aspx

To answer the second part of your question, I wouldn't use an Abstract class. Instead just provide the functionality in the constructor and be done with it. It appeasr you want the specified behavior, and you don't want it to change. Why force descendents to provide the implementation.

Chris Lively