1

I have a number of operations that need to be performed, in series, on the same set of data. As the operations progress, later operations require information from the prior operations. So the initial object passed in to the first method snowballs as it collects results and metadata.

At first I was passing around both a request and a response, but that painted me into a corner a couple times. So now what I intend to do is just have one parameter object that contains all the initial data, it remembers interim values, and delivers the final results, all within a single object that is passed around to many void methods.

My questions: Is this a pattern? Or is this bad form?

My contrived example is below.

    class Program
    {
        static void Main()
        {
            var MyObj = new RequestResponseInfo();
            MyObj.InitalValue = "fo";
            foobar.DoStuff(MyObj);
            Console.WriteLine(MyObj.FinalAnswer);
            Console.ReadKey();
        }
    }

    public static class foobar
    {
        public static void DoStuff(RequestResponseInfo myObj)
        {
            DoSomething_A(myObj);
            DoSomething_B(myObj);
            myObj.FinalAnswer = myObj.A + myObj.B;
        }

        private static void DoSomething_A(RequestResponseInfo myObj)
        {
            myObj.A =  myObj.InitalValue + "ob";
        }

        private static void DoSomething_B(RequestResponseInfo myObj)
        {
            myObj.B = "ar";
        }
    }

    public class RequestResponseInfo
    {
        public string InitalValue { get; set; }
        public string A { get; set; }
        public string B { get; set; }
        public string FinalAnswer { get; set; }
    }
  • Have a look at the patterns Strategy, State, Method-Object and report back, please. – User May 14 '14 at 14:45
2

What you are showing is programming with heavy side effects, which has the risk to lead to unmaintainable code, because it depends heavily on the correct order of execution, and the signatures of the Do... methods don't provide any information about their input and output. Here is an alternative design:

public class MyFooBarClass  
{
    public MyFooBarClass(string initialVal)
    {
          InitalValue=initialVal;
    }
    public readonly string InitalValue;

    public string A { get { return InitalValue + "ob";}}
    public string B { get {return "ar"; }}
    public string FinalAnswer { get{return A+B;} }
}

Now, the order of execution is always correct, you can access the properties A ,B or FinalAnswer in any order you like, the object has become immutable, which makes it more robust against changes or multithreading. Of course, when you call FinalAnswer multiple times, the same calculation will be repeated again, so if your notice a (measurable!) loss of performance, you may have to introduce memoizing techniques (but I would avoid any premature optimization if there is no real reason for this).

Another design alternative, if you really need to separate the result object from the calculation class:

 public static class foobar
 {
    public static Result DoStuff(string initialVal)
    {
        string a = DoSomething_A(initialVal);
        string b = DoSomething_B();
        string finalAnswer = A + B;
        return new Result(initialVal,a,b,finalAnswer);
    }

    private static string DoSomething_A(string initialVal)
    {
        return initialVal + "ob";
    }

    private static string DoSomething_B()
    {
        return "ar";
    }
 }

   public class Result
   {
       public Result(string initalValue, string a, string b, string finalAnswer)
       {
           InitalValue=initalValue;
           A=a;
           B=b;
           FinalAnswer=finalAnswer;
       }
       public readonly string InitalValue;
       public readonly string A;
       public readonly string B;
       public readonly string FinalAnswer;
   }

This makes the data flow much more expressive, you now see immediately what each of the Do methods uses as input, what it returns as output, and the result object is still immutable.

  • Thank you. I think I need to clarify my question. When I said I need to perform a number of operations, I'm talking about 20 to 50 function calls. Each of those takes the MyObj object as a parameter, and modifies the MyObj object by filling in empty references within the MyObj class. I appreciate your advice. Thank you. – user3384842 Jun 13 '14 at 21:31
  • @user3384842: the more operations you have, the more it will be important to make your program clean and expressive. Having 50 operations working with intransparent side effects on some data will easily become a mess (at least, for the next guy who comes after you and will have to maintain that; and if you look at that code six month's later, it is totally possible that you are that guy). – Doc Brown Jun 14 '14 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.