Method Regulator Pattern

(skip ahead to download here)

This blog’s thusfar most popular post, The Getter Setter Debate, spawned this comment from Wolter:

“Just put them in the same package and set them to package-private.
Or put warnings in the API documentation that the getters/setters are for internal use only, and are likely to change.”

While this is a viable solution, I strive for maximal generality. Granted, Java and .NET support the concept of package or “friend” access. Even so, this is language and/or platform dependent, and it can force some awkward package organization in some situations.

Since the thought-provoking idea of avoiding getters occurred to me, I’ve come to the following conclusion: yes, they should be avoided as much as possible, but no, you can’t avoid them completely. They are needed for legitimate uses, such as UI mapping and persistence.

And now, the natural question arises: if you are on a large team, how do you enforce this policy?

There is the possibility of manual intervention. Indeed, many teams employ code reviews and walkthroughs, and every instance of an accessor method being used can be scrutinized. A small example of domain-driven design called TimeAndMoney takes this approach in the file Money.java:

 /**
* How best to handle access to the internals? It is needed for
* database mapping, UI presentation, and perhaps a few other
* uses. Yet giving public access invites people to do the
* real work of the Money object elsewhere.
* Here is an experimental approach, giving access with a
* warning label of sorts. Let us know how you like it.
*/
public BigDecimal breachEncapsulationOfAmount() {
    return amount;
}

public Currency breachEncapsulationOfCurrency() {
    return currency;
}

Certainly, as the author of this class, you are discouraging other developers from using a method in their code with the substring “breachEncapsulation”. And giving the power to the class author is a step in the right direction.

Approach

But you know me. I’m never happy with anything. I’m especially not content with relying on others to behave. It rarely works.

This got me thinking of a pattern-based solution, one where only certain classes are authorized to use another class’s getters and setters, and violation of such would cause run-time problems like exceptions.

I began tinkering around with this approach and came up with the Method Regulator Pattern:

The heart of this setup is the Regulator. It keeps track of a type that is being regulated and a list of types that are authorized to use regulated methods of that type.

What is a regulated method? It is up to the class that wants to be regulated to, first off, inherit from the Regulated Object class, and second, call the inherited authorizeCaller method as the first statement in every method that should be regulated.

The Regulated Object base class uses the process-global Regulated Types class to look up all of the Regulators for the class that called authorizeCaller, including those inherited from base classes and interfaces. Then, for each Regulator, if at least one of them authorizes the method call, the authorization succeeds. Otherwise, indicate failure somehow, like with an exception.

The burning question remains: how does authorizeCaller know the type of the caller? This will depend on your platform, but your platform must have some kind of reflective capability. Both Java and .NET support the ability to query the activation stack: getStackTrace in Java and StackTrace in .NET.

Example

I would never be one to just describe something very abstractly, wave my hands at it, and declare that it works. What am I, a professor? I went ahead and implemented this pattern in C#. You can download it here. Included is a set of NUnit tests.

Another burning question: what prevents some mischievous or misinformed coder from highjacking an instance of a Regulator, twiddling with it to allow access to a specific type to their new class, and rendering this scheme impotent?

This is an implementation issue, and I chose to deal with it by providing methods to close or “lock” a regulator once we’re finished authorizing types. I also do the same for trying to replace an entire Regulator for a given type with a new Regulator.

Some of you are confused. I’m confused as well. I think an example will clear up what is going on.

Suppose you have the following relatively complicated class hierarchy of five classes, each of which has some getters that you’d like to regulate:

Attached to each class in that diagram is a note indicating which classes are allowed to call getters on each class. It is important to note that authorized callers in a base class should be inherited by a subclass to preserve the Liskov Substitution Principle.

Speaking of which, suppose there are five calling classes like so:

Therefore, the classes authorized to use the accessors of class Sub1 are Caller2, Caller1, and Caller5, the latter two inherited. Also, since Caller3 and Caller4 implement Interface1, we could just as easily authorize Interface1 for Sub3 instead of the two classes individually.

Here is some code for setting up who can call accessors on who:

public void Setup()
{
MethodAccessRegulator superReg = new MethodAccessRegulator(typeof(Super));
superReg.addAuthorizedType(typeof(Caller1));
superReg.closeRegulator();

RegulatedTypes.addRegulatedType(superReg);

MethodAccessRegulator sub1Reg = new MethodAccessRegulator(typeof(Sub1));
sub1Reg.addAuthorizedType(typeof(Caller2));
sub1Reg.closeRegulator();

RegulatedTypes.addRegulatedType(sub1Reg);

MethodAccessRegulator subInterfaceReg = new MethodAccessRegulator(typeof(SubInterface));
subInterfaceReg.addAuthorizedType(typeof(Caller5));
subInterfaceReg.closeRegulator();

RegulatedTypes.addRegulatedType(subInterfaceReg);

MethodAccessRegulator sub2Reg = new MethodAccessRegulator(typeof(Sub2));
sub2Reg.addAuthorizedType(typeof(Caller2));
sub2Reg.closeRegulator();

RegulatedTypes.addRegulatedType(sub2Reg);

MethodAccessRegulator sub3Reg = new MethodAccessRegulator(typeof(Sub3));
sub3Reg.addAuthorizedType(typeof(Caller3));
sub3Reg.addAuthorizedType(typeof(Caller4));
sub3Reg.closeRegulator();

RegulatedTypes.addRegulatedType(sub3Reg);
}

Here is some code for Super:

public class Super: MethodAccessRegulatedObject
{
private int _x;

public int x
{
get
{
authorizeCaller(this);
return _x;
}
}
}

Boring; only one member to protect, but it gets the point across.

Now if, say, Caller2 is defined in this way:

public class Caller2
{
public void useSub1()
{
int i = (new Sub1()).x;
}

public void useSub2()
{
int i = (new Sub2()).z;
}

// inherited access
public void useSub3()
{
int i = (new Sub3()).x;
}

// should throw exception
public void useSuper()
{
int i = (new Super()).x;
}
}

and then we use Caller2 like this:

public void TestSingleInheritance()
{
(new Caller2()).useSub1();
(new Caller2()).useSub2();

try
{
(new Caller2()).useSuper();
Assert.Fail();
}
catch (MethodAuthorizationException ex)
{
Console.WriteLine(ex.Message);
}
}

the first two calls will succeed, while the second one will throw a MethodAuthorizationException with message “An object of type Caller2 attempted an unauthorized method call on class Super”.

Catches

  • First, we make use of this StackTrace class, and we kind of assume where we are in the stack. This approach, as I have implemented it, breaks if you build the download in Release mode, because calls to InvokeMethodFast are inserted instead of the actual calling class.
  • Second, a much better way for client classes to declare their desire to be regulated would be to use Aspect-Oriented Programming. I do not have experience with AOP yet, so this is a future enhancement. I also wanted a lightweight approach for the blog, instead of telling you to download something like NAspect.
  • The “locking” aspect mentioned above (all the code in that Setup() function) is only effective if you can, within your organization, centralize the creation and instantiation of the Regulated Types object and the constituent Regulators.
  • Finally, all of this has to happen within a single process, though I think if you are distributing your objects, you might have more pressing problems.
  • This entire scheme might be rendered impotent by reflection.

I look forward to some feedback on the practicality, usability, and security of this approach.

About these ads

10 Responses to “Method Regulator Pattern”

  1. MoffDub -

    I like the way you’re thinking about the problem, but perhaps we are working a little too hard to solve it.

    Using the method regular pattern is all getting a little too complex for me. Perhaps an alternative naming strategy could do great things for the abuse of getters and setters, so in the timeandmoney example the use of ‘breachEncapsulation’ (or whatever as long as its not get) could stop people in their tracks just enough to make them think.

    Playing devil’s advocate for a moment, just how much does exposing a Currency object do harm in that example? It may or may not be optimal in the context, but to me, its a lot better than exposing a BigDecimal for amount. If an object has self contained business behaviour, its probably not going to be *as* dangerous to expose it as it would have been if the Currency object was a String instead.

    My belief is that we are trying to go too far with something to make up for the fact that education is not where it should be and I think that its not necessarily practical or even desirable to try and fix all problems with brute strength. Rails folk like to use convention over configuration and this is probably an instance of that type of thinking. Perhaps recognizing weaker/less experienced developers and holding some workshops and explaining the problem, or using code reviews and ensuring that the whole team is on the same page and thinks carefully is a practical, workable and simple solution to this type of problem.

    Wouldn’t be too sure that aspects are a better way of doing this. While I don’t want to preach to anyone on the subject, it can really hit you in a very painful way if you get aspects wrong and I know of a few people who have tried them and chosen to stay away. Not to say that with enough time and energy you couldn’t make them work. Don’t forget though, that it’s not about being clever, its about delivering business value to your customer.

  2. moffdub Says:

    Thanks for the feedback. A naming convention could certainly work, but code reviews to catch this specific problem require expensive human labor. A search through all source files could work, but in the absolute worst case, someone who wants to side-step this convention can try all sorts of ways to obfuscate the detection of a getter method.

    Exposing the Currency object is definitely a step forward as opposed to exposing a type with no domain behavior. Even better would be to expose a Currency interface for the obvious reasons of changing the implementation later down the road.

    The thrust of the problem is discouraging users of a particular class from doing the work that your class can do. Granted, a Currency object is likely to have behavior associated with it, but if the class that uses the Currency object as a private member does a lot of useful work with that member, you face the same problem, in some cases.

    You are correct in saying that education is the root of this problem, and I am not advocating my little “pattern” here as a replacement, but rather as a cheaper way to bring attention to the code and/or developers that might be violating this principle.

    Re: aspects, interesting take, and right now I agree with you. Probably for this example, AOP would’ve been overkill and would’ve detracted from the business value you are trying to deliver.

  3. Miguel Barrosa Says:

    Hi there! I came across this post and found it interesting. Can you re-post the code because the geocities link doesn’t work anymore?

    Thanks,
    Miguel Barrosa

  4. I will try to do that soon.

  5. - decouple the gui or whatever via simple transfer objects…
    - reflection/factories for full decoupling… it’s just a demo

    http://pastebin.com/f538134e7

    any use?

    just in case…

    m2c

  6. Interesting approach… Probably mixes non-business logic and reflection a little too much fir by tastes.

  7. Miguel Barrosa Says:

    Almost forgot about this… Moffdub, sorry to insist, but could you upload the source code again, please? Thanks a lot!

  8. Link updated… better late than never I guess! Thanks for still being interested.

  9. Miguel Barrosa Says:

    Cool! Thanks a lot! I’ll have a look at it.

  10. stijndewitt Says:

    I like how you think about this. Your pattern looks interesting and if the data to protect is important enough I would use something like that. However, this:

    “It is up to the class that wants to be regulated to, first off, inherit from the Regulated Object class”

    is a big no no!

    Never, ever demand that objects extend from some base class. It makes the implementation completely inflexible. What if my class already extends something else? What if some other piece of code also demand you extend from some base class, but it has to be a different one?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: