根据构造函数参数的不同,为行为不同的类编写规范


Writing specs for a class that behaves differently depending upon constructor arguments

如果你有一个类,它的响应因构造函数参数的不同而不同,你该如何为这个类编写规范呢?

class Route
{
  function __construct($url, array $methods = array())
  {
    // stores methods and url in private member variables
    // creates a regex to match $url against incoming request URLs
  }
  public function isMatch($url)
  {
    // checks if the incoming request url matches against this url
  }
}

使用例子:

$a = new Route('/users/:id');
$a->isMatch('/users/1') // returns true;
$b = new Route('/users');
$b->isMatch('/users') // returns true

如果我使用phpspec:

中的let函数为这个类设置spec
class Route extends ObjectBehaviour
{
  function let() 
  {
    $this->beConstructedWith('/users/:id')
  }
}

我的规范只能检查这个类的行为是否在其中一种情况下工作。

我考虑过添加setter方法来允许我围绕这个进行测试,但看起来我将为了测试的目的而破坏封装。

我正在努力寻找任何与此相关的内容,所以我开始认为这可能是糟糕的代码气味情况

beConstructedWith()并不总是需要从let()方法调用。您也可以从规格中调用它。

在我看来,用一种以上的方式建立一个对象并没有错。但是,您应该避免在构造函数中做太多的工作。

  1. 构造函数应该只用于获取将在这里设置为成员属性的变量。这里没有更多的逻辑应该做…
  2. 根据第1点的想法,应该有另一个逻辑来决定接下来会发生什么(例如if Object->hasProperty(X) then do x()等)
  3. 那么评论将是简单直接的。

的例子:

class Route
{
    private $url;
    private $methods = array();
    /**
     * Constructor method, sets the attributes to private member variables
     * @param string $url URL pattern
     * @param array $methods Methods that should be used with given URL
     */
    function __construct($url, $methods = array())
    {
        $this->url      = $url;
        $this->methods  = $methods;
    }
    // ...
}