Подтвердить при входе или перед сохранением? - PullRequest
1 голос
/ 01 апреля 2011

Мой мозг начинает болеть, поэтому я решил спросить здесь.

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

Например, сейчас у меня есть;

public function getSSN($bFormatted = true) { 
    return ($bFormatted) ? $this->format_ssn($this->SSN) : $this->SSN; 
}
public function setSSN($s, $bValidate = false)
{
    // If we're validating user entry, save a copy.
    // Either way, store a trimmed version.
    if ($bValidate): $this->SSNToValidate = $s; endif;
    $this->SSN = str_replace('-', '', $s);
}
public function getSSNToValidate() { return $this->SSNToValidate; }

Что это делает:
* Когда вы устанавливаете SSN, если он выполняется системой (например, из базы данных), тогда он делает setSSN('123456789', false), потому что SSN хранятся в базе данных без черточек.
*Когда вы устанавливаете SSN из пользовательского ввода, он просто setSSN('123-45-6789') затем не только обрезает тире, но и сохраняет необработанную версию для проверки (потому что я хочу проверить на основе формата)
* Когда вы получаете SSN,если запрашивается форматирование (и оно всегда выполняется, кроме случаев, когда вы выполняете запись в базу данных), оно форматирует его на основе другой функции в классе Employee.

Поэтому мой вопрос таков: возможно, я могу добавить проверку всеттер здесь, вместо того чтобы полагаться на монолитную функцию проверки в классе Manager?Поскольку я начинаю сталкиваться с ошибками, возникающими во всем приложении, на данный момент я решил перейти к центральному статическому классу Error Handler, а не каждому менеджеру поддерживать свой собственный список ошибок.

И из-за этого я мог бы легко добавить обработку ошибок к этому:

public function setSSN($s, $bFromUser = false)
{
    if ($bFromUser && !$this->validateSSN($s))
    {
        ErrorHandler::add(array('ssn' => 'Invalid SSN entered')); 
    }
    else
    {
        $this->SSN = str_replace('-', '', $s);
    }
}

Поэтому я предполагаю, что мой вопрос таков: имеет ли это смысл или я теряю себя, перенося валидацию из менеджера (быть выполненным по требованию или непосредственно перед записью в базу данных) к объекту (для выполнения при записи)?

Это в целом универсально, я просто использую SSN в качестве хорошего примера.

Ответы [ 2 ]

3 голосов
/ 01 апреля 2011

Вы всегда должны проверять, когда вы создаете объект или устанавливаете значения в объекте.Таким образом, вы всегда гарантированно получите объект, который находится в допустимом состоянии.Если проверка не в самом объекте, вы не можете гарантировать, что объект когда-либо будет подтвержден.

Пример проверки вне объекта:

Inв этом случае есть ошибка, и мы забыли проверить SSN.

class EmployeeManager
{
    function saveEmployee($employee)
    {
        //Oops, we forgot to validate SSN
        $db->save($employee);  //This is just SQL to persist the employee.
    }
}

//Somewhere else in code...
$employee = new Employee();
$employee->setSSN("FredFlintstone");  //No validation is done here.
$employeeManager = new EmployeeManager();
$employeeManager->saveEmployee($employee);  //This call will persist FredFlintstone because validation was missed.

Пример проверки внутри объекта:

В этом случаеобъект сотрудника проверяет все свои входные данные.Таким образом, мы знаем, что если у нас есть экземпляр сотрудника, все данные в нем действительны.

class Employee
{
    function setSSN($input)
    {
        if(strlen($input) != 9)
        {
            throw new Exception('Invalid SSN.');
        }
        //Other validations...
        $this->ssn = $input;
    }
}

//Somewhere else in code...
$employee = new Employee();
$employee->setSSN("FredFlintstone");  //This call will now throw an exception and prevent us from having a bad object.
$employeeManager = new EmployeeManager();
$employeeManager->saveEmployee($employee);

Кроме того, вы никогда не должны позволять создавать объект, который не полностью инициализирован.Если, скажем, SSN требуется для сотрудника, не указывайте пустой конструктор.Ваши конструкторы должны иметь параметры для всех обязательных полей (в отличие от моего примера, в котором я опущен для ясности).

2 голосов
/ 01 апреля 2011

Общее правило для приложений, основанных на службах, заключается в том, что проверка должна ВСЕГДА происходить на стороне сервера, незадолго до сохранения. При желании вы можете выполнить проверку на клиенте для лучшего взаимодействия с пользователем. Но выполнять проверку только на клиенте (т. Е. В вашем установщике) небезопасно. Никогда не полагайтесь на правильность данных клиента.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...