Как рекомендации по функциональному программированию для статических методов влияют на возможность тестирования?

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

http://www.amazon.de/Functional-Programming-Techniques-Projects-Programmer/dp/0470744588

Конечно, это имеет смысл, если вы думаете о функциональной чистоте. Статическая функция стоит там и говорит: "Мне не нужно какое-либо состояние!"

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

ИЗМЕНИТЬ

Так как есть сомнения, действительно ли книга делает эту рекомендацию. Я приведу немного больше. Надеюсь, это хорошо для Оливера Штурма.

Использовать статические методы

Статические методы - одна из основных идей, которые следует рассматривать в качестве общего руководства. Он поддерживается многими объектно-ориентированными программистами, и с функциональной точки зрения функции могут выполняться чаще всего в большинстве случаев. Любая чистая функция может быть сделана статической. (...)

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

Наконец, рекомендуется рекомендовать: когда вы написали метод, который не требует доступа к любому полю в классе, в котором он живет, сделайте его статическим!

Кстати, до сих пор были хорошие ответы. Спасибо за это!

Ответ 1

Один из способов взглянуть на это - это то, что для функционального программирования вам нужно только высмеять состояние (путем предоставления подходящих входов), которое требуется конкретной функции. Для программирования OO вам нужно высмеять все состояние, необходимое для внутренней работы класса.

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

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

(Я понимаю, что стили функционального программирования могут использовать OO через неизменяемые объекты - пожалуйста, прочитайте упоминания OO выше как "объектно-ориентированное программирование с изменчивым состоянием" )

Edit:

Как указано Fredrik, важная часть функциональных методов заключается не в том, что они являются статическими, а в том, что они не изменяют состояние программы. "Чистая" функция - это отображение из набора входов в набор выходов (тот же ввод всегда дает тот же результат) и не имеет другого эффекта.

Ответ 2

Все "состояние" в чисто функциональном программировании происходит от входов. Для unit test функциональных программ вы создаете тестовые входы и наблюдаете за выходами. Если ваши методы не могут быть протестированы, предоставив им тестовые входы и наблюдая за выходом, они недостаточно функциональны.

Ответ 3

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

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

Ответ 4

В функциональном программировании вы хотели бы высмеять функции вместо объектов. Поэтому, если вы хотите проверить функцию f, не зависимо от некоторого ComplicatedAndLongFunction в

f(x)
{
    myx = g(x);
    y = ComplicatedAndLongFunction(myx);
    myy = h(y)
    return myy;
}

вы можете отделить f от ComplicatedAndLongFunction, введя последнее в f:

f(x, calc)
{
    myx = g(x);
    y = calc(myx);
    myy = h(y)
    return myy;
}

чтобы вы могли указать поведение calc в своем тесте.

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