Best practice-когда оценивать условия выполнения функции

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

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

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 ответов


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

public function Foo() {
    DoThing();
}

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

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


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

function DoThing() {
    // do stuff
}

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

function Foo() {
    DoThingOnlyIfCondition();
}

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

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


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

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

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

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


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

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