Wiki

Clone wiki

C# RuleDocs / Example

Home

#Example: FizzBuzz As noted before FizzBuzz, is container that has various sub-rules injected into it. Its version of CreateDocumentation() looks like this:

public RuleData CreateDocumentation()
{
    var docs = RuleData.Construct("FizzBuzz",
        "Rules for processing FizzBuzz", this)
        .AddData("RuleType", "Container for IRules");
    for (int i = 0; i < _rules.Count; ++i)
    {
        docs.AddChild(_rules[i])
            .AddData("Parent", "FizzBuzz")
            .AddData("RuleOrder", i + 1);
    }
    docs.AddChild(_defaultRule)
        .AddData("Parent", "FizzBuzz")
        .AddData("RuleOrder", _rules.Count + 1);
    return docs;
}

Since the FizzBuzz class is a container that processes other rules, we are calling AddChild() with an additional key value pair that specifies the order in which the rules are being executed.

Design Note: an important factor in this code is that the rules are added to the documentation in the exact same order as they are ran when processing data. This means that when we look at the documentation, we will know the exact order of processing that is occurring with the data. This is why each sub-rule is explicitly added, and reflection is not used. We want to know the exact order, and that is something that reflection cannot guarantee.

###KeywordRule One of the rules that was injected into FizzBuzz was the KeywordRule. Its CreateDocumentation() looks like this:

public RuleData CreateDocumentation()
{
    var docs = RuleData.Construct("Keyword Rule",
        "Will insert the keyword into the formatter if the condition is met.", this)
        .AddData("Keyword", _keyword)
        .AddData("RuleType", "IRule with IConditionValue and IFormatter<String>")
        .AddData("Input", "StringBuilder int")
        .AddData("Output", "StringBuilder");
    docs.AddChild(_condition).AddData("Parent", $"KeywordRule({_keyword})");
    docs.AddChild(_formatter).AddData("Parent", $"KeywordRule({_keyword})");
    return docs;
}

Since KeywordRule is focused on the keyword it contains, that data is inserted into the documentation. It also inserts that it is a rule type that is a container for a condition and formatter.

Finally, it adds the condition and formatter instances to itself.

###ValueIsMultipleOf This condition is injected into KeywordRule. Its CreateDocumentation() looks like this:

public RuleData CreateDocumentation()
{
    return RuleData.Construct("ValueIsMultipleOf",
        $"Checks to see if the value is a multiple of {_mod}",
        this)
        .AddData("RuleType", "IConditionValue")
        .AddData("ConditionType", "Modulus")
        .AddData("Input", "int")
        .AddData("Output", "true/false")
        .AddData("ReturnValue", $"true if value is a multiple of {_mod}");
}

It adds in that its RuleType is a Condition, with a specific type of Modulus, and that it takes an int as its input. It also specifies that it returns a true or false, and how a true value is determined.

Since ValueIsMultipleOf is leaf node, it does not make any calls to AddChild().

There are additional rules that FizzBuzz uses, but the above set of rules explains the logic that they are using as well.

Updated