Подтвердить что ты не робот

Различные способы реализации функции "грязного" флага

Почти каждый программист сделал это один раз в своей жизни: установил некоторый флаг, если изменилось значение переменной. Там всегда много свойств, и вы хотите отслеживать, если что-то изменилось

  • в любом свойстве
  • в определенном свойстве
  • или в некоторых наборах свойств

Я заинтересован в различных способах реализации функциональности "грязного флага" для вышеупомянутых ситуаций, кроме того, что флажок стандартного объекта с грязным флагом обновляется при каждом изменении свойства. Там должно быть что-то лучше, чем положить "грязный = истинный" в каждый сеттер: он просто выглядит уродливым и утомительным.

4b9b3361

Ответ 1

Для моего DAO я сохраняю копию исходных значений, полученных из базы данных. Когда я отправляю его для обновления, я просто сравниваю исходные значения с текущим. Это стоит немного в обработке, но это намного лучше, чем наличие грязного флага на каждое свойство.

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

Ответ 2

У меня был базовый класс Entity, предоставляющий Dirty/Removed Logic.

При написании Entity-подклассов вы можете сделать что-то вроде:

public string Name
{
    get { return name; }
    set { setValue("Name", value); }
}

Это прекрасно работает, но имеет болезнь "уродливой струны"...

Сегодня вы можете использовать выражения Lambda Expressions для исключения строк:

set {setValue(x => x.Name, value);}

Или, и я думаю, что это лучшее решение, вы можете использовать AOP:

https://www.postsharp.net/

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

Кроме того, вы можете сохранить список свойств в своем классе (базовый Entity), который будет помнить измененные свойства и получить доступ к этому списку из вашего кода AOP.

Ответ 3

Я создал класс под названием DirtyValue<T>, который имеет исходное значение и текущее значение. При первом использовании он устанавливает как исходное значение, так и текущее значение. Последовательные вызовы устанавливают только текущее значение.

Вы можете узнать, изменилось ли это, сравнив два, с свойством readonly bool, называемым IsDirty(). Используя этот метод, вы также можете получить доступ к исходному значению.

Ответ 4

Если вы устанавливаете "грязный" флаг, понимаете, что вы сохраняете состояние. В какой-то момент вам нужно принять действие на основе этого состояния, иначе вам не нужно будет держать флаг. Итак, тогда возникает вопрос: есть ли другой способ инициировать необходимое действие? Отправка сообщений какого-то рода? Кто потребляет "грязное" состояние и принимает меры, и есть ли более чистый интерфейс для этого уведомления?

Ответ 5

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

Я успешно использовал этот метод в симуляциях - где производитель - это физический цикл, а читатель - это 3D-дисплей.

Ответ 6

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

Ответ 7

Интересная альтернатива явному подходу dirty=true, хотя она, вероятно, слишком сложна для большинства ситуаций и часто неприменима, будет использовать защитные страницы. Задайте страницу памяти как доступную только для чтения (например, VirtualProtect() в Windows) и поймайте сигнал/исключение, когда программа пытается записать страница. Сделайте запись о том, что страница была изменена, затем измените флаги защиты страницы на запись и возобновите выполнение.

Это метод, обычно используемый операционными системами для определения необходимости записи страницы в файл подкачки, прежде чем она будет выведена из ОЗУ.

Ответ 8

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

  • Если хеш же, никаких изменений. (не отправлять в репозиторий или базу данных)
  • если hash different, объект имеет изменения. (обновление)
  • Если ключ не найден, объект новый. (Вставка)
  • Не знаете, как определить, нужно ли удалять объект, кроме удаления процесса по запросу, и не использовать для них отслеживание hashcode.

Я не пробовал это, и хеш-таблица, возможно, не лучший способ отслеживать ключи объектов/хэш-значения. Он сохранил бы mem, только отслеживая только хэш-коды и ключи. Я не уверен на 100%, но я думаю, что некоторые ормы могут использовать этот метод в своих объектах контекста данных/отслеживания.