【问题标题】:DRY and similar queriesDRY 和类似的查询
【发布时间】:2009-02-27 01:51:10
【问题描述】:

在开发一个特定的应用程序时,我一次又一次地编写非常相似的查询。它们并不完全相同,但具有非常相似的形式,并且嵌入在几乎相同的代码块中,例如

$Mysqli = new mysqli;
if ($Stmt = $Mysqli->prepare("SELECT foo 
                              FROM tblFoo 
                              WHERE something = ?")) {
    $Stmt->bind_param('s', $this->_something);
    $Stmt->execute();
    if (0 != $Stmt->errno)
        throw new Exception("blah, blah, blah");
    $Stmt->bind_result($foo);
    while ($Stmt->fetch()){
        $this->_foos[] = new Foo($foo);
    }
    $Stmt->close();
    } else {
        throw new Exception("blah, blah, blah"););
    }
}

然后,在其他地方......

$Mysqli = new mysqli;
if ($Stmt = $Mysqli->prepare("SELECT bar, baz 
                              FROM tblBar 
                              WHERE somethingElse = ?")) {
    $Stmt->bind_param('s', $this->_somethingElse);
    $Stmt->execute();
    if (0 != $Stmt->errno)
        throw new Exception("blah, blah, blah");
    $Stmt->bind_result($bar, $baz);
    while ($Stmt->fetch()){
        // do something else with $bar and $baz
    }
    $Stmt->close();
    } else {
        throw new Exception("blah, blah, blah"););
    }
}

...然后另一个,在其他地方另一个...等等。

这真的违反了 DRY 吗?编写一个类来执行这种查询(使用构造函数参数或表、列、绑定变量等的设置器)然后在我的整个应用程序中重用它似乎没有意义。但同时,我也无法摆脱这种反复无常的感觉。

也许只是写一个简单查询的方法只有这么多,这样一定程度的重复是可以预料的。

想法?

【问题讨论】:

    标签: mysql dry


    【解决方案1】:

    很多人都是这样做的。创建一个代表每个表的类,它们都继承自同一个类。基类可以处理加载和保存数据。因此,如果要加载数据,只需调用 load 方法即可。您可以通过对象的属性设置和访问字段值。

    还有像 hibernate 这样的库可以为你处理很多脏活。

    【讨论】:

    • @Kibbee - 谢谢。我不会使用 Hibernate,但我确实创建了一个 ActiveRecord 类,然后为特定表替换了几个类。
    【解决方案2】:

    我会说这是违规行为。看一眼您的代码(除非我遗漏了什么),除了字符串“foo”和“bar”(重复几次)和您的实际业务逻辑之外,这两个语句是相同的。

    至少你可以提取它。更重要的是,应该提取所有 SQL 字符串。对我来说,它们似乎更像是数据而不是代码。如果你有一个 SQL 字符串、表等数组——那会让重构更明显吗?

    (从代码中提取字符串和其他数据是开始重构的好方法)

    一种可能性,如果您有一个具有表名的对象和一个包含您的业务逻辑的方法,您可以将它传递给一个带有所有样板的“处理器”(这是您那里的所有其余代码) .

    我认为这可能会让它变干。

    (PS。总是更喜欢组合而不是继承。在可以“运行”您的对象的类上使用继承没有任何优势)

    【讨论】:

    • @Bill K。这是一个千钧一发的电话,但我选择了 Kibbee 的回答,因为它更接近我实际处理这个问题的方式。您的 cmets 也非常有帮助——尤其是关于提取字符串作为重构的第一步。 +1 谢谢!
    【解决方案3】:

    您遇到了第一个模块化的愿望。 :-)

    有两种通用解决方案。第一个是抽象对所有(或大部分)类似查询的调用。然后再进行另一组查询。然后到另一个。等等。不幸的是,这导致许多块做同样的事情:调用查询,检查问题,组装结果集,将其传回。这是一个 DAL,但只是一种。它也无法扩展。

    第二个解决方案是抽象查询和返回结果的过程,然后再考虑在此之上抽象数据访问(这基本上意味着你构建了一些组装 SQL 的东西)。这更有可能成为一个合适的 ORM 而不是一个简单的 DAL。扩展它要容易得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-24
      • 2015-06-15
      • 2017-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多