One of the hardest questions for me to answer is, "Why are you doing this?" It's also an excellent question, one that checks what I am working on. I recently found myself asking this question when trying to use something I've never tried to use before: weak references to DOM elements.
For those of you coming from JavaScript-land, you know that once you hold a DOM element as a property, it will last as long as the object you attached that property to. (Depending on the usage, longer.) This is because XPConnect generates a "strong" reference to the element, which through the magic of XPCOM reference counting, requires the element not be deleted until all strong references are gone - including yours. Weak references are different. They are objects which hold a pointer to your real target, but they don't require the real target "stay alive". In JavaScript pseudo-code, it looks a little like this:
function getWeakReference(obj) {
var weakPtr = {
_realPtr: obj,
QueryReferent: function(aIID)
{
if (this._realPtr)
return this._realPtr.QueryInterface(aIID);
return null;
},
QueryInterface: function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWeakReference) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};
return weakPtr;
}
There's one thing this code can't show you: Some time in the future,
weakPtr._realPtr could be destroyed, and set to null. That
doesn't happen in normal code (thank heaven!). But with weak references, it
can happen at any time.
There's a long list of sub-projects and sub-sub-projects, etc., each of which seems to require I look at something I hadn't tried yet. Here's the current list, and how I started thinking (wrongly) I needed weak references.
(Continued on the next page...)
nsIWeakReference
object. Unfortunately, I didn't see many examples of
nsIWeakReference in use, so I figured I needed to
write a testcase for nsIWeakReference objects from
elements.nsIWeakReference
object without a real element pointer). Forcing JavaScript garbage
collection didn't fix that, as this was a XPCOM cycle collector task.
There's also (currently) no obvious way to force XPCOM cycle collection
from XPCShell, so I realized I needed to add XPCOM cycle
collection to Components.utils.Hence why I started writing this blog article, to analyze my own planning and determine if I really needed to do all the steps. In writing this, I realized that I'd made an error in my logic. Everything from item 4 onward takes place in a separate DOM window, in a wizard. That means the template, the template editing code, the repeated XML fragments, the broadcast/observer code, all of it, would not live very long. After the user finished their work with the template, all these pieces of code would be inaccessible to the user and to other components, and XPCOM cycle collection would presumably clean them up.
Individually, each step in the list leads logically to the next one. Taken as a complete picture, step 10 makes an incorrect statement, and nothing after it matters. Timed observers do NOT need to hold weak references to the element, since neither the element nor the observer will be around for the rest of the application's life.
However, items 11 and 12 would still be useful - perhaps not to me, but to others. I still think they need doing, but considering the size of this "requirements stack trace" -- and the dozens of other things I have to get working for Verbosio 0.1 "Proof of concept", I'm not going to spend any immediate time on them.
Why am I sharing all this? It's a classic forest-for-the-trees problem. If you find yourself writing code for this grand project, and doing something so far from it you can't see how you got there... maybe you need to step back and write it all down. In this case, it helped me realize I was off-track. However, if everything checked out, I would have gladly continued to work on weak references, knowing I was still progressing towards my ultimate goal. (Certainly, items 1 through 9 are still valid statements, and I should continue working on "timer-based observations of properties".) Writing out this "requirements stack trace" can help you see if you went astray, and if you did, tell you where to get back on track. If you didn't go astray, it gives you confidence that you're doing the right thing.
Ideally, it shouldn't take you very long to write it all out - say, 15 minutes for a fast typist on a computer. If it does take longer to write out all the steps, you really do have a stack overflow to worry about, and you should think about ways you can cut back to #1. Whether you find the path is correct from start to finish, or has a flaw in it, answering the question, "Why am I doing this?" is always useful.
Posted by WeirdAl at October 22, 2009 12:07 AM