可以将域实体的可变属性作为值对象存储吗?
我希望能够更改和传递UserEntity的某些部分,并且某些部分应该保持不变。
例如,我永远不想更改我的UserEntity的id,但电子邮件或密码等内容可能会经常更改,也可能被UserEntity之外的其他对象使用。
其中一个例子是创建一个UserEntity。 由于UserEntity不能存在没有id,我的控制器可以创建一个UserData对象来标准化UserEntity属性。 在映射器在数据库中创建一个实体之后,它将创建一个新的UserEntity并在构造函数中传入id和UserData对象。
当UserEntity需要电子邮件或密码等信息时,只需查看其UserData即可。
似乎更便携,但这是矫枉过正? 有更好的解决方案吗?
注意
我认为这可能是好的原因:可变字段的值需要被标准化......有时这些字段需要在实体本身之外传递。 例如,在实体创建之前。 通过创建一个可以传递的值对象,我们提供了一个标准化的点来从任何地方分配这些值,以及可以在实体外传递的东西。
通过“标准化”我的意思是我的信息需要统一,无论它存在于何处。 例如, email
需要始终n
长度和有效的格式, name
总是需要是n
长度等我的目标是在这里,我想能够在单点设置这些“规则” ..并且由于UserEntity的这些属性(可变属性)存在于实体本身之外,有时它们可能独立存在于它们自己的价值对象中。
我不认为有一种“真正的方法”来做到这一点(不管你读到什么),如果它在你的模型中有意义,那对我来说听起来很好。 当你说“许多这些领域需要标准化”,以及为什么不能作为UserEntity的一部分来完成时,我不确定你的意思。 也就是说,如果没有完全独立的对象类,你可以完成你想要做的事情。
评论/批评:
你所建议的并不是真正遵循严格的“对象”模型,即UserData只是由UserEntity的属性组成的事物,而且这些属性之间没有其他的基础关系。
我不确定为什么你需要一个单独的对象在实体之外传递......如果你需要这些数据,为什么你不能传递UserEntity并从那里访问? 在将数据传递给UserEntity构造函数之前,您需要怎么处理这些数据,而这些数据不能轻易地通过在stdClass的实例中收集数据然后在UserEntity中处理它来完成?
如果是我,我会做更像下面的事情(例如,创建一个新用户):
<?
// 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's 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());
?>
编辑以解决更多信息提供:
你说这些属性存在于UserEntity之外,并且它们可能独立存在......你的意思是这些属性可以被收集,使用和丢弃,甚至不用于UserEntity对象? 如果是这种情况,那么一个单独的对象将完全适合该数据。 如果不是,如果数据总是从属于现有的或未来的用户实体,那么这些属性将永远不会“独立存在”,我们称之为“全局数据”。 如果将整个系统视为一个整体,而不仅仅是代码,那么很可能数据“属于”UserEntity类。
至于静态方法,我没有看到特别的理由来避免它们(显然),但是对于他自己来说。 许多其他体系结构会稍微复杂一些,但以下是一些选择:
$this->status = 'error';
或者类似的东西来告诉你一些不好的东西发生了,你必须处理)。 $status
属性才能表示验证失败。 看起来,这对于一组可以独立于任何域对象使用的验证器来说是一个很好的例子 - 也许这是我的函数式编程方面出来的,但是我没有看到创建一堆函数的问题像isValidEmail()
。
我知道你对一堆静态函数感到不舒服, 你会考虑一个静态的Validator
类而不是一堆方法,以保持整洁?
无论哪种方式,你可以在UserEntity
对象之外使用这种验证(我假定你正在讨论像其他域对象,控制器中的输入验证等情况)。 但是你也可以在'UserEntity'对象内部使用它 - 对于我自己,我还没有确定在设置属性或将其保存到持久存储区时,我是否更喜欢卫生和验证。 我现在更倾向于通过二传手功能倾向于第一。
上一篇: Is it okay to store a domain entity's mutable properties as a value object?