Реализация функции проверяющей что-то и возвращающей ОК или ошибку
От: MozgC США http://nightcoder.livejournal.com
Дата: 29.07.12 21:01
Оценка:
Здравствуйте,

Допустим, нужно проверить, можно ли отправить сообщение пользователю, и если нет, вывести соответствующее сообщение с указанием причины (пример просто один из, т.е. могут быть другие похожие задачи и хочется выбрать типовое решения для использования в проекте).
Представим такую функцию на PHP:

function CanSendMessageToUser(User $user)
{
    if(!$user->AccountEnabled)
    {
        return ...; // вызывающему коду нужно сообщить, что сообщение отправить нельзя потому что пользователь уже неактивен (заблокирован и т.п.)
    }
    else if(/* some other check */)
    {
        return ...; // вызывающему коду нужно сообщить, что сообщение отправить нельзя еще по какой-то причине
    }

    return ...; // сообщение можно отправить
}


У нас есть такие основные варианты:

1) Использовать исключения. Просто, мало кода, но почему-то мне кажется что не очень кошерно использовать тут исключения (наверное потому что исключения я привык использовать для каких-то исключительных ситуаций, которые не должны происходить в нормальном режиме работы).

2) Использовать коды ошибок и функцию для преобразования кода ошибки в текст:

function CanSendMessageToUser(User $user)
{
    if(!$user->AccountEnabled)
    {
        return SendMessageTestResult::ACCOUNT_DISABLED;
    }
    ...

    return SendMessageTestResult::SUCCESS;
}

class SendMessageTestResult
{
  const SUCCESS = 0;
  const ACCOUNT_DISABLED = 1;
  ...
}

function SendMessageErrorCodeToText($errorCode)
{
  switch($errorCode)
  {
    case SendMessageTestResult::ACCOUNT_DISABLED:
      return 'Cannot send message to the user because their account is disabled.';
    ...
  }
}

//Вызывающий код получается чистеньким:

$res = CanSendMessageToUser($user);
if($res !== SendMessageTestResult::SUCCESS)
  return Presenter::GetErrorMessage(SendMessageErrorCodeToText($res));

Минус такого варианта, в том что как-то много кода нам приходится писать (класс с константами кодов ошибок и функцию-конвертер кода ошибки в текст).

3) Возвращать константу SUCCESS или текст ошибки:
function CanSendMessageToUser(User $user)
{
    if(!$user->AccountEnabled)
    {
        return 'Cannot send message to the user because their account is disabled.';
    }
    ...

    return SUCCESS;
}

...

$res = CanSendMessageToUser($user);
if($res !== SUCCESS)
  return Presenter::GetErrorMessage($res);

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

4) Использовать специальный класс типа MethodResult, описывающий результат выполнения метода, и который может содержать код ошибки или описание ошибки:

function CanSendMessageToUser(User $user)
{
    if(!$user->AccountEnabled)
    {
        return MethodResult::ErrorMessage('Cannot send message to the user because their account is disabled.');
    }
    ...

    return MethodResult::Success();
}

...

$res = CanSendMessageToUser($user);
if(!$res->Success)
  return Presenter::GetErrorMessage($res->ErrorMessage);

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

---

Что скажут гуру дизайна и PHP?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.