2016-04-05 3 views
0

Я столкнулся с этой сложной дилеммой достаточно времени, чтобы почувствовать себя вынужденным получить мнение об этом. Итак, вот он идет:Является ли хорошей практикой кодирования для заполнения входных параметров?

private void populateResults (final ImmutableSet<String> inputSet, final Map<String, Integer> successResult, final Set<String> errored){ 
    final BatchResult<String> result = this.serviceClient.call(inputSet); 
    for (final String input : inputSet) { 
     try { 
      Integer output = result.getOutput(input); 
      successResult.put(input, output); 
     } catch (Exception e) { 
      errored.put(input); 
     } 
    } 
} 

Учитывая фрагмент выше, что это лучший способ, чтобы закодировать это:

  • Отправить в 2 пустых коллекциях & пусть метод заполнение тех
  • занесения успеха & возвращения не удалось
  • Какой-нибудь другой вариант?

Поблагодарите ваши комментарии по этому вопросу.

ответ

2

Идеально для минимизации или локализации побочных эффектов максимально; чистые функции обычно предпочтительнее.

This question on P.SE спрашивает конкретно о функциональном программировании, но многие принципы FP обычно считаются хорошей практикой для дизайна OO.

Неизменимость обычно считается хорошей вещью в любой парадигме программирования; не только потому, что он помогает с безопасностью потоков, а потому, что побочные эффекты могут быть довольно непрозрачными при отладке.

Методы, которые изменяют свои аргументы, существенно изменяют «общее состояние». Хотя глобальная переменная не так сильна, как глобальная переменная, неодобрение заключается в том, что их состояние сложнее прогнозировать при прохождении через программу.

Неизменяемые функции поддерживаются . (Что относится к дизайну OO/интерфейса, а также к дизайну пользовательского интерфейса).

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

Чтобы переписать эту функцию без побочных эффектов, рассмотреть вопрос структурирования результатов в качестве возвращаемого значения, которые указывают на успех/провал, а также содержащий данные результата:

private Map<String, Integer> populateResults (final ImmutableSet<String> inputSet) { 
    Map<String, Integer> resultMap = new Map<String, Integer>(); 
    final BatchResult<String> result = this.serviceClient.call(inputSet); 
    Integer output; 

    for (final String input : inputSet) { 
     try { 
      output = result.getOutput(input); 
     } catch (Exception e) { 
      output = null; 
     } 

     resultMap.put(input, output); 
    } 
} 

В качестве альтернативы, вы можете создать отдельный класс для сохраните свой результат вместо Map<String, Integer>; в любом случае, цель состоит в том, чтобы избежать совместного состояния, написав «чистый» метод, который не модифицирует какое-либо государство, принадлежащее чему-либо более широкому, чем его собственная локальная область.

+0

Спасибо за ваш ответ Бен. Помещение нулевого значения в карту кажется отсрочкой проблемы. Цель метода заключалась в том, чтобы добиться успеха, а результаты отказа были разделены и готовы к следующему шагу. Но да, я вижу ценность в рефакторинге в новый класс. – mindreader

0

В дополнение к Ben's very good answer Я бы сказал, что метод (или класс) должен нести отдельную ответственность. Он должен сделать одно. Он должен иметь только одну ось изменения. Обновление двух коллекций - это случай побочного эффекта (обескураженный повсюду, но особенно в функциональном программировании). Это случай побочного эффекта, потому что помимо выполнения собственной работы (получение результатов), метод также, похоже, заполняет два разных типа коллекций. Подобно тому, как ссылки параметров, которые вы отметили как окончательные, коллекции, которые вы проходите (если вы делаете), должны быть немодифицируемыми. Но тогда вы не можете их изменить. Также одним из индикаторов ООП побочных эффектов является метод с возвратом void.

Если вы думаете об этом, решение заполнить коллекцию основано на результатах, и это ответственность другого метода. Путаница, ИМО, существует, потому что мы не знаем, что является основной ответственностью метода.Какую операцию необходимо выполнить. Когда у вас будет несколько небольших методов, выполняющих единую ответственность, вы можете посмотреть composed method pattern и the levels of abstraction и реорганизовать код примерно this.

Дайте мне знать, если это поможет.

+0

Спасибо за ваш ответ. Я не уверен, понимаю ли я, как уровни абстракции вписываются в это. Даже если я сломаю это дальше, в конце концов, я все равно столкнусь с той же проблемой - отправлю назад успех и сбор сбоя. – mindreader

+0

@mindreader действительно пытаются отделить два. Тогда вам не нужно передавать коллекцию в качестве входных данных. Таким образом, методы не будут иметь побочных эффектов. Таким образом, будут два пути - один для успеха, а другой для исключения. В этот момент не будем беспокоиться об уровнях абстракции, которые, вероятно, появятся и будут видны в конце. – Atul

Смежные вопросы