Это не обязательно относится только к PHP, но это моя проблема.
Недавно я написал несколько проверочных функций, которые получают некоторый аргумент, а затем проверяют его правильность различными способами. Например, checkXmlString ($ xml) проверит, содержит ли данная строка правильно сформированный XML-документ и т. Д.
Вопрос в том, должны ли эти функции возвращать логическое значение или генерировать исключения и ничего не возвращать в случае успеха.
Так
function checkAbc($arg) { if ($arg is invalid) return false; else return true; }
или скорее
function checkAbc($arg) { if ($arg is invalid) throw new Exception(...); }
Согласно почти всем книгам, написанным на предмет, и не в последнюю очередь, согласно логике, название должно быть самым большим намеком на то, что делает функция. В этом случае применяется только первый вариант. Как уже говорила Бет Ламед, функция «проверка» не должна генерировать исключения, просто чтобы вы знали, в порядке ли проверка или нет.
Если вы хотите исключения, вы можете переименовать его в DeserialisationToAbc () или TryParseAbc () или что-то подобное.
Вопрос в том, должны ли эти функции возвращать логическое значение или
исключения и ничего не вернуть в случае успеха.
Сначала определите, является ли это исключительной ситуацией, чем используйте исключение. Ваш случай не кажется исключительным. Это просто условие, поэтому относитесь к нему как к условию. Если оно было похоже на «Правильно, но в некоторых ситуациях не удается, вы не можете определить, чем вы можете использовать исключение.
Посетите эти две ссылки и узнайте больше об исключении
Вы могли бы бросить InvalidArgumentException чтобы проверить, являются ли аргументы неверными, но я думаю, что для вашего случая, если вы пишете «контролеры», они должны возвращать логическое значение, чтобы вы не знали, продолжать ли операции, например, если foobar.xml на самом деле является CSV-файлом, который вы не хотели бы продолжайте свою работу, но вы не хотели бы поймать исключение либо
<?php
class Checker {
function validXml($string)
{
if(!(bool)$string) throw new \InvalidArgumentException("Cannot pass empty string as argument", 1);
// Check
// Is valid XML ? Return True : return false
}
}
try {
if(new Checker->validXml($xmlString))
{
// Continue Operation
// return
}
// Notify User of invalidity
// return
} catch (\InvalidArgumentException $e) {
// Log args
//
}
Это, конечно, немного основано на мнении, но спросите себя, что делать вы ожидать от функции, как checkEmail()
? Целью метода является проверка чего-либо, поэтому вы, вероятно, ожидаете ответа на этот вопрос.
$isValid = checkEmail($arg);
Я думаю, что большинство разработчиков ожидают, что в качестве возвращаемого значения будет использоваться bool, это делает код читабельным Ожидаются неверные значения, поэтому нельзя сказать, что это исключение, если передан неверный аргумент. Чтобы вернуть сообщение об ошибке, я бы использовал параметр out:
function checkAbc($arg, &$errorMessage)
{
if ($arg is invalid)
{
$errorMessage = 'The argument is invalid because of...';
return false;
}
else
{
$errorMessage = '';
return true;
}
}
Я действительно не совсем уверен, какая форма предпочтительнее в целом.
С одной стороны, в случае ошибки вам понадобится полезное сообщение, поэтому вы получите смешанные возвраты (true / string), что является уродливым, или возврат массива (даже более уродливый). Исключение дает вам это бесплатно.
С другой стороны, не следует ожидать, что функция check … () будет генерировать исключение, потому что обнаружение, что «это не является действительной вещью», не является чем-то исключительным и не является ошибкой.
Третий способ будет называть это «throwIfFalse», но это тоже безобразно ….
Хм ….
Одно из возможных решений:
interface Checker {
public function check();
public function getMessage();
}
class WhateverChecker implements Checker { ... }
class ClientOfChecker {
public function doStuff() {
$checker = new Checker();
if (! $checker->check() )
throw new Exception($checker->getMessage());
}
}
Тем не менее, это кажется невероятно многословным, и, могу ли я сказать, Javaesque для меня.
Обычно есть 2 типа функций относительно вашего вопроса:
Чистая функция, которая проверяет, выполняется ли условие.
Функция, которая обеспечивает выполнение условия и изменяет поток управления, если это не так.
Разные языки программирования могут иметь разные соглашения об именах обоих типов. принимать C++
Например, одно общее название CHECK_XXX
для типа 2 и IsXXX
для типа 1.
Вот пример, взятый из руководство библиотеки google-log:
CHECK(fp->Write(x) == 4) << "Write failed!";
CHECK_NE(1, 2) << ": The world must be ending!";
Другим примером является maktaba служебная библиотека для Vimscript
, где maktaba#value#IsXXX()
используется для проверки, является ли аргумент определенного типа, в то время как maktaba#ensure#IsXXX()
используется для обеспечивать IsXXX
держит и выдает исключение в противном случае.
function! TakeAString(name)
" Ensure argument type is String.
let name = maktaba#ensure#IsString(a:name)
endfunction
if maktaba#value#IsString(name)
" Branch if name is a String.
echo name
endif
Итак, вот в чем суть: выберите тот, который подходит вам лучше всего, и назовите функцию в соответствии с языковым соглашением. В терминах вариантов использования обоих, примерно, используйте тип 2 для проверки предварительного условия, такого как тип аргумента, и используйте тип 1 в условных выражениях.