извлекать логические проверки для локальных переменных - PullRequest
1 голос
/ 10 августа 2009

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

Что ты думаешь?

Есть ли недостатки?

Является ли компилятор строкой или чем-то еще, если переменная больше нигде не используется? Я также подумал об уменьшении области видимости с помощью дополнительного блока "{}".

if (person.getAge() > MINIMUM_AGE && person.getTall() > MAXIMUM_SIZE && person.getWeight < MAXIMUM_WEIGHT) {
    // do something
}

final boolean isOldEnough = person.getAge() > MINIMUM_AGE;
final boolean isTallEnough = person.getTall() > MAXIMUM_SIZE;
final boolean isNotToHeavy = person.getWeight < MAXIMUM_WEIGHT;

if (isOldEnough && isTallEnough && isNotToHeavy) {
    // do something
}

Ответы [ 9 ]

11 голосов
/ 10 августа 2009

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

3 голосов
/ 10 августа 2009

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

Да, возраст, вес и рост людей меняются не очень часто по сравнению со временем выполнения большинства программ, но они меняются, и если, например, возраст изменяется, когда объект, из которого ваш фрагмент еще жив ваш окончательный isOldEnough теперь может дать неправильный ответ.

И, тем не менее, я не считаю целесообразным вводить isEligible в Личность, поскольку знание о том, что является правомочным, кажется более широким. Надо спросить: право на что?

В целом, в обзоре кода, я бы, вероятно, рекомендовал вам вместо этого добавлять методы в Person.

boolean isOldEnough (int minimumAge)  { return (this.getAge() > minimumAge); }

и т. Д.

1 голос
/ 11 августа 2009

Ваши два блока кода неэквивалентны.

Есть много случаев, которые могут быть использованы, чтобы показать это, но я буду использовать один. Предположим, что person.getAge ()> MINIMUM_AGE были истинными, а person.getTall () выдал исключение.

В первом случае выражение выполнит блок кода if, а во втором - исключение. В теории вычислимости, когда выдается исключение, это называется «нижним элементом». Было показано, что программа при оценке с использованием энергичной семантики оценки (как в вашем втором примере), что, если она заканчивается (не разрешается до конца), то гарантируется, что стратегия оценки лени (ваш первый пример) гарантирована прекратить. Это важный принцип программирования. Обратите внимание, что вы не можете самостоятельно писать функцию && в Java.

Хотя маловероятно, что ваш метод getTall () вызовет исключение, вы не можете применить свои рассуждения к общему случаю.

0 голосов
/ 10 августа 2009

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

if (person.getAge() > MINIMUM_AGE
  && person.getTall() > MAXIMUM_SIZE
  && person.getWeight < MAXIMUM_WEIGHT)
{
  // do something
}

Большая проблема, которую поднимают другие ответы, заключается в том, относится ли это к объекту Person. Я думаю, что простой ответ на этот вопрос таков: если есть несколько мест, где вы проводите один и тот же тест, это относится к человеку. Если есть места, где вы проводите похожие, но разные тесты, они принадлежат к вызывающему классу.

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

С другой стороны, если у вас есть одно место, где вы проверяете, кто старше 18 лет, и где-то еще, где вы проверяете, не старше ли он 12 лет, и где-то еще, где вы проверяете, старше 65 лет и т. Д., То мало что можно получить. нажав эту функцию в Person.

0 голосов
/ 10 августа 2009

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

0 голосов
/ 10 августа 2009

Я думаю, что это вопрос личного вкуса. Я считаю ваш рефакторинг вполне читабельным.

В этом конкретном случае я мог бы преобразовать весь тест в

isThisPersonSuitable()

способ.

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

Как правило, я бы предпочел удобство чтения по сравнению с любыми незначительными соображениями производительности.

0 голосов
/ 10 августа 2009

Одним из преимуществ последнего случая является то, что у вас будут переменные isOldEnough, isTallEnough и isNotToHeavy (sic), которые можно будет использовать позже в коде. Это также более легко читается.

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

0 голосов
/ 10 августа 2009

Вы можете пойти еще дальше и создать подтипы человека:

Teenager extends Person
ThirdAgePerson extends Person
Kid extends Person

Подклассы будут переопределять методы Person по-своему.

0 голосов
/ 10 августа 2009

Я думаю, что чеки, вероятно, принадлежат к классу человека. Вы можете передать значения Min / Max, но, на мой взгляд, лучшим решением будет вызов person.IsEligable ().

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