-3

I have a situation where it is possible for a user to develop complex requirements using a UI. Specifically it deals with authorising users to perform certain work based on their qualifications.

For example the user must have;

  1. All of These: Qual1, Qual2, Qual3
    • OR (One of These: (Qual4, Qual5) AND (All of These: Qual11, Qual12, Qual13))
  2. AND
    • One or More of These: Qual6, Qual7, Qual8
    • AND One of These: Qual9, Qual10

I've had a look at the Specification Pattern but I'm not sure if this is the best solution for the problem.

The requirements for each role are stored in the database using an Authorisation table linked to a Qualifications table and the user's training via a Training table linked to the Qualifications table.

Ray
  • 342
  • 5
  • 15
  • This seems fairly obvious. You just want to check if they have the qualifications you specified. I downvoted it because you don't specify technology at all. Are we talking WebAPI or... – Mr. B Jun 21 '16 at 03:59

1 Answers1

1

It seems straightforward to represent such rules in code. To begin with, you're making it way too complicated. "And" and "all of" are both just "all", and "one or more" and "or" are both just "any". So you only need a few predicates:

abstract class Requirement 
{
   abstract public bool Satisfied(User user);
}
sealed class Qual1 : Requirement { ... }
sealed class Qual2 : Requirement { ... }
...
sealed class All : Requirement 
{
   private IEnumerable<Requirement> r;
   public All(params Requirement[] r) { this.r = r; }
   public All(IEnumerable<Requirement> r) { this.r = r; }
   public override bool Satisfied(User user) {
     return r.All(x => x.Satisfied(user));
   }
}
sealed class Any : Requirement 
{
   ....

So now you just have to say:

var q1 = new Qual1();
... etc ...
var rule =  All(
              Any(
                 All(q1, q2, q3), 
                 All(
                     Any(q4, q5), 
                     All(q11, q12, q13))), 
              All(
                Any(q6, q7, q8), 
                Any(q9, q10)));

And now you can say:

if (rule(user)) ...

Easy peasy.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Thanks @Eric but as I can't hard code the rule as the user builds the conditions through the UI. How would I go about dynamically parsing the conditions in code? – Ray Jun 21 '16 at 04:34
  • @Ray: So, how is that any different? You've got objects. You've got a UI that manipulates objects. Write a UI that takes in actions from the user and constructs objects; **that's what UIs do**. – Eric Lippert Jun 21 '16 at 05:18