0

I am trying my best to create a web app to familiarize myself with DDD and ValueObjects. So far everything is working fine, I am just asking myself if I am correctly implementing my value objects. Here is my current state (code stripped from non-essential parts):

class User {

   private $id;

   /**
    * @var Credentials
    */
   public $credentials;

   public function getId() { return $this->id; }

}

class Credentials {

    private $username;
    private $password;

    public function __construct($username, $password) { // no need to detail }

    public function changePassword($newPassword) {
      return new self($this->username, $newPassword);
    }
}

So whenever I want to update my user's password, I have to do $user->credentials = $user->credentials->changePassword("newPassword");

Is this correct ? Should I create a getter and a setter for the $credentials property of my User class ? Should I put the changePassword() method in the User class ?

Any help is greatly appreciated !

Lucio
  • 632
  • 5
  • 21

2 Answers2

3
$user->credentials = $user->credentials->changePassword("newPassword");

That's the right idea.

In this implementation, $username and $password are part of the state of Credentials. You want that state to be immutable; there should be no code that changes that state after the constructor has finished.

However, you need to expose that state somehow; immutable write-only objects don't provide very much business value. Implementing value types as a collection of immutable public properties is a common idiom. Here's an old discussion of how to do that in PHP. Alternatively, you can implement calls that allow the Credentials object to pass copies of that state to other objects.

Should I create a getter and a setter for the $credentials property of my User class ?

Not usually -- your implementation of User has an Id property, which makes it look like an entity. Entities only very rarely allow their internal state to escape. In particular, setters are many nines close to never a good idea -- the point of entities is that they can enforce their own data constraints; they are responsible for ensuring that all changes to their state satisfy the business invariant.

A getter that offers access to immutable state isn't likely to cause problems; a getter that allows the caller to navigate to mutable state is worrisome.

BUT: getters aren't particularly expressive -- a query, possibly supported by a domain service, is often a more flexible choice

Compare:

password = user.password
strength = calulatatePasswordStrength(password.toString)

to

password = user.password
strength = password.strength(calculator)

to

strength = user.passwordStrength(calculator)

Should I put the changePassword() method in the User class ?

Assuming that you are supporting that use case, yes. The Credentials value knows how to calculate a new state of credentials from an old one; the User entity knows how to validate that the user in its current state is allowed to change the credentials in that way.

(Example: a naive security implementation might track when the credentials were last changed, and have policies that restrict password changes, where the correct policy to use depends on other properties of the user. That's way too much work for the credentials object to be doing on its own.)

In particular, the fact that the user's password is actually a bunch of state in a Credentials value object is an implementation detail, which shouldn't be exposed to the code that calls User. In other words, if User were implementing the interface IUser (isolating the implementation details), then I would expect IUser to promise that a changePassword($password) method will be available.

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • Okay, seems more clear to me now. I am going to create a changePassword() method in my User class and make the property private then, that's going to make the code a little bit nicer and easy to read. Thanks a lot ! – Lucio Jun 08 '16 at 20:02
0

Almost I'd say. Key to a value object is it is a value. I.e. you can compare it to another object of the same type and can determine if it's different by its value. In this case I'd expect to be able to see that a Credential where username=x and password=x would be 'equal to' another credential with the same values.

That doesn't necessarily imply you need getters on the fields.

I've got what I think is a fun code kata around this topic on my blog. You can find it here Why Private C# Variables are Not as Private as you Thought

The value object kata is near the bottom. Hope that helps.

Codescribler
  • 2,235
  • 18
  • 22
  • I took a look at your kata, did it without problem. The fact is when a ValueObject is inside an Entity, and I need to access it. I have the habit to create getters/setters for everything, and I'm trying to lose it. However it seems so easy to do `$user->changePassword($password)` than `$user->credentials = $user->credentials->changePassword($password)`... – Lucio Jun 08 '16 at 19:35
  • Do you need the Credentials object at all in this case? Will it have more functionality? – Codescribler Jun 08 '16 at 19:39
  • Actually I don't think, not for now in fact. I thought i would put a `$email` property, but it doesnt fit well in it since it's more a "profile" property in my project – Lucio Jun 08 '16 at 19:42