2011-12-12 23 views
3

我已经参与了许多Web应用程序项目到达那里面向对象模式和/或“自愈”的结构化方法?

  1. 应用程序预计持续的数据是在一个特定的格式点

  2. 该应用程序将BARF如果从持久化数据的流浪狗格式

  3. 旧“神秘代码”在不好的格式保存数据

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

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

    return parent::save(); 
}   

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

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

回答

2

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

虽然现在它是基于一组Ruby类实现抽象Step,根据yaml配置工作,我猜测在接下来的重写中,我会使用纯粹的Ruby DSL。

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

HealingProcessor.on(impure_data) { 
    replace_bad_value :field => :some_prop, :bad_value => 'bad value', :good_value => 'good_default_value' 
    # etc 
} 
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/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) { 
.... 
+0

+1所付出的努力,但是这也正是排序我试图避免的代码。 –

+0

那么你确实提到了“自我修复”,因为你希望取消这种类型的实施。 try/catch块和日志记录将帮助你做到这一点。 –

+0

@AlanStorm:你最终达成解决方案吗? –