Simple Rules Engine? - c#

I'm looking for some engine that could handle situations like this:
I have an order object, with a customer object attached to it.
Rule:
If order.customer.id = 186 and order.industry = 23 then order.price = 100
I found NxBRE, but it seems overkill for this?
What are other people doing for situations like this? Just hardcode it or use Eval?

I also ran into this dilemma about two years ago, since it was something simple enough, didn't want to go overboard, and time constrain I ended up building something using customized logics interpretation to analyze ==, like, !=, >, etc, using Linq and strategy pattern as the base of the rules evaluation engine
Although if you know Windows Workflow Foundation, then apparently you can leverage its rules engine without having to actually use WF

I also came across similar situations and thought of building my own engine instead of using existing, because when there is any change in my current logic or going on with new grounds it will be a great pain. If we get to know how the engine works we are open for any logic and the best thing is we can build solution to find the local and global optima!
Refer the below link which spoon feeds engine and helped me to create my new engine!
Click here for start up

If you are looking for a much simpler version and want to write your code like this...
[TestMethod]
public void GreaterThanRule_WhenGreater_ResultsTrue()
{
// ARRANGE
int threshold = 5;
int actual = 10;
// ACT
var integerRule = new IntegerGreaterThanRule();
integerRule.Initialize(threshold, actual);
var integerRuleEngine = new RuleEngine<int>();
integerRuleEngine.Add(integerRule);
var result = integerRuleEngine.MatchAll();
// ASSERT
Assert.IsTrue(result);
}
... or like this...
[TestMethod]
public void GreaterThanRule_WhenGreater_ResultsTrue()
{
// ARRANGE
int threshold = 5;
int actual = 10;
// ACT
var integerRule = new IntegerGreaterThanRule(threshold);
var integerRuleEngine = new RuleEngine<int>();
integerRuleEngine.ActualValue = actual;
integerRuleEngine.Add(integerRule);
// Get the result
var result = integerRuleEngine.MatchAll();
// ASSERT
Assert.IsTrue(result);
}
... then maybe check out my blog where I build up a rule engine slowly. http://www.duanewingett.info/2015/01/21/SimpleCRuleEnginePart1TheRuleEngine.aspx

Related

On which level should I test my logic

I have a TextGenerator class, which generates random text using MarkovChain class. Logic to create next word from MarkovChain lives in ChainNavigator class:
public class TextGenerator
{
public List<string> MakeText(int requiredTextLength, string sourceText)
{
var chain = new MarkovChain(sourceText);
var chainNavigator = new ChainNavigator(chain);
var nextWord = chainNavigator.GetNextWord(/*params here*/);
}
}
internal class ChainNavigator
{
internal string GetNextWord(/*params here*/) { }
}
MarkovChain is generated from source text. Source text's last word would not have any 'next state', as it does not have any words after it. When generating long text, ChainNavigator would reach last word and would not know what to return.
I want to test that TextGenerator starts new sentence, when it reaches last word, and this test can be written in 2 places.
On one hand, it makes sense to test this in TextGenerator as it's my external interface:
[TestClass]
public class TextGeneratorTest
{
[TestMethod]
public void ShouldAppendADot_WhenEndOfChainReached()
{
var generator = new TextGenerator();
var sourceText = "free men can remain free or sell their freedom";
var firstWord = "their";
var requiredTextLength = 2;
var text = generator.MakeText(requiredTextLength, sourceText, firstWord);
Assert.AreEqual("freedom.", text[1]);
}
}
On the other hand, the actual tested logic belongs to ChainNavigator class and it would make sense to test it here:
[TestMethod]
public void AppendADot_WhenEndOfChainReached()
{
var sourceText = "free men can remain free or sell their freedom";
var chain = new Chain(sourceText);
var navigator = new ChainNavigator(chain);
var nextWord = navigator.GetNextWord("their", 1);
Assert.AreEqual("freedom.", nextWord);
}
Doing it in both places looks like a duplication. Where is it better to do it?
Your confusion is actually a common one. The source of this is the term "unit" in "unit test". A lot of people will tell you, that the "unit" is something like a single class or even just a single method. People have been telling this for decades now, but it is mostly wrong. The misconception stems from the fact that you rarely see real applications being tested in books, articles, and blogs. Since it hard to show the general principles of unit testing with a full blown application, examples will usually be limited to a very small number of classes. Even Kent Beck is using the famous Money class example, which is mostly limited to a single class, in his book.
Test at the highest level that is not bound to external details. In your limited example TestGenerator might just be the perfect level. It lets you test your business logic fully, without the test breaking when you change the inner structure. Should you ever decide to split the ChainNavigator into multiple classes or join the ChainNavigator with MarkovChain, your test would not need to know and would not break.

What's the benefit of var patterns in C#7?

I don't understand the use case of var patterns in C#7. MSDN:
A pattern match with the var pattern always succeeds. Its syntax is
expr is var varname
where the value of expr is always assigned to a local variable named
varname. varname is a static variable of the same type as expr.
The example on MSDN is pretty useless in my opinion, especially because the if is redundant:
object[] items = { new Book("The Tempest"), new Person("John") };
foreach (var item in items) {
if (item is var obj)
Console.WriteLine($"Type: {obj.GetType().Name}, Value: {obj}");
}
Here i don't see any benefits, you could have the same if you access the loop variable item directly which is also of type Object. The if is confusing as well because it's never false.
I could use var otherItem = item or use item diectly.
Can someone explain the use case better?
The var pattern was very frequently discussed in the C# language repository given that it’s not perfectly clear what its use case is and given the fact that is var x does not perform a null check while is T x does, making it appear rather useless.
However, it is actually not meant to be used as obj is var x. It is meant to be used when the left hand side is not a variable on its own.
Here are some examples from the specification. They all use features that are not in C# yet but this just shows that the introduction of the var pattern was primarly made in preparation for those things, so they won’t have to touch it again later.
The following example declares a function Deriv to construct the derivative of a function using structural pattern matching on an expression tree:
Expr Deriv(Expr e)
{
switch (e) {
// …
case Const(_): return Const(0);
case Add(var Left, var Right):
return Add(Deriv(Left), Deriv(Right));
// …
}
Here, the var pattern can be used inside the structures to “pull out” elements from the structure. Similarly, the following example simplifies an expression:
Expr Simplify(Expr e)
{
switch (e) {
case Mult(Const(0), _): return Const(0);
// …
case Add(Const(0), var x): return Simplify(x);
}
}
As gafter writes here, the idea is also to have property pattern matching, allowing the following:
if (o is Point {X is 3, Y is var y})
{ … }
Without checking the design notes on Github I'd guess this was added more for consistency with switch and as a stepping stone for more advanced pattern matching cases,
From the original What’s New in C# 7.0 post :
Var patterns of the form var x (where x is an identifier), which always match, and simply put the value of the input into a fresh variable x with the same type as the input.
And the recent dissection post by Sergey Teplyakov :
if you know what exactly is going on you may find this pattern useful. It can be used for introducing a temporary variable inside the expression:
This pattern essentially creates a temporary variable using the actual type of the object.
public void VarPattern(IEnumerable<string> s)
{
if (s.FirstOrDefault(o => o != null) is var v
&& int.TryParse(v, out var n))
{
Console.WriteLine(n);
}
}
The warning righ before that snippet is also significant:
It is not clear why the behavior is different in the Release mode only. But I think all the issues falls into the same bucket: the initial implementation of the feature is suboptimal. But based on this comment by Neal Gafter, this is going to change: "The pattern-matching lowering code is being rewritten from scratch (to support recursive patterns, too). I expect most of the improvements you seek here will come for "free" in the new code. But it will be some time before that rewrite is ready for prime time.".
According to Christian Nagel :
The advantage is that the variable declared with the var keyword is of the real type of the object,
Only thing I can think of offhand is if you find that you've written two identical blocks of code (in say a single switch), one for expr is object a and the other for expr is null.
You can combine the blocks by switching to expr is var a.
It may also be useful in code generation scenarios where, for whatever reason, you've already written yourself into a corner and always expect to generate a pattern match but now want to issue a "match all" pattern.
In most cases it is true, the var pattern benefit is not clear, and can even be a bad idea. However as a way of capturing anonymous types in temp variable it works great.
Hopefully this example can illustrate this:
Note below, adding a null case avoids var to ever be null, and no null check is required.
var sample = new(int id, string name, int age)[] {
(1, "jonas", 50),
(2, "frank", 48) };
var f48 = from s in sample
where s.age == 48
select new { Name = s.name, Age = s.age };
switch(f48.FirstOrDefault())
{
case var choosen when choosen.Name == "frank":
WriteLine(choosen.Age);
break;
case null:
WriteLine("not found");
break;
}

Best approach to programming highly complex business/math rules

I have to take a piece of data, and apply a large number of possible variables to it. I really don't like the idea of using a gigantic set of if statements, so i'm looking for help in an approach to simplify, and make it easier to maintain.
As an example:
if (isSoccer)
val = soccerBaseVal;
else if (isFootball)
val = footballBaseVal;
.... // 20 different sports
if (isMale)
val += 1;
else
val += 5;
switch(dayOfWeek)
{
case DayOfWeek.Monday:
val += 12;
...
}
etc.. etc.. etc.. with possibly in the range of 100-200 different tests and formula variations.
This just seems like a maintenance nightmare. Any suggestions?
EDIT:
To further add to the problem, many variables are only used in certain situations, so it's more than just a fixed set of logic with different values. The logic itself has to change based on conditions, possibly conditions applied from previous variables (if val > threshold, for instance).
So yes, i agree about using lookups for many of the values, but I also have to have variable logic.
A common way to avoid large switching structures is to put the information into data structures. Create an enumeration SportType and a Dictionary<SportType, Int32> containing the associated values. The you can simply write val += sportTypeScoreMap[sportType] and you are done.
Variations of this pattern will help you in many similar situations.
public enum SportType
{
Soccer, Football, ...
}
public sealed class Foo
{
private static readonly IDictionary<SportType, Int32> sportTypeScoreMap =
new Dictionary<SportType, Int32>
{
{ Soccer, 30 },
{ Football, 20 },
...
}
private static readonly IDictionary<DayOfWeek, Int32> dayOfWeekScoreMap =
new Dictionary<DayOfWeek, Int32>
{
{ DayOfWeek.Monday, 12 },
{ DayOfWeek.Tuesday, 20 },
...
}
public Int32 GetScore(SportType sportType, DayOfWeek dayOfWeek)
{
return Foo.sportTypeScoreMap[sportType]
+ Foo.dayOfWeekScoreMap[dayOfWeek];
}
}
Use either a switch statement or filter function.
By filter function, I mean something like:
func filter(var object, var value)
{
if(object == value)
object = valueDictionary['value'];
}
Then apply the filter with:
filter(theObject, soccer)
filter(theObject, football)
Note that the filter works much better using a dictionary, but it is not required.
Cribbing from The Pragmatic Programmer, you could use a DSL to encapsulate the rules and write a process engine. For your presented problem, a solution might look like:
MATCH{
Soccer soccerBaseVal
IsMale 5
!IsMale 1
}
SWITCH{
Monday 12
Tuesday 13
}
Then match everything in the first col of MATCH, and the first item in each SWITCH you come to. You can make whatever syntax you feel like, then just write a bit of script to cram that into code (or use Xtext because it looks pretty cool).
Here are a few ideas:
1 Use lookup tables:
var val = 0;
SportType sportType = GetSportType();
val += sportvalues[sportType];
You can load the table from the database.
2 Use the factory pattern:
var val = 0;
val += SportFactory.Create(sportType).CalculateValue();
The Dynamic Factory Pattern is useful in situations were new (sport) types are added frequently to the code. This pattern uses reflection to prevent the factory class (or any global configuration) from being changed. It allows you to simply add a new class to your code.
Of course the use of an dynamic factory, or even a factory can be overkill in your situation. You're the only one who can tell.
As a first step I would probably break up each logical processing area into its own method: (May not be the best names as a first pass)
EnforceSportRules
ProcessSportDetails
EnforceGenderRules
Next, depending on how complex the rules are, I may break each section into its own class and have them processed by a main class (like a factory).
GenderRules
GenderContext
I have nothing special to offer you than to first recommend not to just leave it as a big block-- break it into sections, make comment dividers between important parts.
Another suggestion is if you are going to have many very short tests as in your example, break from convention and put the val incrementors on the same line as the evaluatation and indent so they align with eachother.
if (isSoccer) val = soccerBaseVal;
if (isMale) val += 1;
else val += 5;
switch(dayOfWeek){
case DayOfWeek.Monday: val += 12;
...
}
Excess whitespace can make those hundred things into several hundred lines, making vertical scrolling excessive and difficult to get an overall view of the thing.
If you are really just adding values in this sort, I would either create an enumeration with defined indices that correspond to stored values in an array. Then you can do something like this:
enum Sport
{
football = 0,
soccer = 1,
//...
}
int sportValues[] = {
/* footballValue */,
/* soccerValue */,
/* ...Values */
};
int ApplyRules(Sport sport, /* other params */)
{
int value = startingValue;
value += sportValues[(int)sport];
value += /* other rules in same fashion */;
}
Consider implementing the Strategy Pattern which utilizes inheritance/polymorphism to make managing individual functions sane. By seperating each function into its own dedicated class you can forego the nightmare of having miles-long case blocks or if statements.
Not sure if C# supports it yet (or ever will) but VB.NET integrates XML Comment CompletionList directives into intellisense, which--when combined with the Strategy Pattern--can give you the ease of use of an Enum with the open-ended extensibility of OO.

How to force c# binary int division to return a double?

How to force double x = 3 / 2; to return 1.5 in x without the D suffix or casting? Is there any kind of operator overload that can be done? Or some compiler option?
Amazingly, it's not so simple to add the casting or suffix for the following reason:
Business users need to write and debug their own formulas. Presently C# is getting used like a DSL (domain specific language) in that these users aren't computer science engineers. So all they know is how to edit and create a few types of classes to hold their "business rules" which are generally just math formulas.
But they always assume that double x = 3 / 2; will return x = 1.5
however in C# that returns 1.
A. they always forget this, waste time debugging, call me for support and we fix it.
B. they think it's very ugly and hurts the readability of their business rules.
As you know, DSL's need to be more like natural language.
Yes. We are planning to move to Boo and build a DSL based on it but that's down the road.
Is there a simple solution to make double x = 3 / 2; return 1.5 by something external to the class so it's invisible to the users?
Thanks!
Wayne
No, there's no solution that can make 3 / 2 return 1.5.
The only workaround taking into consideration your constraints is to discourage the users to use literals in the formula. Encourage them to use constants. Or, if they really need to use literals, Encourage them to use literals with a decimal point.
never say never...
The (double)3/2 solution looks nice...
but it failed for 4+5/6
try this:
donated to the public domain to be used freely by SymbolicComputation.com.
It's alpha but you can try it out, I've only run it on a few tests, my site and software should be up soon.
It uses Microsoft's Roslyn, it'll put a 'd' after every number if all goes well. Roslyn is alpha too, but it will parse a fair bit of C#.
public static String AddDSuffixesToEquation(String inEquation)
{
SyntaxNode syntaxNode = EquationToSyntaxNode(inEquation);
List<SyntaxNode> branches = syntaxNode.DescendentNodesAndSelf().ToList();
List<Int32> numericBranchIndexes = new List<int>();
List<SyntaxNode> replacements = new List<SyntaxNode>();
SyntaxNode replacement;
String lStr;
Int32 L;
for (L = 0; L < branches.Count; L++)
{
if (branches[L].Kind == SyntaxKind.NumericLiteralExpression)
{
numericBranchIndexes.Add(L);
lStr = branches[L].ToString() + "d";
replacement = EquationToSyntaxNode(lStr);
replacements.Add(replacement);
}
}
replacement = EquationToSyntaxNode(inEquation);
List<SyntaxNode> replaceMeBranches;
for (L = numericBranchIndexes.Count - 1; L >= 0; L--)
{
replaceMeBranches = replacement.DescendentNodesAndSelf().ToList();
replacement = replacement.ReplaceNode(replaceMeBranches[numericBranchIndexes[L]],replacements[L]);
}
return replacement.ToString();
}
public static SyntaxNode EquationToSyntaxNode(String inEquation)
{
SyntaxTree tree = EquationToSyntaxTree(inEquation);
return EquationSyntaxTreeToEquationSyntaxNode(tree);
}
public static SyntaxTree EquationToSyntaxTree(String inEquation)
{
return SyntaxTree.ParseCompilationUnit("using System; class Calc { public static object Eval() { return " + inEquation + "; } }");
}
public static SyntaxNode EquationSyntaxTreeToEquationSyntaxNode(SyntaxTree syntaxTree)
{
SyntaxNode syntaxNode = syntaxTree.Root.DescendentNodes().First(x => x.Kind == SyntaxKind.ReturnStatement);
return syntaxNode.ChildNodes().First();
}
simple, if I'm not mistaken:
double x = 3D / 2D;
One solution would be writing a method that does this for them and teach them to use it. Your method would always take in doubles and the answer will always have the correct number of decimals.
I'm not pretty sure, but I believe you can get a double using 3.0/2.0
But if you think .0 just as another way of suffixing then it's not the answer too :-)
Maybe you can try RPN Expression Parser Class for now or bcParser? These are very small expression parsing libraries.
I like strong, statically typed languages for my own work, but I don't think they're suited for beginners who have no interest in becoming professionals.
So I'd have to say unfortunately your choice of C# might not of been the best for that audience.
Boo seems to be statically typed to. Have you thought about embedding a Javascript engine, Python, or some other dynamically typed engine? These usually are not that hard to plug into an existing application and you have the benefit of lots of existing documentation.
Perhaps an extenstion method on int32?
Preprocess formulas before passing them to the c# compiler. Do something like:
formula = Regex.Replace(formula, #"(^|[\^\s\+\*\/-])(\d+)(?![DF\.])", "$1$2D")
To convert integer literals to double literals.
Alternately, you could use a simple state machine to track whether or not you're in a string literal or comment rather than blindly replacing, but for simple formulas I think a regex will suffice.
Try doing it like this:
double result = (double) 3 / 2;
result = 1.5

Using C# and gppg, how would I construct an abstract syntax tree?

Is there a way to do this almost out-of-the-box?
I could go and write a big method that would use the collected tokens to figure out which leaves should be put in which branches and in the end populate a TreeNode object, but since gppg already handled everything by using supplied regular expressions, I was wondering if there's an easier way? Even if not, any pointers as to how best to approach the problem of creating an AST would be appreciated.
Apologies if I said anything silly, I'm only just beginning to play the compiler game. :)
See MGrammar and Oslo...
http://msdn.microsoft.com/oslo
http://channel9.msdn.com/pdc2008/TL31/
In your syntax file declare a property which will keep the root of your AST:
{%
public BatchNode Batch;
public ErrorHandler yyhldr;
private TransformationContext _txContext = TransformationContext.Instance;
%}
Start writing your grammar with actions which build nodes of your AST:
Batch
: StatementList {Batch = new BatchNode($1.Statements);}
;
StatementList
: Statement {$$.Statements = new List<StatementNode>(); $$.Statements.Add($1.Statement); }
| StatementList Statement {$$.Statements = $1.Statements; $$.Statements.Add($2.Statement);}
;
Call parser:
var parser = new Parser.Parser();
var scanner = new Scanner();
parser.scanner = scanner;
scanner.SetSource(sourceString, 0);
bool result = parser.Parse();
if (result)
HandleMyAst(parser.Batch)
Take a look at ANTLR, I did a simple .NET compiler written in C# with it few years back.

Categories