Stefan Lindner
Stefan Lindner

Reputation: 329

Refactoring pattern for one method with different return values

I have to do a refactoring of a method and run into a problem where this method gets called with different expectation for return values. This is basically what i have at this point (abstracted from real method and classnames).

public static List<TypeA> calculationMethod(...)
{
    List<TypeA> aTypes = new ArrayList<TypeA>;

    //this one is used to calculate some stuff inside this method
    List<TypeB> bTypes = new ArrayList<TypeB>;


    // generation of objects of TypeA and TypeB and more

    // use bTypes to check if aTypes is fine

    return aTypes;
}


public void method1()
{
    List<TypeA> aTypes = calculationMethod(...)
    //do other stuff with aTypes
}

public void method2()
{
    List<TypeA> aTypes;
    List<TypeB> bTypes;

    // here is the problem, i need to get both lists from calculationMethod
    aTypes = calculationMethod(...);
}

The calculationMethod returns a list with TypeA objects which is fine for method1 (90% of my calls) but not for method2, because there i need the second list with objects of TypeB to do further verification.

I came up with the following solutions with which i have some problems.

Call by reference Instead of returning a value i could just put the list in the method parameters and expect it to be filled after calculationMethod is done. This is actually where i came from and where i don't want to go again. Something like:

public static void calculationMethod(List<TypeA> aTypes, List<TypeB> bTypes, ...)
{
    aTypes.add(...);
    bTypes.add(...);
}

Switch return type of calculationMethod Instead of returning a list, i could return a tuple with both lists in it. But since i only need one of the lists in most cases this seems like i weaken my method contract and readability of my code.

public static Tuple<List<TypeA>, List<TypeB>> calculationMethod(...)
{
    // do stuff

    return new Tuple<>(aTypes,bTypes);
}

Split method I could also split the method (and rename them) so i have two methods and i can call the one i need at the moment. But this would create duplicate code, at least to some extend, because the code used in calculationMethod can not be put into another method so easily.

public static List<TypeA> calculationMethod1(...)
{
    //code
    return aTypes;
}

public static Tuple<List<TypeA>, List<TypeB>> calculationMethod2(...)
{
    // same code
    return new Tuple<>(aTypes,bTypes);
}

TL;DR Is there a refactoring pattern so i can refactor a method that uses call by reference for its parameters to handle multiple return types?

edit The second list contains Boolean and is used to verify the initialization of the objects of list one (TypeA). Usually it is enough if i know that bTypes only contains true. But there is one case where i want that bTypes contains false. And this is the case for method2 where i want bTypes to do further checks outside of calculationMethod.

public static List<TypeA> calculationMethod(...)
{
    List<TypeA> aTypes = new ArrayList<TypeA>;
    List<Boolean> bTypes = new ArrayList<TypeB>;

    TypeA typeA = new TypeA(...);
    bTypes.add(validateInit(typeA));

    Boolean initOK = true;
    for(Boolean b: bTypes)
    {
        if(!b)
            initOK = false;
    }
    if(initOK)
    {
        return aTypes;
    }else 
        return null;
} 

Upvotes: 1

Views: 2086

Answers (1)

Y.E.
Y.E.

Reputation: 922

This is a design issue, when you have to return 2 objects from a method, that means the method does more than it should do. You may have 2 options depending on the implementation you already have in your hands;

Split the method to do one meaningful thing only OR encapsulate the Lists in an object, populate it in the method and return that.

public class Types {
    List<TypeA> typeAs;
    List<TypeB> typeBs;
}

Upvotes: 4

Related Questions