Можно ли хранить изменяемые свойства объекта домена как объект значения? - PullRequest
7 голосов
/ 17 марта 2012

Существуют определенные части моего UserEntity, которые я хотел бы иметь возможность изменять и передавать, и есть определенные части, которые должны оставаться постоянными.

Например, я НИКОГДА не хочу менять идентификатор моей UserEntity, но такие вещи, как электронная почта или пароль, могут часто меняться и могут использоваться другими объектами за пределами UserEntity.

Один из примеров этого был бы при создании UserEntity. Поскольку UserEntity не может существовать без идентификатора, мой контроллер может создать объект UserData, который будет стандартизировать свойства UserEntity. После того, как mapper создаст сущность в БД, он создаст новый UserEntity и передаст объект id и UserData в конструктор.

Когда UserEntity требуется информация, такая как электронная почта или пароль, он может просто просмотреть свои UserData.

Кажется более портативным, но это перебор? Есть ли лучшее решение?

Примечание

  • Причина, по которой я думаю, что это может быть хорошо: значения изменяемых полей должны быть стандартизированы ... и иногда эти поля должны передаваться за пределы самой сущности. Например, до того, как объект был создан. Создав объект значения, который можно передавать, мы предоставляем стандартизированное место для назначения этих значений из любого места, а также что-то, что можно передавать за пределы объекта.

  • Под «стандартизацией» я подразумеваю, что моя информация должна быть однородной, где бы она ни существовала. Например, email всегда должен иметь длину n и в допустимом формате, name всегда должен иметь длину n и т. Д. Моя цель в том, чтобы я хотел иметь возможность установить их " правила "в одном месте ... и поскольку эти свойства UserEntity (изменяемые) существуют вне самой сущности, иногда они могут потенциально жить самостоятельно, в своем собственном объекте значения.

Ответы [ 2 ]

1 голос
/ 22 марта 2012

Я не думаю, что есть "один верный способ" сделать это (независимо от того, что вы читаете об этом) ... если это имеет смысл в вашей модели, тогда это звучит хорошо для меня.Я не совсем уверен, что вы имеете в виду, когда говорите «многие из этих полей должны быть стандартизированы» и почему это нельзя сделать как часть 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, то эти свойства никогда не будут «жить сами по себе» с ... давайте назовем это «глобальными данными».Когда вы рассматриваете всю систему как единое целое, а не только код от момента к моменту, вполне вероятно, что данные «принадлежат» классу UserEntity.

Что касается статических методов, я не вижу особой причины избегатьих (очевидно), но каждому свое.Многие другие архитектуры были бы немного более сложными, но вот несколько вариантов:

  1. Проверка данных в конструкторе.Проблема в том, что если он не проверяется, вам придется удалить запись в базе данных.Ужасно.
  2. Переместите взаимодействие с базой данных в конструктор вместе с проверкой данных.Это может нарушить вашу предпочтительную объектную модель, и вам просто нужно будет проверить состояние объекта после того, как он создан (т.е. установить открытое свойство $this->status = 'error'; или что-то в этом роде, чтобы сообщить вам, что произошло что-то плохое, что вам придетсяhandle).
  3. Создайте отдельную функцию для проверки данных.Ужасно, потому что это функция, которая конкретно связана с UserEntity и / или его данными.
  4. Или просто создайте отдельный объект UserData, как вы предложили, и покончим с этим.Как и в шаге №2, вам потребуется какое-то свойство $status, указывающее на неудачную проверку.
0 голосов
/ 23 марта 2012

Кажется, это было бы хорошим случаем для набора валидаторов, которые можно использовать независимо от любого предметного объекта - возможно, это моя функционально-программная сторона, но я не вижу проблемы с созданием куча функций, таких как isValidEmail().

Я понимаю, что вам неудобно с кучей статических функций; Вы могли бы рассмотреть статический Validator класс с кучей методов, чтобы сохранить порядок?

В любом случае, вы можете использовать эту проверку вне объекта UserEntity (я предполагаю, что вы говорите о таких случаях, как другие доменные объекты, проверка ввода в контроллере и т. Д.?). Но вы также можете использовать его внутри объекта «UserEntity» - для себя я до сих пор не определил, предпочитаю ли я дезинфекцию и проверку при задании свойства или когда оно сохраняется в постоянном хранилище. В настоящее время я больше склоняюсь к первому через функции сеттера.

...