Отслеживание состояния объектов - PullRequest
1 голос
/ 11 февраля 2009

В PHP, как лучше всего отслеживать состояние объекта, чтобы узнать, был ли он изменен? У меня есть объект репозитория, который создает новые объекты, которые затем считываются / изменяются другими компонентами и в конечном итоге возвращаются в репозиторий. Если объект изменился, я хочу, чтобы хранилище сохраняло данные обратно в постоянное хранилище (БД).

Я могу придумать четыре варианта:

  1. Используйте внутреннее логическое свойство с именем $ _modified, которое обновляется каждым сеттером при внесении изменений (утомительно, если сеттеров много).
  2. Какой-то ужасный уродливый хак, использующий serialize () и сравнивающий строки (я уверен, что это очень плохая идея, но я решил добавить ее для полноты)
  3. Нечто подобное описанному выше, но с хэшем свойств объектов (не уверен, что он будет работать с объектами, содержащими другие объекты)
  4. Взятие клонов объектов по мере их выхода из репо и сравнение того, что входит (сложнее, чем кажется, потому что как вы узнаете, с каким клоном сравнивать объект?)

    или ...

  5. Какой-то другой хитрый трюк, о котором я не знаю?

Спасибо
Jack

Ответы [ 4 ]

3 голосов
/ 11 февраля 2009

Вариант 1 - использование логического флага - это лучший способ. С точки зрения производительности, а также общего удобства и мобильности.

Все остальные опции связаны с чрезмерными издержками, которые в данном случае просто не нужны.

1 голос
/ 11 февраля 2009

Во-первых, я обычно думаю, что $ измененное или $ dirty свойство - лучшее решение здесь.

Но причиной, по которой я пишу, был ваш комментарий, что это будет

утомительно, если много сеттеров

Мне интересно, если вы не используете PHP5?

Если да, то это идеальное использование магического метода __set (). Вы даже можете использовать его как есть, вызывая существующие сеттеры из метода __set ().

Например:

class some_concept
{

    private $x = 1;
    private $y = 2;
    private $dirty = false;

    // This represents your existing setter methods
    function set_y($i)
    {
        $this->y = $i;
    }

    function __set($name, $value)
    {
        if ($value != $this->{$name}) $this->dirty = true;

        return $this->{'set_' . $name}($value);
    }

    function __get($name)
    {
            return $this->{$name};
    }
}

Однако в вашей идее сравнения сериализованных строк есть некоторые достоинства. Сериализация может быть дорогой. Это так.

Но это самое точное решение в вашем списке. Представьте, что вы загружаете объект выше, устанавливая $ y в 0, затем устанавливаете его обратно в 2, затем сохраняете. Это грязно? Это скажет так, но на самом деле, он находится в том же состоянии, в котором он был при загрузке.

Тест, который я использовал бы здесь, показывает, насколько дорогой является ваш save (). Если сохранение - это очень дорогой вызов API, транзакция с БД и т. Д., Вы можете обнаружить, что стоит сериализовать загружаемый объект и сохранить его в хеше md5.

Если эта операция, которая займет доли секунды, может сохранить многосекундную транзакцию, то она действительно может стоить этого.


Наконец, я хочу указать на противоположное мнение по этому вопросу от Дэмиена Каца. Кац - талантливый разработчик, который создал CouchDb и в настоящее время работает на MySQL.

Его Коды ошибок v Исключения сообщение длинное, но очень хорошее чтение по этой теме.

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

Прежде всего, он говорит о том, как создавать атомарные классы так же, как транзакции SQL. Основная идея заключается в том, что вы делаете копию объекта, изменяете его состояние и только на последнем шаге, если он успешен, вы меняете эту копию на основной объект. Это позволяет значимые функции отмены. Подобный шаблон, хотя его трудно внедрить в существующее приложение, также обеспечивает решение этой проблемы is_modified.

1 голос
/ 11 февраля 2009

Возможно, вы захотите взглянуть на шаблон Единица работы , поскольку это большая проблема, для решения которой он предназначен. При изменении объектов они регистрируются или пассивно регистрируются в UoW, который отвечает за отслеживание того, какие объекты были изменены, и за выяснение того, что необходимо сохранить обратно в базу данных в конце воспроизведения.

0 голосов
/ 11 февраля 2009

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

Одно и то же содержимое должно выдавать одинаковое хеш-значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...