向对象添加数据-验证*然后*添加,或者在添加时验证


Adding Data to an Object - Validate *then* add, or validate as you add?

看下面的例子,

class Cup {}
class MyObject {
    protected $cups = array();
    public function addCup(Cup $cup) {
        if (!in_array($cup, $this->getCups())) {
            array_push($this->cups, $cup);
        }
        return $this;
    }
    public function addCups(array $cups) {
        // Add cups logic, see below
    }
    public function getCups() {
        return $this->cups;
    }
    public function setCups(array $cups) {
        // Set cups logic, see below
    }
}

在这个类中,我们可以使用$myObject->addCup()添加一个Cup,但是我们也可以使用$myObject->addCups()添加多个杯子,或者使用$myObject->setCups()覆盖任何现有的杯子。

我的问题是,在addCups()setCups()方法中,在添加它们之前,您是否验证所有传递的数据都是有效的,或者您是否验证作为添加它们?

场景1,在添加

之前验证
public function addCups(array $cups) {
    foreach($cups as $cup) {
        if (!($cup instanceof Cup)) {
            throw new InvalidArgumentException();
        }
    }
    foreach($cups as $cup) {
        $this->addCup($cup);
    }
}

场景2 ,验证你添加:

public function addCups(array $cups) {
    foreach($cups as $cup) {
        if (!($cup instanceof Cup)) {
            throw new InvalidArgumentException();
        }
        $this->addCup($cup);
    }
}

我欣赏代码中没有太大的区别,但它从根本上改变了对象添加/设置数据的方式。在场景1中,如果您添加的所有数据都有效,则只能向对象添加新数据,而在场景2中,数据实际上将被添加到错误点。

我个人一直在使用场景1,但我忍不住觉得你也可以使用场景2,因为如果你抛出了一个异常,你就不应该继续执行了。

我很想知道是否有一个具体的设计模式可以遵循,或者如果没有人们的意见。

谢谢。

先检查所有项目

允许事务行为,这通常是一件好事。这确保了行为易于理解和调试。

性能方面,它也是可取的。

然而,如果你的目标是"做尽可能多的工作",那么检查每一项,并在可能的情况下添加——如果一项失败,直接跳到下一项。这是一个罕见的用例。

我想说这取决于你是否想把'Cups'的添加作为一个交易。如果您希望在一个或多个杯子失败时,所有杯子的添加都失败,请使用方法1。否则,请执行方法2。

据我所知,这两种方法都是可行的,并且有它们自己的用例。