为什么将有状态对象传递给构造函数是件坏事?

时间:2016-02-26 20:17:14

标签: php oop solid-principles

通过将构造函数传递给有状态对象来实例化对象是我的直觉理解,这是一种不好的做法。以此代码为例:

class MathValues
{
    private $x;

    public function __construct($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    public function getX()
    {
        return $this->x;
    }

    public function getY()
    {
        return $this->y;
    }
}

class MathCalculator
{
    private $mathValues;

    public function __construct(MathValues $class)
    {
        $this->mathValues = $class;
    }

    public function calculateMultiplication()
    {
        return $this->mathValues->getX() * $this->mathValues->getY();
    }
}

$mathValues = new MathValues(2,5);

$mathCalculator = new MathCalculator($mathValues);
$someValue = $mathCalculator->calculateMultiplication();

现在,我已经成为Web开发人员很长一段时间了,直到最近我才开始开发OOP范例,遵循(尽我所能)SOLID原则,面向服务的体系结构等。也有一段时间了我一直在使用Symfony2 / 3框架进行开发。我在那里看到的一切(包括Symfony的服务容器)都说应该使用构造函数来传递其他服务(无状态实例),但我不能在我的生活中找到什么原则说你不应该将有状态对象传递给构造函数。

所以我的问题是在标题中 - 什么原则说将状态对象传递给构造函数是一件坏事?

更新

似乎我的问题还不够明确,所以我更新了我的例子。在这个例子中问题和解决方案是明确的:每次,当我需要乘法时,我需要创建2个类的2个实例。相反,我可以创建一个服务MathCalculator并传递它2个参数 - x和y。所以我需要的只是我想要进行数学运算的所有值的1个实例,以及我需要进行数学运算的每个值的对象(如果需要的话)。

更不用说有状态编程是一个糟糕的动态,我相信分离值不可变对象和根本没有状态的服务。

1 个答案:

答案 0 :(得分:1)

首先,正如您在更新中提到的那样,您已经认识到,每次有不同的MathCalculators操作时,保持实例化新MathValues并不理想。< / p>

您首先要问的是,xy值是否与MathCalculator实际上具有任何特定于域的真实关系。如果它们都可以只是用户输入的随机值,那么将它们放在同一个类中并不好 - S SOLID表示您应该应用单一责任或封装原则。 MathValues的一个实例应该有一个值,y应该成为MathValues的另一个实例,因此在这种情况下MathValues变得多余,您只需使用一个集合或列表号。

我怀疑您使用MathValues作为Data Transfer Object (DTO)

否则,如果xy以某种方式相关,并且它们属于同一个类,例如地理数据或网格引用,您使用MathValues所做的是Anaemic Domain Model反模式和违反Law of Demeter

的示例

您应该将您的业务逻辑放入您的实体中以遵守S SOLID - 了解如何将x和y相乘MathValues的责任,以满足单一责任和封装的责任,你应该将该方法重构为该类。

不可否认,这是值得商榷的,因为实际上您的MathValues看起来也像DDD Value Object,在这种情况下您不需要任何逻辑,而是将MathValues聚合到一个聚合类并将方法放在那里。虽然这是一个决定,但只有在您的域名开始变得更复杂时才能做出决定。