Лучшая практика - когда оценивать условия выполнения функции - PullRequest
6 голосов
/ 03 июня 2010

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

В первом варианте сказано, что поместите его в функцию, чтобы он гарантированно был проверен. Абстрагируйтесь, если хотите.

public function Foo() {
    DoThing();
}

private function DoThing() {
    if (!condition) return;
    // do stuff
}

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

Второй вариант - проверить перед вызовом.

public function Foo() {
    if (condition) DoThing();
}

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

Вариант три - переименовать функцию, чтобы она была более наглядной.

public function Foo() {
    DoThingOnlyIfCondition();
}

private function DoThingOnlyIfCondition() {
    if (!condition) return;
    // do stuff
}

Это "правильное" решение? Или это заходит слишком далеко? Я чувствую, что если бы все было так, то имена функций начали бы дублировать их код.

Насчет того, что это субъективно: конечно, это так, и, возможно, не будет правильного ответа, но я думаю, что здесь все еще прекрасно. Получение совета от лучших программистов, чем я, - второй лучший способ обучения. Субъективные вопросы - это именно то, на что Google не может ответить.

Ответы [ 4 ]

5 голосов
/ 03 июня 2010

Согласно DRY, я бы пошел с первым.

public function Foo() {
    DoThing();
}

private function DoThing() {
    if (!condition) return;
    // do stuff
}

Как только вы привыкнете к шаблону, не так страшно видеть одинокий DoThing() в коде. Вы начнете читать это как EnsureThingDone().

2 голосов
/ 03 июня 2010

Вариант четвертый, заключить предикат и фактический вызов в 3-ю функцию.

function DoThing() {
    // do stuff
}

function DoThingOnlyIfCondition() {
    if (!condition) return;
    DoThing();
}

function Foo() {
    DoThingOnlyIfCondition();
}

// Foo version 2
function FooBar() {
    DoThing();
}

Теперь Foo или любая другая функция может использовать наиболее подходящую версию DoXXX ().

0 голосов
/ 03 июня 2010

Вы можете использовать систему типов. Сделайте параметр DoThing объектом, который вы можете создать, только если выполнены предварительные условия.

Отличный способ сделать это - сделать DoThing методом экземпляра для этого объекта.

0 голосов
/ 03 июня 2010

Мне нравится проверять предварительные условия внутри функции,

public function DoThing()
{
    ValidatePreconditions();
    DoWork();
}

private function DoWork()
{
    //Do the actual work;
}

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

...