Если мне назвали функцию от нескольких мест, и она требует, чтобы некоторое условие было встречено для чего-нибудь, что она делает для выполнения, где то условие должно быть проверено? В моем случае это для рисования - если кнопка мыши удерживается, то выполните логику рисунка (это делается в обработчике движений мыши для того, когда Вы перетаскиваете.)
Опция, которые, как каждый говорит, помещают ее в функцию так, чтобы она, как гарантировали, будет проверена. Абстрактный, если Вы будете.
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.
Согласно DRY, я бы выбрал первый.
public function Foo() {
DoThing();
}
private function DoThing() {
if (!condition) return;
// do stuff
}
Как только вы привыкнете к шаблону, увидеть в вашем коде одинокий DoThing ()
уже не так страшно. Вы начнете читать его как EnsureThingDone ()
.
Вариант четвертый: заключить предикат и фактический вызов в третью функцию.
function DoThing() {
// do stuff
}
function DoThingOnlyIfCondition() {
if (!condition) return;
DoThing();
}
function Foo() {
DoThingOnlyIfCondition();
}
// Foo version 2
function FooBar() {
DoThing();
}
Теперь Foo или любая другая функция может использовать наиболее подходящую версию DoXXX ().
Вы можете использовать систему типов. Сделайте параметр для DoThing объектом, который можно создать, только если переданы предварительные условия.
Изящный способ сделать это - сделать DoThing методом экземпляра для этого объекта.
Мне нравится проверять предварительные условия внутри функции,
public function DoThing()
{
ValidatePreconditions();
DoWork();
}
private function DoWork()
{
//Do the actual work;
}
Таким образом, я уверен, что все надлежащие предварительные условия выполнены перед выполнением моей функции, и потребителю не нужно добавлять ненужные код каждый раз, когда вызывается моя функция.