dsfb20227 2011-03-31 20:39 采纳率: 0%
浏览 24
已采纳

入境时或保存前验证?

My brain is starting to hurt so I decided I'd ask here.

I have a data object, Employee. Getters, setters, formatters, etc. I have a manager, EmployeeManager, which handles database access and other things. Right now I have a large validation block in EmployeeManager, but I've been wondering if I could move some of that to the setters.

For example, right now I have;

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; }

What this does is:
* When you set an SSN, if it's being done by the system (like from the database) then it does setSSN('123456789', false), because SSNs are stored in the database sans dashes.
* When you set an SSN from user input, it does simply setSSN('123-45-6789') then not only trims the dashes, but also stores a raw version to validate (because I want to validate based on format)
* When you get an SSN, if formatting is requested (and it always is except when you're writing to the database), it formats it based on another function in the Employee class.

So my question is: Could I perhaps add the validation to the setter here, instead of relying on the monolithic validate function in the Manager class? Because I'm starting to have to deal with errors coming from all over the application, I've decided for the moment to move to a central Error Handler static class, rather than each manager maintain its own list of errors.

And because of this, I could easily add error handling to this:

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

So I guess my question is: Does this make sense at all or am I hosing myself by moving validation from the manager (to be performed on demand or just before writing to the database) to the object (to be performed on entry)?

This is overall generic, I'm just using SSN as a good example.

  • 写回答

2条回答 默认 最新

  • douchao1957 2011-03-31 21:18
    关注

    You should always validate when you're creating an object or setting values in the object. This way you are always guaranteed to have an object that is in a valid state. If the validation is not in the object itself you can not guarantee that the object will ever be validated.

    Example validation outside of the object:

    In this case there is a bug and we forgot to validate 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.
    

    Example validation inside of the object:

    In this case the employee object validates all of it's input. This way we know that if we have a instance of an employee all the data within it is valid.

    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);
    

    In addition you should never allow an object to be created that is not fully initialized. If say a SSN is required for an employee then don't supply an empty constructor. Your constructors should have parameters for all required fields (unlike my example which I omitted them for clarity).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办