Search code examples
c#solid-principles

Clean Code - Are output parameters bad?


I was looking at a former colleagues post. He quoted something from an article

"In Clean Code Bob Martin disparages output arguments, saying “In general output arguments should be avoided.”

My current code base is C#. I am working in a rather large application. It was written primarily in procedural style often breaking SOLID principles. When I have the opportunity I often will break some of the methods that violate single responsibility principle into separate methods. At times I'll create methods with a couple of output parameters as in the following.

var value1 int;
var value2 int;

DoSomeWork(out value1, out value2);

I prefer this over creating a special types which would never be reused anyways if a type were created. Is this acceptable or is there a better approach?


Solution

  • It's correct that output parameters should generally be avoided. When possible (and reasonable) it's better to just return the result. Using output variables gives you a process of Prepare - Call - Handle that is more complex than it has to be.

    You don't always have to create a new type to use for return value. There are types in the framework that you can use as long as you don't need a specific name for the components in the return value:

    public Tuple<int, int> CalculateMinMax()
    

    This is of couse only good if the meaning of the return value is obvious. In the example above the two values would be expected to be the minimum and maximum that was calculated, in that order.

    If the return value is more complex, you are better off creating a type for it. If it's that complex, then using output variables for it will not make for simple code either.

    Update

    In more recent versions of C#, you can use tuple types to return a tuple with named properties. For example:

    public (int Min, int Max) CalculateMinMax()
    

    There are several ways to handle the result. You can get the result as a tuple:

    (int Min, int Max) limits = CalculateMinMax();
    

    You can populate existing variables:

    (min, max) = CalculateMinMax();
    

    You can declare new variables:

    (int min, int max) = CalculateMinMax();