Search code examples
cqrscommand-query-separation

In CQ(R)S, is it OK to use a Command as a parameter of a model constructor?


Say I have a CreateUser command:

class CreateUser
{
    public string $email;
    public string $password;
    public string $firstName;
    public string $lastName;
    public LocalDate $dateOfBirth;
    public ?string $location;
}

Is it OK if my User model accepts this command as a constructor parameter?

i.e. instead of having this:

class User
{
    public function __construct(
        string $email,
        string $password,
        string $firstName,
        string $lastName,
        LocalDate $dateOfBirth,
        ?string $location
    ) {
       ...

and have the command handler map the command data to the model(s), I could just simply make the model constructors accept the command as a parameter and extract the data they need:

class User
{
    public function __construct(CreateUser $command)
    {
        ...
}

Is this a correct approach, or are there drawbacks?


Solution

  • Is this a correct approach, or are there drawbacks?

    Small drawbacks.

    Drawback #1 - you've added a (small) extra step of work. If I want a User, I first have to get a CreateUser command. So there's an extra step that gets in the way.

    Drawback #2 - because you need a CreateUser, you need values for all of the fields of User and all of the extra fields that User doesn't care about.

    For example, suppose you later decide that CreateUser should have a messageId. Now the code paths that want a User need to invent a messageId that they don't want in order to construct a CreateUser that they don't want so that they can construct the User that they do want.

    Wanting to have a function that accepts a CreateUser and returns a User is perfectly reasonable. It's even reasonable that you would want that function to be close to User.

    You probably don't want that function to be __construct, though. A static helper method would probably be a healthier long term solution.