Information hiding and functional programming style

I was developing a simple class called Simulator

that applies a list Simulation

to a specific input. For each input, the simulation may or may not provide an output based on some conditions that the input must fulfill for each simulation. The result generated Simulator

is a list of outputs.

Here is the code.

class Simulator {
    final List<Simulation> simulations;

    // Some initialization code...

    List<Ouput> execute(Input input) {
        return simulations
            .stream()
            .filter(s -> s.processable(input))
            .map(s -> s.prepareOutput(input))
            .collect(Collectors.toList());
    }
}

      

As you can see, I first check to see if the input is processed with by Simulation

filtering the simulations for which it isn't, and then applying those simulations to the input.

From an object oriented point of view, I expose the internals of the class Simulation

. The validation operation performed by the method processable

must be hidden inside the method prepareOutput

.

However, if processable

seen on Simulator

, I can take a more functional approach, which is very convenient.

Which approach is better? Are there any other solutions I am missing?

+3


source to share


2 answers


Since your class is Simulation

already showing an operation prepareOutput

that might fail, there is no additional exposure if you provide a method processable

for detecting in advance if an operation will be performed prepareOutput

. In fact, this is a good API design, offering this kind of validation as long as it is not too expensive to calculate in advance.

You may still want to consider doing a bulk processing operation in the class Simulation

.

public class Simulation {
    public Output prepareOutput(Input input) {
    }
    public static List<Output> prepareWhenPossible(List<Simulation> list, Input input) {
        return simulations.stream()
            .filter(s -> s.processable(input))
            .map(s -> s.prepareOutput(input))
            .collect(Collectors.toList());
    }
}

      



It is important to instruct the caller to skip items that cannot be operated on instead of performing an all-or-nothing behavior.

This still does not preclude exposure processable

if it is cheap to implement. It is not as if it were an impossible operation, as you can always simply call prepareOutput

and discard the result to see if the operation is possible. Having a method processable

for this purpose is much cleaner.

+4


source


If you need to hide processable

, why not do it a little differently:

 Optional<Output> prepareOutput(Input input) {

      boolean isProcessable = processable(input); // processable is private

      if(isProcessable){
            // prepare Output
            return Optional.of(Output);   
      }
      return Optional.empty();

 }

      



And here's something like this:

  List<Ouput> execute(Input input) {
    return simulations
        .stream()
        .map(s -> s.prepareOutput(input))
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());
 }

      

+1


source







All Articles