質問

I have 1 Employee entity which holds a value object of ContactInformation :

Employee.php

class Employee {
    private $contactInformation;

    public function __construct(ContactInformation $contactInformation) {
        $this->contactInformation = $contactInformation;
    }

    public function getContactInformation() {
        return $this->contactInformation;
    }
}

ContactInformation.php

class ContactInformation {
    private $email;        // Required
    private $cellPhone;    // Required
    private $phone;        // Optional
    private $address;      // Optional

    public function __construct($email, $cellPhone) {
        $this->email = $email;
        $this->cellphone = $cellphone;
    }

    /** Here goes a bunch of setter getter for those properties **/
}

If an Employee's phone is changed, is it not better to do just

$employee->getContactInformation()->setPhone($newPhone)

Rather than forcing immutability such as

$employee->setContactInformation(new ContactInformation(/** copy paste here **/));

Going by Eric Evans' book, I understand that when you change a part of a value object, then it is a whole different value object then it was before.

I just cannot get the same conclusion about a little bit more complex object like this ContactInformation, is it supposed to be an Entity?

Need advice, thanks !

役に立ちましたか?

解決

For me, Employee to have dependency on ContactInformation means that you expect to have ContactInformation already set with phones, etc. and then passed to employee, i.e.:

$contanctInfo = new ContactInformation();
$contanctInfo->setPhone(820);
$employee1 = new Employee($contanctInfo);
echo $employee1->getContanctInformation()->getPhone(); // 820

However, that means you would need to make as much ContactInformation objects, as Employee objects, before instantiating each Employee, because:

$contanctInfo = new ContactInformation();
$contanctInfo->setPhone(820);
$employee1 = new Employee($contanctInfo);
$employee2 = new Employee($contanctInfo);
$employee1->getContactInformation()->setPhone(123);
$employee2->getContactInformation()->setPhone(666);

echo $employee1->getContactInformation()->getPhone();
echo $employee2->getContactInformation()->getPhone();

Turns into:

666
666

Because you are changing one and the same object.

In your case, you are instantiating ContactInformation at the same time, when you are instantiating Employee when makes the dependency a bit useless:

$employee1 = new Employee(new ContactInformation());
$employee2 = new Employee(new ContactInformation());

$employee1->getContactInformation()->setPhone(123);
$employee2->getContactInformation()->setPhone(666);

echo $employee1->getContactInformation()->getPhone();
echo $employee2->getContactInformation()->getPhone();

Results into:

123
666

So, if you don't want to make changes on the dependent object before inject it to another object, you don't need a dependency at all. Even more, in real world ContanctInformation is bind to an Employee, not the opposite.

I would make it this way:

class Employee {

    private $_contactInformation;

    public function __construct() {
        $this->_contactInformation = new ContactInformation($this);
    }

    /**
     * @return ContactInformation
     */
    public function getContactInformation() {
        return $this->_contactInformation;
    }
}

class ContactInformation {

    private $_employee;

    private $email;        // Required
    private $cellPhone;    // Required
    private $phone;        // Optional
    private $address;      // Optional

    public function __construct(Employee $employee) {
        $this->_employee = $employee;
    }

    public function setPhone($phone) {
        $this->phone = $phone;
    }

    public function getPhone() {
        return $this->phone;
    }
}

$employee1 = new Employee();
$employee2 = new Employee();

$employee1->getContactInformation()->setPhone(123);
$employee2->getContanctInformation()->setPhone(666);

echo $employee1->getContactInformation()->getPhone();
echo $employee2->getContactInformation()->getPhone();

On the other hand, if Employee has some identificator, so the ContanctInfo retrieves info based on the ID, you can make the injection the way you want it.

他のヒント

Value objects should be immutable, but ContactInformation should not be a value object.

Consider two people who share a house, and therefore have the same address and phone number (it simplifies matters if you assume they don't have a cellular phone or email).

In that situation, they'd have identical ContactInformation objects, but the contact information is still distinctly one person's or another's. If one of them moves out, or buys a cell phone then their contact information will have to change.

As you mentioned in your comment, it's better to consider ContactInformation as a mutable Entity, and not a Value Object.

Interesting discussion. What I do is to have getContactInformation return a clone.

class Employee {

public function getContactInformation() {
    return clone $this->contactInformation;
}
...
$contactInformation = $employee->getContactInformation();
$contactInformation->setPhone('');
$employee->setContactInformation($contactInformation);

By doing so, the value object actually stored inside of Employee is immutable. You always pull a copy, which since it no longer linked to employee, is no longer a value object(one could argue with lots of hand waving) and thus can be modified without upsetting the DDD police.

Works for me and let's me use a form system which expects setters.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top