In my designs I am quite strict about defining contracts like:
- each resource acquisition must be paired with a release
- each call to start a service must be paired with a call to stop the service
- each observer that attaches to a subject must detach
- and so on
(such contracts are not unusual, like you must pair the open and close of a file or pair new/delete calls in languages that do not employ automatic garbage collection).
Each of these contracts can be tested at run-time to some degree. For example, an observer detaching more times than it has attached can be detected and reported (assert or exception depending on the situation).
So, your question that:
In theory, is it considered more
correct for the code adding the
handler to an object to remember to
remove it than assuming the object
will clean itself up before it goes
out of scope?
Is spot on. The answer is Yes, and not just in theory, but in practice too. In my opinion, these contracts help you avoid sweeping errors under the carpet.
Prescribe to this way off thinking and you are well on your way to building really robust software.