How to Monitor Changes to an Object

Monitor changes on object property

Depending on how much control you have over how its called, you could make an accessor function. The function could take an object as an argument, and set that object as the current value if the argument is set. For your use you can add a trigger of some type here. If no argument is passed it would return the current value.

Thats the type of API that knockout uses to great effect.

In modern browsers, getters and setters make this easy. For older values you could have an accessing property and then another property that serves as the holder for the data.

Is there a way to monitor changes to an object?

Well, depending on the domain you're working with, you can use backbone.js - it has a "model" object that you can extend and connect up to callbacks that get triggered by events automatically when the model is changed - that is, you set a field on the model, and it will automatically fire an event that you can listen to. You have to define your models to extend its Model, and call a setter function instead of setting properties directly, but it's very useful, I recommend it.

Just for clarity's sake, the event is fired from the model on change, so it's fired even if you set the value of the attribute programmatically or in the console.

How to monitor changes in an attribute? (as opposted to change /of/ the attribute)

Operations like push are not performed on the attribute itself, but on the array object referenced by that attribute.

The only reliable way to observe such operations is therefore from within that array object – by tie-ing it to an appropriate class. But this is fairly dark Perl magic and generally inadvisable (slow, difficult to do correctly, may expose bugs in other modules, and very low-level).

The often better approach is to choose a design that stops exposing an array reference. E.g. instead of push @{ $foo->attribute }, 42 you might offer a method $foo->push_attribute(42). In that method you can implement any hooks you need.

Monitor changes to an array object

If your array is a property in your class, you can use property observers. willSet is called before the change, didSet is called after. It is really easy.

var myArray:[Int] = [1, 3, 4] {
didSet {
println("arrayChanged")
}
}

This will print array changed if I add an Int, remove and Int, etc. I generally put it on one line though:

var myArray:[Int] = [1, 3, 4] { didSet { println("arrayChanged") } }

Python object that monitors changes in objects

Here is an implementation for you. Note that the objects you monitor must be hashable and picklable. Note also the use of a WeakKeyDictionary which means that the Monitor won't stop the monitored objects from being deleted.

from weakref import WeakKeyDictionary
from cPickle import dumps

class Monitor():
def __init__(self):
self.objects = WeakKeyDictionary()
def is_changed(self, obj):
current_pickle = dumps(obj, -1)
changed = False
if obj in self.objects:
changed = current_pickle != self.objects[obj]
self.objects[obj] = current_pickle
return changed

class MyObject():
def __init__(self):
self.i = 1
def change_somehow(self):
self.i += 1

If you test it like this

object1 = MyObject()
monitor = Monitor()
print monitor.is_changed(object1)
object1.change_somehow()
print monitor.is_changed(object1)
print monitor.is_changed(object1)

It prints

False
True
False

Vue.js: Monitor Dynamic Changes To Object

For Vue 1, it should be constructed like this in order to allow Vue to detect the change to the object:

this.$set('filterOperators.' + fieldName, response.data);

Reference: Reactivity in Depth

How to monitor changes to a mutable object?

You can test for the other variables in your property method and use them as part of a cache key:

class CachedProperties(object):
@property
def expensiveValue(self):
cacheKey = (self.var1, self.var2)
if cacheKey in self._expensiveValueCache:
return self._expensiveValueCache[cacheKey]

# No cached value available, calculate it now
res = self._expensiveValueCache[cacheKey] = calculation(self.var1, self.var2)
return res

Now you defer calculation until you actually need the expensive value and var1 or var2 have changed.

How to track changes to an object graph?

After people pointed out that old may be pointing to new, I added a copy constructor and things are looking much better.



public class Old{
protected Old old;
protected List stuff;

//Needed for JUnit
public Old(){
}

//Here's my new copy constructor.
public Old(Old old){
this.stuff=new ArrayList(old.getStuff());
this.old=null;
}

public Old(List stuff){
this.stuff=stuff;
old=new Old(this);//Here I now call the copy constructor.
}

public void add(){
stuff.add(2);
}

public void match(){
System.out.printf("old:%d\nnew:%d\n",old.getStuff().size(),stuff.size());
}

public List getStuff(){
return new ArrayList(stuff);
}

@Test
public void testOld(){
List list=new ArrayList();
list.add(1);
Old thing=new Old(list);
thing.add();
thing.match();
}
}

Output:


old:1
new:2


Related Topics



Leave a reply



Submit