Java: когда использовать поля в сравнении с аргументами?

#java #coding-style #methods

#java #стиль кодирования #методы

Вопрос:

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

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

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

Вместо:

  invoke (oldField1, oldField2, newField1)  
 submethod1 (results, oldField1, oldField2, newField1)  
 submethod2 (results, oldField1, oldField2, newField1)  
  

Должно ли это быть:

  invoke(oldField1, oldField2, newField1){
   OldField1=oldField1
   OldField2=oldField2
   NewField1=newField1
 }
 submethod1(results)
 submethod2(results)
  

Или даже:

  new (oldField1, oldField2, newField1){
   OldField1=oldField1
   OldField2=oldField2
   NewField1=newField1
 }
 invoke()
 submethod1(results)
 submethod2(results)
  

Спасибо!

Ответ №1:

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

Третий вариант позволяет сделать объект с отслеживанием состояния, но неизменяемым. Его можно использовать для нескольких вызовов, использующих один и тот же набор полей, даже параллельно (если сделать неизменяемым).

Оба эти решения приемлемы. Чем меньше состояние объекта, тем проще его использовать, особенно в многопоточной среде.

Чем менее изменяемый объект, тем проще его использовать.

Второе делает его изменяемым объектом с сохранением состояния, который не может использоваться несколькими потоками (без синхронизации). На мой взгляд, он выглядит менее чистым, чем два других.

Ответ №2:

Мое общее правило — по возможности избегать изменения состояния в сервис-ориентированном классе. Хотя Java на самом деле не поддерживает функциональное программирование как таковое, самая простая и масштабируемая реализация — это ваш первый подход, который не использует переменные-члены.

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

 public class Invoker {
    public static void invoke(ResultContainer result, List<String> parameters) {
        submethod1(result, parameters);
        submethod2(result, parameters);
    }
}
  

Я бы также рекомендовал вам взглянуть на шаблон дизайна декоратора для получения дополнительных идей.

Ответ №3:

Это зависит от того, является ли ваш аргумент данными или идентифицирует режим / переключатель.

Я предлагаю один аргумент для типа структуры данных и другой аргумент, который содержит перечисляемые типы различных операций.

И затем, основываясь на вашем типе перечисления или режиме работы, вы можете выбрать стратегию, в каком классе выполнять.

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