0

I have class that has several fields.

public class Foo {
 int firstCoef;
 int secondCoef;

 public Foo(String args){
  this.firstCoef=Integer.parseInt(args[0]);
  this.secondCoef=Integer.parseInt(args[1]);
 }
}

The arguments are assigned this way because I create several members of this class by reading data from .csv. I have another class that manages a list of Foo instances. It creates the whole list at once by reading it from file and uses the list for calculation. When creating a list in class constructor, it uses new Foo(string).

public class FooManager {
    protected List<Foo> allFoos = new ArrayList<Foo>();

    public FooManager(List<String[]> input) {
        String[] line;
        for (int lineNumber = 0; lineNumber < input.size(); lineNumber++) {
            line = input.get(lineNumber);
            allFoos.add(new Foo(line));
        }
    }

    public int calculate(int number) {
        int result = 0;
        for (Foo foo : allFoos) {
            result += Math.pow(number + foo.getFirstCoef(), foo.getSecondCoef());
        }
        return result;
    }
}

From what I understand, this is considered bad design because the dependencies can't be injected. Also, it is hard to test. How could I change the design without complicating the input? The only goal of both classes is to be able to perform the calculation in the end.

Krzysztof Krasoń
  • 26,515
  • 16
  • 89
  • 115
  • Which dependencies? I cannot see any. `Foo` is a simple data object. You can create it with 'new' with no issue. It is "objects" with behavior that you need to "inject". You can simply test `FooManager` by constructing it with some input and then invoking the `calculate` method and assert on the return value. – Yacoub Massad Mar 26 '18 at 11:11

1 Answers1

0

You could add another layer, by adding a class that does the translation from the List to List:

public class FooParser implements Function<String[], Foo> {

    public Foo apply(String[] input) 
        for (int lineNumber = 0; lineNumber < input.size(); lineNumber++) {
            String[] line = input.get(lineNumber);
            allFoos.add(new Foo(line));
        }
    }
}

And then use it in the constructor of FooManger:

public FooManager(FooParser parser, List<String[]> input) {
    allFoos = parser.apply(input);
}

This way you have another part of logic in separate class - and it is easier to test in isolation.

Krzysztof Krasoń
  • 26,515
  • 16
  • 89
  • 115