Хранение функций в переменных экземпляра (Java) - PullRequest
1 голос
/ 20 июня 2019

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

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

    public class SomeClass {
    private final UnaryOperator<Something> someMethod = s -> doSomething;

    public void someMethod2(Something s) {
        //some code which goes over several lines and uses someMethod variable
    }

    public void someMethod3(Something s) {
        //some code which goes over several lines and uses someMethod variable
    }
}

Другой пример, в котором ввод предварительно подготовлен для различных служб в классе помощника. Два одинаковых символа должны быть заменены в строке для обоих сервисов. Функция для этого не хранится обычным статическим методом, она хранится в статическом поле, которое реализует UnaryOperator.

public class PrepareServicesInputHelper {
    private static final UnaryOperator<String> replaceSignsForAllServices = s -> s.replace('+', '-')
            .replace('/', '*');

    public static String transformStringForServiceOne(String s) {
        return "Additional transformation information for service one" + removeUnwantedSigns.apply(s);
    }

    public static String transformStringForServiceTwo(String s) {
        return "Additional transformation information for service two:" + removeUnwantedSigns.apply(s);
    }
}

Это выглядит лучше и понятнее для меня.

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

1 Ответ

1 голос
/ 21 июня 2019

В вашем примере я не вижу никакой дополнительной ценности вашего решения по сравнению с простым вызовом метода.Ваше решение является излишним.

Авраам Маслоу (https://en.wikipedia.org/wiki/Law_of_the_instrument):

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

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

Изучите шаблоны проектирования поведения здесь или здесь , такие как Command, Observer / Listener, Strategy, Visitor. Здесь вам нужно передать поведение, и именно для этого в Java созданы лямбды.

Еще одно быстрое «практическое правило» может быть таким:

  1. Вам нужно вызватьметод прямо сейчас ? Итак, вызовите метод.
  2. Вам нужно передать метод для вызова изнутри другого метода, позже, возможно, вызватьне один раз, а несколько раз, может быть, даже не совсем (если решает метод управления)?лямбда.

Для вашего случая использования наиболее распространенным является следующий способ.Он выглядит даже лучше и даже понятнее:)

public class PrepareServicesInputHelper {
    private static String replaceSignsForAllServices(final String s) {
        return s.replace('+', '-').replace('/', '*');
    }

    public static String transformStringForServiceOne(final String s) {
        return "Additional transformation information for service one" + removeUnwantedSigns(s);
    }

    public static String transformStringForServiceTwo(final String s) {
        return "Additional transformation information for service two:" + removeUnwantedSigns(s);
    }
}

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

public class Logger {
    private boolean logIsOn;
    // constructor, setters, getters etc.

    public log(final String message) {
        if (logIsOn) {
            printToFile(message);
        }
    }

    public lazyLog(final Supplier<String> message) {
        if (logIsOn) {
            printToFile(message.get());
        }
    }
}

// Here the expensive calculation occurs always, even if the logging is off
logger.log("Operation x performed on " + 
    person.getFirstName() + " " +
    person.getLastName() + 
    " with the result " + result.calculate()); 

// Here the expensive calculation occurs only when the logging is on
logger.lazyLog(() -> "Operation x performed on " + 
    person.getFirstName() + " " +
    person.getLastName() + 
    " with the result " + result.calculate()); 
...