Can I save the properties of a mutable domain object as a value object?

There are certain parts of my UserEntity that I would like to be able to modify and transmit, and there are certain parts that should remain constant.

For example, I NEVER want to change my UserEntity identifier, but things like email or password can change frequently and can be used by other objects outside of UserEntity.

One example of this could be the creation of UserEntity. Since UserEntity cannot exist without id, my controller can create a UserData object that will standardize UserEntity properties. After mapper creates the object in db, it will create a new UserEntity and pass the id and UserData object in the constructor.

When UserEntity needs information such as email or password, it can just look at UserData.

It seems more portable, but is it overkill? Is there a better solution?

Note

  • The reason why I think this might be good: the values ​​of the variable fields must be standardized ... and sometimes these fields must be passed outside of the entity itself. For example, before creating an object. By creating a value object that can be transferred, we provide a standard place for assigning these values ​​from anywhere, as well as what can be transferred outside the object.

  • By "standardization" I mean that my information should be uniform, wherever it exists. For example, email should always be length n and in a valid format, name should always be length n , etc. My goal here is that I would like to be able to set those “rules” in one place ... and since these UserEntity properties (mutable) exist outside the object itself, sometimes they can potentially live on their own in their own value object.

+7
source share
2 answers

I don’t think there is a “one true way” for this (no matter what you read about it) ... if that makes sense in your model, then that sounds good to me. I'm not quite sure what you mean when you say “many of these fields should be standardized” and why this cannot be done as part of UserEntity, but whatever. However, it is likely that you can accomplish exactly what you are trying to do without a completely separate class of objects.

Comments / Critical Reviews:

What you offer does not actually correspond to a strict "object" model, that is, UserData simply consists of things that are really UserEntity attributes, and there are no other fundamental relationships with these attributes.

I'm not sure why you need a separate object that will go outside the object ... if you need data, why can't you just bypass UserEntity and access it from there? What do you need to do with the data before passing it to the UserEntity constructor, which cannot be just as easily implemented when collecting data together in an stdClass instance and then processing it in UserEntity?


If it were me, I would do something more like the following (for example, to create a new user):

 <? // assume an appropriately defined UserEntity class... // I'm using stdClass just to keep the parameters together to pass all at once // I'm assuming some basic user data passed from the browser $user_data = (object) array( 'email' => $_REQUEST['email'], 'name' => $_REQUEST['name'], 'password' => $_REQUEST['password'], 'confirm_password' => $_REQUEST['confirm_password'] ); /* validateData is static so it can be called before you create the new user It takes the $user_data object to validate and, if necessary, modify fields. It also takes a $create flag which indicates whether the data should be checked to make sure all of the necessary fields are there to create the user with. This allows you to call it on update with the $create flag unset and it will pass validation even if it missing otherwise required fields. It returns $result, which indicates pass or failure, and the potentially modified $user_data object */ $create = TRUE; list($result, $user_data) = UserEntity::validateData($user_data, $create); // equivalence allows you to pass back descriptive error messages if ($result === TRUE) { // create the user in the database, get back $user_id... $user = new UserEntity($user_id, $user_data); } else { // return error to user } // access user data either individually, or if you want just make a getter // for the entire group of data, so you can use it just like you would a // separate UserData object send_double_opt_in($user->getUserData()); ?> 

Change address of additional information:

You say that these properties exist outside of UserEntity, and they can potentially live on their own ... Do you mean that these properties can be collected, used and discarded, not even intended for the UserEntity object? If this happens, then a separate object will be completely suitable for this data. If not, if the data is always subject to either the existing or the future UserEntity, then these properties will never "live independently" of ... let it be called "global data". When you look at the entire system as a whole, and not just code from moment to moment, it is likely that the data "belongs" to the UserEntity class.

As for static methods, I see no particular reason to avoid them (obviously), but for each of them. Many other architectures will be a little more complicated, but here are a few options:

  • Confirm the data in the constructor. The problem is that if it is not checked, you will have to delete the database record. Ugly.
  • Move database interaction with the designer along with data validation. This may violate your preferred object model, and you just need to check the status of the object after creating it (i.e. set the public property $this->status = 'error'; or something like that to tell you that something happened it’s bad that you have to handle).
  • Create a standalone function to validate the data. Awful because it is a function that is specifically associated with UserEntity and / or its data.
  • Or just create a separate UserData object, as you suggested, and do with it. As with step # 2, you need to have some kind of $status property to indicate a failed check.
+1
source

This seems to be a good example for a set of validators that can be used independently of any domain object - maybe this is my side of functional programming, but I don't see a problem creating a set of functions like isValidEmail() .

I understand that you are uncomfortable with a bunch of static functions; Do you consider a static Validator class with a bunch of methods to keep things going?

In any case, you can use this check outside the UserEntity object (I suppose you are talking about cases like other domain objects, input validation in the controller, etc.?). But you can also use it inside the UserEntity object - I still haven’t decided for myself whether I prefer sanitation and checking when a property is set or when it is stored in persistent storage. Currently, I'm leaning more toward the former, through the setter functions.

0
source

All Articles