enhancement idea: IEnumerable validation rules

enhancement idea: IEnumerable validation rules

Old forum URL: forums.lhotka.net/forums/t/7352.aspx


mongo posted on Tuesday, July 28, 2009

I would love to see a different model for declaring business rules as perhaps an override of returning IEnumerable. I understand looking at .AddRule that there would be more to that structure.

Is that already being/been considered? I would like it from a testability perspective.

RockfordLhotka replied on Tuesday, July 28, 2009

I don't quite follow what you are suggesting?

mongo replied on Tuesday, July 28, 2009

In the current model of adding business rules, we override protected AddBusinessRules and then make a call into the object with ValidationRules.AddRule.

Changing that model, one could provide an override on a method that returns an IEnumerable list of Rules. The key difference is only yielding a list of Rule objects that are internally added by the CSLA object to the ValidationRules collection. This way you can set up a test to verify that an enumerated list of validation rules are being created without having to interrogate the internal state of the csla object (directly or indirectly) after the test is complete.

RockfordLhotka replied on Tuesday, July 28, 2009

So you are suggesting making Csla.Validation.RuleMethod a public class so people can create rule objects and provide them as a list to ValidationRules? Somewhat like this:

 

protected override void AddBusinessRules()

{

  var rules = new List<RuleMethod>();

  rules.Add(new RuleMethod(Csla.Validation.CommonRules.StringRequired, new RuleArgs(…));

  rules.Add(new RuleMethod(Csla.Validation.CommonRules.StringMaxLength, new MaxLengthRuleArgs(…));

  ValidationRules.AddRules(rules);

}

 

There are two RuleMethod classes – one generic, one not, so both would need to be public. And the AsyncRuleMethod types would probably be affected as well.

 

The RuleMethod.Invoke() method would need to become internal, as that shouldn’t be invoked by arbitrary callers.

 

On the surface this doesn’t seem too hard to do, though I can see where RuleMethod might need another ctor overload that accepts an IPropertyInfo as second parameter to keep the calling code simpler.

 

Is that what you have in mind?

 

Rocky

 

mongo replied on Tuesday, July 28, 2009

slightly different but that gives a thought on a potentially? clean way to implement for existing users -

client implements:
public override IEnumerable EnumerateBusinessRules()
{
yield return new RuleMethod(...);
yield return new RuleMethod(...);
}


the framework implements:

protected override void AddBusinessRule()
{
foreach(RuleMethod rulein EnumerateBusinessRules())
ValidationRules.Add(rule);
}

The user can now test that the necessary csla implementation (reduced to the EnumerateRules method) is returning details as needed. The proposed csla internal override would allow current customers to continue coding unimpeded.

Thanks again,
-Steve

mongo replied on Tuesday, July 28, 2009

Not sure that public would be necessary - perhaps protected or internal?

mongo replied on Tuesday, July 28, 2009

My apologies - burning through a set of businessbase/lsitbase implementations along with configuring invariant tests for the various types and a bit distracted.

I meant to say:

public override IEnumerable EnumerateBusinessRules()
{...}

mongo replied on Tuesday, July 28, 2009

I think it should also reduce cyclomatic complexity in that function.

Thank you Rocky,
-Steve

RockfordLhotka replied on Tuesday, July 28, 2009

This is a good discussion, I really appreciate your input!

I don't think I'd name the method quite like that, because it implies enumerating over an existing list. When in reality it is creating the list. It is a personal naming convention I tend to use, where methods that construct things have names that provide an indication of their expense. I'd probably call it something like GetBusinessRules().

I also wouldn't make the method public. I realize you want it for testing, but encapsulation is at least as important as testability (for long term maintainability and readability). Outside of testing, it is hard to imagine a scenario where anyone would or should get the class to generate a rule list.

For all that we're discussing an instance method here, the reality is that CSLA will use it as a static method - it will be called exactly once per AppDomain to construct the static rule list. I agree that it needs to be a virtual instance method.

I also think having ValidationRules.AddRules() is a nice idea. The reason being that you could externalize the generation of the rule list. It would not strictly need to be contained inside your business class (and some people do externalize this today).

Not to say that the base implementation couldn't do as you suggest by calling AddRules(), but having an AddRules() method may open up other scenarios for aggregation of rule lists into an object.

fyi, I have added this to the wish list, tagging this thread with the item so what we're discussing here will inform what I do if/when I make this change.

mongo replied on Tuesday, July 28, 2009

That sounds great - thanks for taking a look at this Rocky.

-Steve

Copyright (c) Marimer LLC