用于“自我修复”的OO模式和/或结构化方法?

时间:2011-12-12 22:08:44

标签: php python ruby oop self-healing

我参与的许多网络应用程序项目都达到了

的程度
  1. 应用程序希望持久化数据采用特定格式

  2. 如果持久数据偏离该格式

  3. ,应用程序将进行barf
  4. 旧的“神秘代码”是以错误的格式保存数据

  5. 这通常会导致应用程序开发人员使用大量验证条件来混淆模型代码。那是

    function save()
    {
        if($model->getSomeProp() == 'bad value')
        {
            $model->setSomeProp('good default value');
        }
    
        return parent::save();
    }        
    

    是否有更好的模式和/或系统来处理这些情况,所述模式和/或系统不依赖开发人员为每个版本编写完美的迁移脚本和/或验证代码?我特别感兴趣的是其他开发人员如何清理这些(根据我的经验)常见的长期问题。

    特别是寻找LAMP Stack / PHP解决方案,但非常欢迎来自其他常见中间件语言/平台(ruby,python等)的解决方案和方法。

2 个答案:

答案 0 :(得分:2)

我们使用配置文件提供的应对每个已处理项目执行的步骤列表。这样可以验证,轻微更改数据,查找,检索和合并来自外部源的某些属性等。

虽然现在它基于一组实现抽象Step的Ruby类,根据yaml配置工作,我想在下一次重写时我会使用纯Ruby DSL。

所以最后,你会有这样的事情:

HealingProcessor.on(impure_data) {
  replace_bad_value :field => :some_prop, :bad_value => 'bad value', :good_value => 'good_default_value'
  # etc
}

答案 1 :(得分:2)

至少你正在处理这种类型的行为尽可能接近数据库交互,如果你的代码库充满了这些类型的检查,那么可能会更糟糕。

如果我的任务是清理这种类型的东西,我认为我要做的第一件事就是设置方法来抛出自定义异常代码,这样我就可以记录调用代码并找到我的应用程序的哪个部分以不正确的方式格式化数据。

例如,您可以执行以下操作:

class CustomException extends Exception
{
    const CODE_BAD_FORMAT = 1;

    protected code;

    public function setCode($code)
    {
        $this->code = $code;
    }

    public function getCode()
    {
        return $this->code;
    }
}

class Model extends ParentModel
{
    function save()
    {
        if ($model->getSomeProp() == 'bad value') {
            $badValueFound = true;
            $model->setSomeProp('good default value');
        }

        // Now that you are using try/catches you don't need a return value
        parent::save();

        if ($badValueFound) {

            $e = new CustomException();
            $e->setCode(CustomException::CODE_BAD_FORMAT);

            throw $e;
        }
    }
}

// Calling code
try {
    $model = new Model();

    $model->setSomeProp('ohnoes im bad format');

    $model->save();

} catch (Exception $e) {

    if ($e->getCode() === CustomException::CODE_BAD_FORMAT) {
        error_log(__METHOD__ . ': Called save with bad format'); 
    } else {
        throw $e; // Some other exception occurred b/c the code() didn't line up so bubble up
    }
}

// All is well b/c made it through the try / catch block... so onto the next logic

现在,您可以调用save(),如果遇到错误的格式,您可以抛出异常并检查调用中的代码,如果代码匹配(预期的格式错误),那么您可以实现一些记录跟踪呼叫代码点。

另外,你不会在这个过程中破坏任何东西,因为保存仍然会发生,但你必须确保对try()块的任何调用都包含在try / catch块中,否则你将获得异常如果抓不到的话。

另一个想法可能是跟踪模型类中的错误格式构造,因此您最终不会在整个地方复制相同的字符串:

class Model
{
    const BAD_FORMAT_MALFORMED_NAME = 'format for a malformed name';
    const BAD_FORMAT_MALFORMED_ADDRESS = 'format for malformed address';
}

....
if($model->getSomeProp() === self::BAD_FORMAT_MALFORMED_NAME) {
....