views:

64

answers:

2

Hello!

I've got this class, let's call it Refund (because that's what it's called). I want to validate some things about this Refund and the Customer it's attached to, and I want to make these validations re-orderable, because the first one that trips will be stored as the reject reason on the Refund, and also some of them are likely to be more resource-intensive than others and more likely to be tripped, so I'd like to be able to easily reorder their execution so that I could squeeze some performance out if I need to.

All of the validation methods will take a Refund object and return a boolean denoting whether the validation has passed or failed. So, I was thinking, why not make a queue (or other data structure) to hold delegates/lambdas/anonymous functions, each representing a validation method? Then, just passing the Refund into some kind of static Validate(Refund refundToValidate) method on some Validator class. This method would walk through the array of delegates, calling each in sequence, and returning false if one of them produced false.

Is this a good idea or a stupid idea? If it's a good idea, can you point me to a resource somewhere or name a pattern that I am inadvertantly implementing, so that I know I'm doing it right? If it's a stupid idea, why and what should I be doing differently?

EDIT: here's what I've got so far-

public static class Validator
    {


        delegate REFUNDDENIALREASONS validationHandler(BatchRefund refundToValidate);

        public static List<REFUNDDENIALREASONS> ValidateRefund(BatchRefund refundToValidate)
        {
            List<Delegate> Validations = new List<Delegate>();
            List<REFUNDDENIALREASONS> DenialReasons = new List<REFUNDDENIALREASONS>();

            Validations = new List<Delegate>();

            validationHandler blockHandler = ValidateBlocks;
            Validations.Add(blockHandler);

            validationHandler accountHandler = ValidateCustomerAccountStatus;
            Validations.Add(accountHandler);

            foreach (validationHandler v in Validations)
            {
                DenialReasons.Add(v(refundToValidate));
            }

            return DenialReasons;
        }

        public static REFUNDDENIALREASONS ValidateCustomerAccountStatus(BatchRefund refundToHandle)
        {
            REFUNDDENIALREASONS denialReason;

            switch (refundToHandle.RefundCustomer.CustStatus)
            {

                case "C":
                    denialReason = REFUNDDENIALREASONS.None;
                    break;
                case "Y":
                    denialReason = REFUNDDENIALREASONS.AccounthasrecentChargebackNSF;
                    break;
                default:
                    denialReason = REFUNDDENIALREASONS.Fraud;
                    break;
            }

            return denialReason;

        }

        public static REFUNDDENIALREASONS ValidateBlocks(BatchRefund refundToHandle)
        {
            List<CustomerBlock> blocks = refundToHandle.RefundCustomer.Blocks;
            //add new codes to block here
            string[] illegalblockcodes = new string[] { "L1", "C1" };

            foreach (string code in illegalblockcodes)
                if (blocks.Exists(b => b.BkClassCode == code))
                {
                    return REFUNDDENIALREASONS.Fraud;
                }

            return REFUNDDENIALREASONS.None;

        }
    }
A: 

Not necessarily a bad idea. Do you intend to keep track of which validation failed? If you're using a static method that runs it through a queue how are you going to tell?

Spencer Ruport
Ooh, good call. Perhaps I can return something a little more interesting than a boolean...
Chris McCall
Perhaps some list of generic ValidationFailed items.
Spencer Ruport
I've decided on List<REFUNDDENIALREASONS> where REFUNDDENIALREASONS is an enum of the obvious.
Chris McCall
+1  A: 

You're basically describing a tweak on the Chain-of-responsibility design pattern. There are advantages and disadvantages to this, but it is a good option if you want the flexibility of adding other operations onto your queue at any point in time.

Reed Copsey