Слияние дубликата кода, использующего разные объекты - PullRequest
0 голосов
/ 28 февраля 2019

Я использую два вызова API для получения данных о vehicleUtils в зависимости от contentFilter.У меня очень похожий код для обоих (водителей и транспортных средств).То, что я пытался сделать, это извлечь код в один метод и применить шаблон стратегии, как они предлагают здесь Рефакторинг методов , но я не мог понять, как его реализовать.Я использую хороший подход или есть лучший способ?

if (contentFilter.equalsIgnoreCase(Contentfilters.VEHICLES.toString())) {

  VuScores vuScores = new VuScores();
  List<VehicleVuScores> vehicleVuScoresList = new ArrayList<>();
  List<VehicleUtilization> vehicleUtilizations = RestClient.getVehicles(request).join().getVehicleUtilizations();


  if (Objects.nonNull(vehicleUtilizations)) {
    vehicleUtilizations.forEach(vehicleUtilization -> {
      vuScores.getVehicleVuScores().forEach(vehicleVuScore -> {

        vehicleVuScore.getScores().setTotal(vehicleUtilization.getFuelEfficiencyIndicators().getTotal().getValue());
        vehicleVuScore.getScores().setBraking(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(0).getValue());
        vehicleVuScore.getScores().setCoasting(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(1).getValue());
        vehicleVuScore.getScores().setIdling(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getIndicators().get(0).getValue());
        vehicleVuScore.getScores().setAnticipation(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getValue());
        vehicleVuScore.getScores().setEngineAndGearUtilization(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getValue());
        vehicleVuScore.getScores().setStandstill(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getValue());
        vehicleVuScore.getScores().setWithinEconomy(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(7).getValue());
        vehicleVuScore.setAvgFuelConsumptionPer100Km(vehicleUtilization.getMeasures().getTotal().getAverageConsumption().getValue());
        vehicleVuScore.setAvgSpeedDrivingKmh(vehicleUtilization.getMeasures().getTotal().getAverageSpeed().getValue());
        vehicleVuScore.setEngineLoad(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(1).getValue());
        vehicleVuScore.setTotalDistanceInKm(vehicleUtilization.getMeasures().getDriving().getDistance().getValue());
        vehicleVuScore.setTotalTime(Math.toIntExact(vehicleUtilization.getMeasures().getTotal().getTime().getValue()));

        vehicleVuScoresList.add(vehicleVuScore);
      });
    });
    vuScores.setVehicleVuScores(vehicleVuScoresList);
  }
  return CompletableFuture.completedFuture(vuScores);

} else if (contentFilter.equalsIgnoreCase(Contentfilters.DRIVERS.toString())) {

  VuScores vuScores = new VuScores();
  List<DriverVuScores> driverVuScoresList = new ArrayList<>();
  List<VehicleUtilization> vehicleUtilizations = RestClient.getDrivers(request).join().getVehicleUtilizations();


  if (Objects.nonNull(vehicleUtilizations)) {
    vehicleUtilizations.forEach(vehicleUtilization -> {
      vuScores.getDriverVuScores().forEach(driverVuScores -> {

        driverVuScores.getScores().setTotal(vehicleUtilization.getFuelEfficiencyIndicators().getTotal().getValue());
        driverVuScores.getScores().setBraking(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(0).getValue());
        driverVuScores.getScores().setCoasting(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(1).getValue());
        driverVuScores.getScores().setIdling(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getIndicators().get(0).getValue());
        driverVuScores.getScores().setAnticipation(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getValue());
        driverVuScores.getScores().setEngineAndGearUtilization(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getValue());
        driverVuScores.getScores().setStandstill(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getValue());
        driverVuScores.getScores().setWithinEconomy(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(7).getValue());
        driverVuScores.setAvgFuelConsumptionPer100Km(vehicleUtilization.getMeasures().getTotal().getAverageConsumption().getValue());
        driverVuScores.setAvgSpeedDrivingKmh(vehicleUtilization.getMeasures().getTotal().getAverageSpeed().getValue());
        driverVuScores.setEngineLoad(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(1).getValue());
        driverVuScores.setTotalDistanceInKm(vehicleUtilization.getMeasures().getDriving().getDistance().getValue());
        driverVuScores.setTotalTime(Math.toIntExact(vehicleUtilization.getMeasures().getTotal().getTime().getValue()));

        driverVuScoresList.add(driverVuScores);
      });
    });
    vuScores.setDriverVuScores(driverVuScoresList);
  }
  return CompletableFuture.completedFuture(vuScores);
}

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

Попробуйте подумать об общем (абстрактном) базовом классе, который содержит общий код.Фактические классы содержат различный код.

Вам тогда не нужно работать с instanceof или Contentfilters или любыми используемыми вами функциями принятия решений.Вы можете просто вызывать обычные методы, поскольку ваша функция должна принимать (абстрактный) базовый класс.Это действительно удаляет дублирование кода.

0 голосов
/ 28 февраля 2019

Итак, все то же самое, за исключением

  • типов DTO, в которые вы копируете данные (VehicleVuScores vs DriverVuScores)
  • вызванный метод RestClient

Основная проблема - поделиться кодом, который вызывает сеттеры.Нам нужен способ ссылаться на целевой объект, не зная, является ли он VehicleVuScores или DriverVuScores.Мы могли бы объявить это как:

Object vuScores;

, но поскольку Object не объявляет сеттеры, мы получим ошибки компиляции при попытке вызвать сеттеры.Чтобы исправить это, мы можем переместить объявление этих методов получения и установки в общий базовый тип:

abstract class VuScoresBase {
    // fields, getters and setters
}

class DriverVuScores extends VuScoresBase {}
class VehicleVuScores extends VuScoresBase {}

, поэтому мы можем написать:

public void convert(VehicleUtilization vehicleUtilization, VuScoresBase result) {
    // invoke the setters here
}

и использовать этот метод в обоих случаях.

С помощью дженериков мы могли бы также повторно использовать код итерации:

<V extends VuScoresBase> public void convertList(List<VehicleUtilization> vehicleUtilizations, List<V> resultList, Supplier<V> constructor) {
    // iterate       
        V vuScore = constructor.apply();
        convert(vehicleUtilization, vuScore);
        resultList.add(vuScore);
}

, чтобы мы могли вызывать его с помощью

convertList(vehicleUtilizations, driverVuScores, DriverVuScore::new);

, но я бы, вероятно, воздержался от этогоПотому что из-за непатентованного кода код становится трудным для понимания.

Однако, поскольку DriverVuScores и VehicleVuScores очень похожи, я бы задал вопрос, действительно ли они должны быть отдельными типами.Если бы мы могли использовать VuScoresBase везде, это значительно упростило бы логику преобразования:

VuScoresBase convert(VehicleUtilization vehicleUtilization) {
   VuScoresBase vuScores = new VuScoreBase();
   // invoke setters
   return vuScores;
}

и

List<VuScoresBase> convertList(List<VehicleUtilization> vehicleUtilizations) {
  // iterate
     result.add(convert(vehicleUtilization));
}
0 голосов
/ 28 февраля 2019

Используйте интерфейс, реализуйте его в обоих классах и используйте этот интерфейс в обоих местах для получения или установки значений.Поскольку все имена методов одинаковы, интерфейс должен содержать все необходимые методы получения и установки.Таким образом, вам не придется использовать разные классы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...