Business rules continued

How to create a Rule based system in c sharp? Below is an image that descibes the rules we want to apply. If a rule has a match, continue to next rule until we meet the expected result. If you haven't read the first part, read it here

Simplicity!

How do we make our Business Rules understandable for non developers? Can they also be a part of the discussion, and also be able to explain for the client what's going on. -I sure think so. Let me explain how in the next section.

What is a Business Rule?

When I started this project I searched the Internet for what types of Business rules there is. There's XML based, programatical etc. A lot of different techniques to achieve the same result. I desided to go for programatical, since I already have functions for it. A businessrule should describe what to reach and todo with the result. If you see the image, which we developers offens get sent to us. It describes what functions needed. Also what we should do with items that reach a certain level.

If we can make all functions with the same name, it's also easy to follow. We know what we need to return.

Basically a Rule is just a function. By adding the Composite Rule, we can now combine these functions in a Fluent way!! I like that, because it is so easy to read and understand. For eg.

var AllowEditContent = IsEditor.And(IsPartOfGroupAdmin).Or(IsPartOfGroupPowerUsers);

It's understandable for anyone, isn't it?

I dont know if this is the best solution, it's just my way of solve a problem and make it easier to read and follow all business rules. Because when a system get's bigger and more complicated, we need to have an easy way to implement new functions, and be understandable for anyone. In this way we can test any single rule before we proceed that will guarantee the result.

If you prepare all rules, you can actually pre-make all Rules, to match all rules required for you solution.

As a result I created a small console app, for you to study.
See the code below, or checkout the code on Bitbucket

public static partial class RuleProcessor
    {
        //Print status colored
        static Action<string> P = (s) => { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(s); };
        static Action<string> F = (s) => { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(s); };
        static Dictionary<RequestType, List<RegisterEvent>> Events = new Dictionary<RequestType, List<RegisterEvent>>();

        public static void Process(List<RegisterEvent> items)
        {
            items.ForEach(c=> ProcessItem(c));
            PrintDict();
        }


        private static void ProcessItem(RegisterEvent item)
        {
            // PreRun all Rules for the Event
            var validateIsBank = ValidateSource(item);
            var validateIsActive = ValidateStatus(item);
            var validateInsuranceType = IsInsuranceType(item);


            /* 
             * Now we can group these rules to meet a specific requirement.
             * Group several rules to match a specific item.
             * What we want to achieve, get's more clear now.
             */
             var ShouldPassActiveAndIsBank =
                validateIsBank
                .And(validateIsActive);

             /*
             * The name "ShouldPassActiveAndIsBank" can later on, 
             * be used to run the event in a specific function 
             * or store the event in a table in a database. 
             * We now know what todo with this item.
             * 
             * The image(schema) describes what todo with an item that reaches this level.  
             */

            if (ShouldPassActiveAndIsBank.PassedItem){
                AddToDict(RequestType.IsActiveAndIsBank, item);
            }
            else {
                var ShouldBeInsuranceType = validateInsuranceType;

                if (ShouldBeInsuranceType.PassedItem)
                    AddToDict(RequestType.IsInsurance, item);
                else
                    AddToDict(RequestType.UnKnownType, item);
            }
        }

        #region Helpers

        private static void PrintDict()
        {
            foreach(var key in Events.Keys)
            {
                var list = Events[key];
                foreach (var evt in list)
                    if(key==RequestType.UnKnownType)
                        F($"Unknown type: {evt.Name}");
                    else
                        P($"Item found: {key} : {evt.Name}");
            }
        }

        private static void AddToDict(RequestType key, RegisterEvent item)
        {
            var items = new List<RegisterEvent>();

            if (!Events.ContainsKey(key)) {
                items.Add(item);
                Events.Add(key, items);
            }
            else
            {
                Events.TryGetValue(key, out items);
                items.Add(item);
            }
        }

        #endregion
    }

Summary

It sounds complicated for some people when I mention Business Rules. But, if we can explain it by show a Rule on a picture or scheme, and then review the code, it will all be much clearer. I hope you enjoyed my writing. Cheers!


Created by Bootproject editor on 2019-10-28


  • multi

    About

    The Swede(me), Rickard Magnusson a Senior Software Engineer, currently employeed as a freelance consultant in Norway.

  • Legal

    Bootproject.se and Footer.se is property of Bootproject and may be used under (MIT)licence . See project on Bitbucket

  • Logo Contact

    Email: bootproject@icloud.com

(©) Copyright www.bootproject.no 2020