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

报告相同问题?

悬赏问题

  • ¥30 motoradmin系统的多对多配置
  • ¥15 求组态王串口自定义通信配置方法或代码?
  • ¥15 实验 :UML2.0 结构建模
  • ¥20 用vivado写数字逻辑实验报告撰写,FPGA实验
  • ¥15 为什么shp文件会有这种小方块?
  • ¥15 ecplise在连接数据库时显示加载驱动成功但是数据库连接失败
  • ¥15 visionmaster启动失败,提示为“机器不满足授权而被禁用”
  • ¥15 IDEA中圈复杂度如何具体设置
  • ¥50 labview采集不了数据
  • ¥15 Multisim红外倒车雷达仿真中距离问题