Maintain list of attached event handlers (.Net 1.1)

P

Peter Duniho

[...]
Let me put it this way:
A basic programming rule that I (and not only I) always obey is: Clean up
references as soon as I don't need them anymore.

Fine. Remove them then. It doesn't matter. I have said this several
times. I do not know why you insist on dwelling on the issue.
As, in this case, I don't care whether it takes 1/100 or 1/1,000 of a
second, how can it be a performance issue? Again, /you/ mentioned
"performance" first.

I don't understand what the concern of "superfluous things" is if not as
regards to performance. However, fine...I'll take as granted that this is
a question of aesthetics and not performance. Your argument still fails:
The result of your misinterpretation of why I don't
want to do superfluous things. It's not for performance reasons. It's
just
illogical to do something that does not have to be done.

But it _does_ have to be done. The alternative to is to do something else
that otherwise does not have to be done.

You are arguing in favor of a more complicated implementation, so that you
can avoid something that in theory doesn't have to be done. But the only
scenario in which it doesn't have to be done is the one in which you
complicate the implementation.

The complicated implementation "does not have to be done" any more than
removing non-existent handlers "does not have to be done". So, how is it
that you feel aesthetically it makes more sense to choose doing the thing
that doesn't have to be done that is more complicated, than to choose the
thing that doesn't have to be done that is simpler?
(yes, I know "it
doesn't hurt" - but doing something that doesn't hurt but that is not
necessary is still illogical)

It is only illogical if it's true that it's not necessary. It's necessary
unless you are intent on doing something else that doesn't otherwise need
to be done. I admit, in this context it appears to be unnecessary. But
only because you are intent on doing something else that otherwise is
unnecessary.
[...]
I think, everything is said about it, don't you, too? :)

If I thought that "everything is said about it", I would stop saying
things. As long as you continue to present illogical arguments, I will
continue to point out the flaws in the logic.

Pete
 
A

Armin Zingler

Peter Duniho said:
[...]
Let me put it this way:
A basic programming rule that I (and not only I) always obey is:
Clean up references as soon as I don't need them anymore.

Fine. Remove them then. It doesn't matter. I have said this
several times. I do not know why you insist on dwelling on the
issue.

I'm dwelling on it because you are again saying "it doesn't matter".
Completely wrong. It does matter a lot because it is the precondition for
the whole discussion.

I don't understand what the concern of "superfluous things" is if
not as regards to performance. However, fine...I'll take as granted
that this is a question of aesthetics and not performance.

Glad to read this, though I'd call it logic not aesthetics.
Your
argument still fails:


But it _does_ have to be done.

Yes, but not twice. It /has/ already been done. The code has alrady been
written in order to do it /before/. You are ingoring the preconditions. I
explained why they are how they are. If you like to discuss under
different preconditions, do it with whomever because it won't help
/me/. A answer to a question that I did not ask, doesn't help.
The alternative to is to do
something else that otherwise does not have to be done.

You are arguing in favor of a more complicated implementation, so
that you can avoid something that in theory doesn't have to be done.

Correct. Only "theory" must be replaced by "practice".
But the only scenario in which it doesn't have to be done is the
one in which you complicate the implementation.

The complicated implementation "does not have to be done" any more
than removing non-existent handlers "does not have to be done". So,
how is it that you feel aesthetically it makes more sense to choose
doing the thing that doesn't have to be done that is more
complicated, than to choose the thing that doesn't have to be done
that is simpler?

I'm afraid, I don't understand this sentence.


The whole situation can be expressed VB-ish: (no, not executable...)

If immediatelly remove handlers? then 'programmer's decision
immediatelly remove handlers
if do more than necessary? then 'programmer's decision
do more than necessary 'means: detach some handlers a second
'time when closing the form
'(aka illogical)
else
maintain a list of remaining handlers
do only what's necessary 'means: only detach remaining handlers
'when closing the form (aka logical)
end if
else
'...
end if

- You are still trying to write the lower Else part, but the first
If-expression has already been evaluated True. That's the precondition.
The corresponding Else part is completely out of interest. Feel free to
discuss it with somebody else but it's not what I am interested in.

- At the second If, you decide for True because you want to avoid the
"maintain a list..." job, whereas I decide for the else block. I do accept
the additional programming work ("maintain...") in order to "do only what's
necessary", whereas you don't.


Our different decisions at the 2nd "If" are caused by differently weighting
the pros and cons. For me, the True block is almost unacceptable whereas you
accept it. To me it is almost unimportant how much work it takes to avoid an
almost unacceptable situation. The additional reason to choose the Else
block was pure technical interest in whether and how it is possible.
Meanwhile I know that it is not possible the way I was looking for,
nevertheless it is possible. Therefore I do it. If it wasn't possible at
all, I would have to swallow the bitter pill and choose the True block.

So, we won't find an agreement because we have different weightings.

[...]
I think, everything is said about it, don't you, too? :)

If I thought that "everything is said about it", I would stop saying
things. As long as you continue to present illogical arguments, I
will continue to point out the flaws in the logic.

No problem. I will repeat my arguments until you got them and see that
your's are illogical. I thought we are grown up enough to avoid this endless
loop. Obviously you are not. Anyways, I won't have to add anything new.


Armin
 
J

John Saunders [MVP]

Armin Zingler said:
[...]
And you called it "catching" too. That doesn't make it right. More
particularly, the word "listen" implies some sort of active role.

That's your interpretation. As I know what events are, I know what "listen
to an event" means. As you also know what events are, you should als know
what "listen to an event" means. I have used it in the past, unless when
teaching beginners, sufficient times without misinterpretation by the
reader.
You can use the word "listen" if you like, and we will even
understand you. My point is to be sure you understand that there is
no actual active listening going on.

You can be sure that I know this.
It hurts nothing to have a
delegate attached to an event, as that involves no actual run time
code execution.

Let me put it this way:
A basic programming rule that I (and not only I) always obey is: Clean up
references as soon as I don't need them anymore. There is no reason to
challenge this every time. Every time, I do not have to count the bytes
potentially freed, then decide if the amount legitimates writing the
removement of the reference. Instead, I simply remove it because I don't
need it anymore. That's the basis rule.

Technology changes. That changes basic rules. This rule, which used to be
basic, needs to be challenged in an environment that includes garbage
collection.

In .NET, it is only rarely a good idea to follow your basic rule.
 
P

Peter Duniho

I'm dwelling on it because you are again saying "it doesn't matter".
Completely wrong. It does matter a lot because it is the precondition for
the whole discussion.

It's not. It never was. Removing the event handlers in the middle has no
bearing on what the most efficient way to clean up at the end is.
Glad to read this, though I'd call it logic not aesthetics.

To make a logical presentation, you have to base it on something. Logic
does not exist by itself. It requires axioms and operators. You haven't
stated any axioms yet, so you cannot claim that it's "logic".

My axiomatic goals are performance and memory usage. You seem to think
those are not relevant, and I have said that's fine. However, you haven't
stated any other axiomatic goals on which you claim to base your
decisions. I'm left with aesthetics, simply because that's a viable goal
in code design at least some of the time and I have not guessed any other
axiomatic goals you might have.

If you would like to state explicitly the axiomatic goals that guide you
design, please feel free to do so. Please do NOT feel free to claim that
your design is "logical" if you have not yet stated what axiomatic goals
are used as the starting point for that "logical" conclusion.
Yes, but not twice. It /has/ already been done. The code has alrady been
written in order to do it /before/.

"Before" what? "It" what? Your posts would make a lot more sense if you
would be more explicit about your nouns, instead of using pronouns. When
you use pronouns in such an isolated context, I have to make some
assumptions as to what they mean. You haven't declared a noun in advance
of the pronoun, and you are unhappy with the assumptions I am making about
your intent. So stop forcing me to make assumptions.
You are ingoring the preconditions. I
explained why they are how they are. If you like to discuss under
different preconditions, do it with whomever because it won't help
/me/. A answer to a question that I did not ask, doesn't help.

This all started with a very general, vague question about your overall
goal. The only two replies you received both said essentially the same
thing. If you wanted an answer to a different question, you should have
been more clear about that.
[...]
The complicated implementation "does not have to be done" any more
than removing non-existent handlers "does not have to be done". So,
how is it that you feel aesthetically it makes more sense to choose
doing the thing that doesn't have to be done that is more
complicated, than to choose the thing that doesn't have to be done
that is simpler?

I'm afraid, I don't understand this sentence.

Which sentence don't you understand? Out of the three that you quoted,
that is.
The whole situation can be expressed VB-ish: (no, not executable...)

If immediatelly remove handlers? then 'programmer's decision

This is fine. It doesn't affect the rest of the discussion.
immediatelly remove handlers
Fine.

if do more than necessary? then 'programmer's decision

You will have to define "do more than necessary". By any obvious
interpretation of the phrase, your conclusion does not result in not doing
more than necessary.
do more than necessary 'means: detach some handlers a second
'time when closing the form
'(aka illogical)

The cost of detaching some handlers a second time when closing the form is
LOWER than the following clause:
else
maintain a list of remaining handlers

THIS is expensive. To maintain the list of remaining handlers is "more"
than to unsubscribe some handlers that have already been unsubscribed.
You cannot claim that you are doing "more than necessary" by unsubscribing
some handlers that have already been subscribed while at the same time
ignoring that you are doing "more than necessary" by maintaining a list of
remaining handlers.
do only what's necessary 'means: only detach remaining handlers
'when closing the form (aka logical)

Can you not see, in your own way of presenting the situation, that in the
supposed "do more than necessary" clause, you have only one action, while
in the supposed "not do more than necessary" clause, you have two? How is
doing one thing "more" than doing two things?
end if
else
'...
end if

- You are still trying to write the lower Else part, but the first
If-expression has already been evaluated True. That's the precondition.

No, I am not "still trying to write the lower Else part. I am trying to
explain to you that it does not matter what the first "if" condition is.
The "do the least necessary" answer is still to simply traverse the entire
data structure when the form closes.
The corresponding Else part is completely out of interest. Feel free to
discuss it with somebody else but it's not what I am interested in.

Nor am I. In nearly every post, I explain to you that it's irrelevant,
and yet in every reply you come back and tell me that you think I'm still
talking about it. How many times do I have to tell you I'm not talking
about that before you figure out that I'm not talking about that?
- At the second If, you decide for True because you want to avoid the
"maintain a list..." job, whereas I decide for the else block. I do
accept
the additional programming work ("maintain...") in order to "do only
what's
necessary", whereas you don't.

I'm not talking about additional programming work. I'm talking about code
execution work. That said, you have MORE of BOTH. In what way is that
not "doing more than is necessary"?
Our different decisions at the 2nd "If" are caused by differently
weighting
the pros and cons.

Only if by "differently weighting the pros and cons" you mean "Armin is
completely ignoring the cost of maintaining the list of not-yet-removed
handlers".

You claim the decision is about "not doing more than is necessary", and
yet your solution is definitely to do more than is necessary.

Now, if you have some other criteria than how much you are "doing", that's
a different matter. But you have to state that criteria for me to
comprehend it. So far, all you are writing is "doing more than
necessary", and the way I interpret that is that you are talking either
about the work in programming, the work of the code executing, or both.
From what you've written, I have narrowed that down to "the work of the
code executing", but even by that criteria, your conclusion is wrong.
For me, the True block is almost unacceptable whereas you
accept it.

But you have not stated a logically correct reason for it to be that "the
True block is almost unacceptable".
To me it is almost unimportant how much work it takes to avoid an
almost unacceptable situation. The additional reason to choose the Else
block was pure technical interest in whether and how it is possible.
Meanwhile I know that it is not possible the way I was looking for,
nevertheless it is possible. Therefore I do it. If it wasn't possible at
all, I would have to swallow the bitter pill and choose the True block.

Why is writing less code, and executing less code, a "bitter pill"? For
most people, that's a win-win situation. For some reason, you are
completely against it. You spend less time working on the code, it's
simpler and so less likely to have bugs, and it takes less time to run.
What's so "bitter" about that?
So, we won't find an agreement because we have different weightings.
No problem. I will repeat my arguments until you got them and see that
your's are illogical.

You have less of an understanding of "logic" than you appear to think you
have.
I thought we are grown up enough to avoid this endless
loop. Obviously you are not. Anyways, I won't have to add anything new.

You already did. I've replied to it (see above).

Pete
 
A

Armin Zingler

John Saunders said:
Technology changes. That changes basic rules. This rule, which used
to be basic, needs to be challenged in an environment that includes
garbage collection.

In .NET, it is only rarely a good idea to follow your basic rule. --

Well, in the German VB.Net group, there were 4 people that agree with me in
this point (4 out of 4). Even the GC doesn't collect objects that are still
referenced. It is common practice and considered clean programming to
remove references to objects that are not needed anymore. Maybe you haven't
heard of it yet.


Armin
 
A

Armin Zingler

As you are not even open to my attempts for an objective explanation of the
situation - which I tried with my VB p-code - the alternatives, their costs
and of why we disagree, I start thinking you are too narrow-minded for a
further discussion. This shall not be my problem anymore.

I don't know why you are not able to accept that we think different, that
we evaluate situations differently, that we call different situations
(un)acceptable, that we consequently decide different, and that we have
a different understanding of logic and clean programming, and we even
use different words (that are well understood in my native language,
sorry) for the same thing. As I've always been appreciated for my
efforts to use clean approaches and for my logical and clean programming
I keep on doing it my way. (I know you consider it all wrong and I know
nothing about everything.)

Though, thanks for participating in this discussion. I'm off...


Armin
 
J

John Saunders [MVP]

Armin Zingler said:
Well, in the German VB.Net group, there were 4 people that agree with me
in
this point (4 out of 4). Even the GC doesn't collect objects that are
still
referenced. It is common practice and considered clean programming to
remove references to objects that are not needed anymore. Maybe you
haven't heard of it yet.

That's it, I'm sure.
 
D

Damien

Well, in the German VB.Net group, there were 4 people that agree with me in
this point (4 out of 4). Even the GC doesn't collect objects that are still
referenced. It is common practice and considered clean programming to
remove references to objects that are not needed anymore. Maybe you haven't
heard of it yet.

Armin

Hi Armin,

Sorry to butt in, possibly with more unwelcome advice. Have you
considered the fact that it used to be best practice to always free
memory as soon as possible, but that now under the GC, the freeing of
memory is done when it is required/when it is convenient.

Now, apply this analogy to the cleaning up of your event handlers.
You're "cleaning up as soon as possible". Peter and John are
advocating "cleaning up when it's convenient".

Let's also consider the fact that, in this case, you have to perform
this clean up in order to ensure that the overall system continues to
run efficiently (no "orphan" objects attached to live objects). In
this case, you have to ensure that resources get cleaned up no matter
what - in the face of possible exceptions and the like - which would
surely lead to you using John/Peters suggestion anyway (possibly with
a comment above it, if you think it's going to trip you/others up
later such as "Of course, some of these may have already been
removed").

Damien

PS - your survey of 4 people on the German newsgroup about which
option would be advocated may or may not be significant - it may come
down to how you've phrased the problem. Thus far, on this newsgroup,
you've got 2 knowledgable individuals recommending a different
approach. I've stayed silent thus far because I agreed wholeheartedly
with what they were saying.
 
P

Peter Duniho

As you are not even open to my attempts for an objective explanation of
the
situation - which I tried with my VB p-code

Not only am I open to those attempts, I used them to point out to you the
fallacy in your argument. Claiming that I am "not even open" to your
approach is a non-starter and demonstrably false, as I have at every step
of the way been happy to discuss the issue in whatever context you've
offered.
- the alternatives, their costs
and of why we disagree, I start thinking you are too narrow-minded for a
further discussion. This shall not be my problem anymore.

You have chosen a particular design and refuse to consider the possibility
that a different one might be better, and _I_ am the one who is "too
narrow-minded"? That's funny!
I don't know why you are not able to accept that we think different, that
we evaluate situations differently,

If by that you mean that I evaluate the situation based on concrete,
objective criteria, while you are unable to state what your actual design
goals are, then yes...we do evaluate situations differently.
that we call different situations (un)acceptable,

I haven't called any situation "unacceptable". What I have done is point
out your failure to _explain_ why you consider a particular situation
"unacceptable".
that we consequently decide different,

Yes, I am deciding using objective measures while you appear to be using
intuition. A classic Meyes-Briggs personality conflict.
and that we have
a different understanding of logic and clean programming,

Two people cannot have a "different understanding of logic". One can
understand logic while another does not, but logic is inherently rigorous
and not open to subjective differences of understanding.

Since I have publicly stated the basis and analysis behind my logic, while
you have not done so, I think it's pretty clear here that I understand
logic. I leave the rest of the conclusion to the reader.
and we even
use different words (that are well understood in my native language,
sorry) for the same thing.

I use the words that match those used by Microsoft in their .NET
documentation. You use terminology that you made up. However, whatever
the case, differences in terminology have NOTHING to do with _this_
thread. I understand that you are still sore about being chastised for
misusing the word "catch", but you need to get over it. And it has
nothing to do with this thread.

Pete
 
A

Armin Zingler

Damien said:
Hi Armin,

Sorry to butt in, possibly with more unwelcome advice.

Nah, no problem. :) Advice is always welcome.
Have you
considered the fact that it used to be best practice to always free
memory as soon as possible, but that now under the GC, the freeing
of memory is done when it is required/when it is convenient.

I know this, but if you don't release references, the GC does not even has
the /chance/ to free memory. That's why it is common practice to release
references as soon as possible. Not in order to free memory immediatelly but
to make it possible. (But I don't go as far as some people that even set
/local/ variables to Nothing at the end of a procedure. That's too much for
me).

I'm afraid, there is nothing new I can add. Instead, I can offer a (IMO)
good comparison:


Imagine, you know 50 people. From time to time you lend things to them.
Every 12/31 you want all lended things back. You have two choices:

a) At 12/31, call all the people and tell everyone to give the things back.
This means, calling also those people that have already given everything
back. It doesn't hurt to call them, but I call it "illogical" (please
replace it by the word of your choice). The phone costs or the time that
it takes is not an issue, but simply doing it although it is not necessary
is IMO not acceptable.

b) Everyone who borrows anything is put on a list. As soon as it's given
back, he is removed from the list. At 12/31, only the people on the list are
called.


You won't be suprised that I favor b) even if I have to maintain a list. I
do this because I consider it the "cleaner" approach.

I guess you favor a) ? :) I accept this opinion - I just don't want to be
handled like an idiot because mine is different.

PS - your survey of 4 people on the German newsgroup about which
option would be advocated may or may not be significant - it may
come down to how you've phrased the problem.

The question in the other group was only about "release references as soon
as possible". I referred to John's mentioning of the "basic rule" (which is
the immediate release). I only asked there to insure myself that I was not
seeing things throughout the past years. :)
Thus far, on this
newsgroup, you've got 2 knowledgable individuals recommending a
different
approach. I've stayed silent thus far because I agreed
wholeheartedly with what they were saying.


Though, thanks for your opinion. I like the way you express it. Thank you!
(and this is not ironic)


Armin
 
R

Rory Becker

PS - your survey of 4 people on the German newsgroup about which
option would be advocated may or may not be significant - it may come
down to how you've phrased the problem. Thus far, on this newsgroup,
you've got 2 knowledgable individuals recommending a different
approach.
I've stayed silent thus far because I agreed wholeheartedly
with what they were saying.

+1

Appologies for not adding much to this except my vote, but Damien has said
it all quite nicely.
 
P

Peter Duniho

Sorry to butt in, possibly with more unwelcome advice. Have you
considered the fact that it used to be best practice to always free
memory as soon as possible, but that now under the GC, the freeing of
memory is done when it is required/when it is convenient. [...]

As you can see (from his reply), the question of whether or not to
unsubscribe the event handlers as soon as they can be continues to
distract Armin from the real issue: how to clean up when the form is
closed.

IMHO, it would be better to leave off the question about whether to
unsubscribe the handlers as they are used. I agree (obviously) that
there's no need to unsubscribe the handlers except at the end. But since
it's still more efficient to simply traverse the tree an unsubscribe all
of the events, even those that have already been unsubscribed, the
question of whether or not he unsubscribes them as they are used is just a
red herring.

The real question here IMHO is whether to make any attempt to track which
event handlers have been unsubscribed. I take as granted (because Armin
insists) that the event handlers _will_ be unsubscribed as they are used,
and I still come to the conclusion that a simple tree traversal at the end
to unsubscribe all of the events is superior to any sort of scheme
attempting to track what's left to unsubscribe.

I also note that even if one is going to track what's left to unsubscribe,
Armin's solution is inefficient and far too complex. But that's yet
another issue, and since I don't agree that the tracking should be done in
the first place, I won't waste much time talking about that. :)

Pete
 
P

Peter Duniho

[...]
Imagine, you know 50 people. From time to time you lend things to them.
Every 12/31 you want all lended things back. You have two choices:

a) At 12/31, call all the people and tell everyone to give the things
back.
This means, calling also those people that have already given everything
back. It doesn't hurt to call them, but I call it "illogical" (please
replace it by the word of your choice). The phone costs or the time that
it takes is not an issue, but simply doing it although it is not
necessary
is IMO not acceptable.

b) Everyone who borrows anything is put on a list. As soon as it's given
back, he is removed from the list. At 12/31, only the people on the list
are
called.


You won't be suprised that I favor b) even if I have to maintain a list.
I
do this because I consider it the "cleaner" approach.

Your analogy fails because a phone call is far more expensive than writing
something on a list. Also, you are dealing with numbers that are so small
that managing the list is relatively easy, even for a human being.

Those characteristics do not translate to your problem. In particular,
the unsubscribing operation is incredibly _inexpensive_. Much less
expensive than the act of maintaining _any_ list, however small. And
while maintaining your list of subscribed handlers isn't too bad as long
as the number is small, code should be scalable and your approach will
incur greater and greater performance penalties as the number of nodes in
your tree grows.
I guess you favor a) ? :) I accept this opinion - I just don't want to
be
handled like an idiot because mine is different.

Nobody is treating you like an idiot. Don't confuse the act of point out
your mistakes as treating you like an idiot.
The question in the other group was only about "release references as
soon
as possible".

Then that is entirely inapplicable to the point I have been making. As I
have stated each time you bring it up: you may unsubscribe the event
handlers as soon as you like. I wouldn't bother with it myself, but it's
not a fundamental design problem.

So, the answer you receive in the other group is entirely irrelevant to
the point I am making.

Pete
 
A

Armin Zingler

A friend told me: "I am adding zero to zero all day long".
I asked: "Why do you do this?"
He answered: "Because it goes sooo quick and it doesn't hurt!"
Me: "Ummmm.... yes, that makes a LOT of sense......."
Me: "But why don't you visit a psychiatrist to stop this?"
He said: "It costs!"
Me: "Ah, I see...But wouldn't it be nice to stop this even if it costs?"
He said: "But why? It goes so quick and it doesn't hurt!"

I stopped trying to convince him.
 
P

Peter Duniho

A friend told me: "I am adding zero to zero all day long".
[...]

I stopped trying to convince him.

So you're trying to say I should stop trying to convince you?
 
D

Damien

Nah, no problem. :) Advice is always welcome.


I know this, but if you don't release references, the GC does not even has
the /chance/ to free memory. That's why it is common practice to release
references as soon as possible. Not in order to free memory immediatelly but
to make it possible. (But I don't go as far as some people that even set
/local/ variables to Nothing at the end of a procedure. That's too much for
me).
Okay. I was just trying to highlight the fact that what was once a
best practice of "release immediately" (with respect to freeing
memory) is now a) not followed, and b) because of the GC design, not
even possible - it's all entirely under the GCs control, and it
follows a different strategy.

I'm afraid, there is nothing new I can add. Instead, I can offer a (IMO)
good comparison:

Imagine, you know 50 people. From time to time you lend things to them.
Every 12/31 you want all lended things back. You have two choices:

a) At 12/31, call all the people and tell everyone to give the things back.
This means, calling also those people that have already given everything
back. It doesn't hurt to call them, but I call it "illogical" (please
replace it by the word of your choice). The phone costs or the time that
it takes is not an issue, but simply doing it although it is not necessary
is IMO not acceptable.

b) Everyone who borrows anything is put on a list. As soon as it's given
back, he is removed from the list. At 12/31, only the people on the list are
called.

You won't be suprised that I favor b) even if I have to maintain a list. I
do this because I consider it the "cleaner" approach.

I guess you favor a) ? :) I accept this opinion - I just don't want to be
handled like an idiot because mine is different.
I guess what Peter especially is trying to get you to focus on is the
fact that all strategies for release have attendent overheads. Have
you ever done any robust COM programming in a C derived language? It's
amazing how complex it is to just make sure your reference counting
code is correct, and handles the edge cases - and that was because the
COM model was based around the "release as soon as possible" approach.

I know you've stated you're not looking at this from a performance
perspective, but from a "clean code" perspective. In Peter's code, we
can see 1 operation, in 1 place, possibly with the comment "Some of
these may have already been removed", which goes through the whole
tree and removes all of the handlers. I can go and look at that one
chunk of code, and know that I am *sure* that all of the handlers are
being removed when the form closes.

Contrast this with your solution. I have to read this "same" chunk of
code, and see that it is removing only those handlers which haven't
been removed. But I then need to go and review each handler, and
verify that it is removing itself correctly. And I then need to
examine all of the list maintenance procedures, and ask myself
questions such as "is this list operation thread safe?", "Does it need
to be?". Only after I've done all of that would I be as confident that
your solution is removing all of the handlers.

And even if I had verified your solution, I'd probably still go back
to the final "chunk" which does the cleanup and remove the list
checks, and let it remove all of the handlers (again, adding the
comment if you so wish), because a) I know that the removal code is
cheeper to run than the list checkup code (okay, that is a performance
argument), BUT b) because I'm going to use a belt and braces approach.

Sorry - I don't know if you know or understand the phrase "belt and
braces". I don't know if there's a German equivalent. It refers to the
practice of ensuring something happens (in this case, your trousers
staying up) by the use of more than method (using a belt, and also
using braces).

This post turned a bit epic. Apologies.

Damien
 
A

Armin Zingler

Damien said:
Okay. I was just trying to highlight the fact that what was once a
best practice of "release immediately" (with respect to freeing
memory) is now a) not followed, and b) because of the GC design, not
even possible - it's all entirely under the GCs control, and it
follows a different strategy.

I know this all. I already wrote that it is not done to release
memory immediatelly, but to give the GC the /chance/ to clean up objects.
Without releasing unrequired references, objects will /never/ be destroyed.


I'm afraid, there is nothing new I can add. Instead, I can offer a
(IMO) good comparison:

Imagine, you know 50 people. From time to time you lend things to
them. Every 12/31 you want all lended things back. You have two
choices:

a) At 12/31, call all the people and tell everyone to give the
things back. This means, calling also those people that have
already given everything back. It doesn't hurt to call them, but I
call it "illogical" (please replace it by the word of your
choice). The phone costs or the time that it takes is not an
issue, but simply doing it although it is not necessary is IMO not
acceptable.

b) Everyone who borrows anything is put on a list. As soon as it's
given back, he is removed from the list. At 12/31, only the people
on the list are called.

You won't be suprised that I favor b) even if I have to maintain a
list. I do this because I consider it the "cleaner" approach.

I guess you favor a) ? :) I accept this opinion - I just don't
want to be handled like an idiot because mine is different.
I guess what Peter especially is trying to get you to focus on is
the fact that all strategies for release have attendent overheads.
Have you ever done any robust COM programming in a C derived
language? It's amazing how complex it is to just make sure your
reference counting code is correct, and handles the edge cases - and
that was because the COM model was based around the "release as soon
as possible" approach.

I've heard of it. :) Fortunatelly, in VB classic it was simpler to handle,
though I know what was going on under the hood (addref/releaseref...). I
like the GC approach more.
I know you've stated you're not looking at this from a performance
perspective, but from a "clean code" perspective. In Peter's code,
we can see 1 operation, in 1 place, possibly with the comment "Some
of these may have already been removed",

Right. The very last sentence is the reason why it is not an acceptable
solution (for me). I'm afraid, I can not add anything new to the rest of
your posting.

Doing it Peter's way is /intentionally/ writing code that /intentionally/ is
sometimes doing things that do not have to be done. Even if those
superfluous things are "inexepensive" and "don't hurt" (just like adding
zero to zero which also doesn't make sense...), why should I decide for
intentionally writing this code? That's what I call an "illogical" decision
(you may call it different, of course). I don't want to write illogical
code. I accept writing more code in order to prevent me from writing
illogical code - yes, even if it costs. Sometimes the logical way is longer.
Peter's solution has such a big drawback that it is not acceptable for me.
You probably don't consider it being a "big" drawback, but for me it so big
that it is /unacceptable/.

/As a consequence/, I /had to/ find a way to avoid the situation above.
Assuming this, the next decision was to "maintain a list...". That's an
obvious decision (because if you want to store an unknown number of items,
a list/arraylist/whatever is what a programmer does).

What has always been ignored in this thread is the 2nd reason why I asked
here: As an experienced programmer - I guess all the people in this
thread are - I came to the point where I wondered how to store a certain
piece of information. Programmers store and retrieve information all day
long, so we know how it works. But in this case I did not know how to do
it: How can I store information in variables that can later be used with
the Addhandler/Removehandler keyword? (in addition: without handling each
object type and event individually to be able to maintain it in a single
list; meanwhile I know that it is not possible and I accepted it)

-> This is just a technical question <-

Don't you sometimes want to learn things just for the sake of learning?
It doesn't matter whether you will ever use the knowledge, but you are just
interested in it. In this case, I felt that the question was very
interesting because i haven't had the case not to know how to store a
piece of information for a long time. Therefore I asked here.


Armin
 
D

Damien

Okay. I was just trying to highlight the fact that what was once a
best practice of "release immediately" (with respect to freeing
memory) is now a) not followed, and b) because of the GC design, not
even possible - it's all entirely under the GCs control, and it
follows a different strategy.

I know this all. I already wrote that it is not done to release
memory immediatelly, but to give the GC the /chance/ to clean up objects.
Without releasing unrequired references, objects will /never/ be destroyed.


[...]
I'm afraid, there is nothing new I can add. Instead, I can offer a
(IMO) good comparison:
Imagine, you know 50 people. From time to time you lend things to
them. Every 12/31 you want all lended things back. You have two
choices:
a) At 12/31, call all the people and tell everyone to give the
things back. This means, calling also those people that have
already given everything back. It doesn't hurt to call them, but I
call it "illogical" (please replace it by the word of your
choice). The phone costs or the time that it takes is not an
issue, but simply doing it although it is not necessary is IMO not
acceptable.
b) Everyone who borrows anything is put on a list. As soon as it's
given back, he is removed from the list. At 12/31, only the people
on the list are called.
You won't be suprised that I favor b) even if I have to maintain a
list. I do this because I consider it the "cleaner" approach.
I guess you favor a) ? :) I accept this opinion - I just don't
want to be handled like an idiot because mine is different.
I guess what Peter especially is trying to get you to focus on is
the fact that all strategies for release have attendent overheads.
Have you ever done any robust COM programming in a C derived
language? It's amazing how complex it is to just make sure your
reference counting code is correct, and handles the edge cases - and
that was because the COM model was based around the "release as soon
as possible" approach.

I've heard of it. :) Fortunatelly, in VB classic it was simpler to handle,
though I know what was going on under the hood (addref/releaseref...). I
like the GC approach more.
I know you've stated you're not looking at this from a performance
perspective, but from a "clean code" perspective. In Peter's code,
we can see 1 operation, in 1 place, possibly with the comment "Some
of these may have already been removed",

Right. The very last sentence is the reason why it is not an acceptable
solution (for me). I'm afraid, I can not add anything new to the rest of
your posting.

Doing it Peter's way is /intentionally/ writing code that /intentionally/ is
sometimes doing things that do not have to be done. Even if those
superfluous things are "inexepensive" and "don't hurt" (just like adding
zero to zero which also doesn't make sense...), why should I decide for
intentionally writing this code? That's what I call an "illogical" decision
(you may call it different, of course). I don't want to write illogical
code. I accept writing more code in order to prevent me from writing
illogical code - yes, even if it costs. Sometimes the logical way is longer.
Peter's solution has such a big drawback that it is not acceptable for me.
You probably don't consider it being a "big" drawback, but for me it so big
that it is /unacceptable/.

I'll try to put my point more briefly than last time. Because having 1
small piece of code where I can see exactly what is happening is
easier to comprehend, and be sure it is correct, than a large number
of blocks of code, through the source, which all have to be read and
understood before you can be sure that the code is doing the right
thing.

You example of adding zero being a wasted operation? How would you
write the following function:

Function ABC takes two arrays (which most both be 1 dimensional arrays
of integers with the same length). It must return a new array, of the
same length as the inputs, where the value at each position is the sum
of the input values at the same position. (Exception throwing code for
length mis-match omitted).

Option 1:

Public Function ABC(ByVal ar1() As Integer, ByVal ar2() As Integer)
As Integer()
Dim out(ar1.GetUpperBound(0)) As Integer

For i As Int32 = 0 To ar1.GetUpperBound(0)
out(i) = ar1(i) + ar2(i)
Next
Return out
End Function

Option 2:

Public Function ABC(ByVal ar1() As Integer, ByVal ar2() As Integer)
As Integer()
Dim out(ar1.GetUpperBound(0)) As Integer

For i As Int32 = 0 To ar1.GetUpperBound(0)
If ar1(i) = 0 Then
If ar2(i) = 0 Then
out(i) = 0
Else
out(i) = ar2(i)
End If
Else
If ar2(i) = 0 Then
out(i) = ar1(i)
Else
out(i) = ar1(i) + ar2(i)
End If
End If
Next
Return out
End Function

I hope you'll stick to your guns and choose Option 2, since Option 1
sometimes performs addition operations it doesn't have to.

[snip to end]
-> This is just a technical question <-

Don't you sometimes want to learn things just for the sake of learning?
It doesn't matter whether you will ever use the knowledge, but you are just
interested in it. In this case, I felt that the question was very
interesting because i haven't had the case not to know how to store a
piece of information for a long time. Therefore I asked here.

Armin

Absolutely. I love learning new things. I frequently don't know the
answer to questions people pose on these newsgroups. But if the
question is interesting, I'll sometimes spend some time looking into
the question. Even if I can't then answer the question, I'll usually
have learnt something new. Or I'll provide half an answer and invite
others to extend it to where I cannot - and learn from that.

The day I stop learning is the day I die.

Damien
 
A

Armin Zingler

Damien said:
I'll try to put my point more briefly than last time. Because having
1 small piece of code where I can see exactly what is happening is
easier to comprehend,

I would have my problems to explain the, at first sight, more comprehensive
code to somebody else. If my boss (although I don't have one...) looked at
it, he would probably ask me: "You are removing handlers immediatelly,
right?". Me: "Right". He: "At the end, you are removing also those handlers
that already have been removed. Maybe all handlers have already been
removed, though you are really removing all handlers twice? It doesn't hurt
but it also doesn't make sense, so change this!". I'll change the code
because I see that he is right - even if it is extra work.

I think, code must be explainable. Code that sometimes does superfluous
things is not explainable.
and be sure it is correct, than a large number
of blocks of code, through the source, which all have to be read and
understood before you can be sure that the code is doing the right
thing.

I don't have a problem in understanding the code. It is not an argument to
not write code because it will have to be understood by anybody in the
future because this is true for /any/ code. If the code has to be written,
it has to be done. (I know that you think it doesn't have to be written).
You example of adding zero being a wasted operation? How would you
write the following function:

[..]

I hope you'll stick to your guns and choose Option 2, since Option 1
sometimes performs addition operations it doesn't have to.

Good example that makes me think about it. I would choose Option 1.
The analogy fails because your Option 2 translated to my case would
have to be (pseudo code):

for each item in list
if item.handlerisattached then
item.removehandler
end if
next item

That's what I do /not/. Would be even too much for me (just as too much as
"if a isnot nothing then a = nothing").

I apologize that I won't discuss this example additionally, because I really
want to come to an end, primarily because my solution runs since...
-> This is just a technical question <-
[...]
Absolutely. I love learning new things. I frequently don't know the
answer to questions people pose on these newsgroups. But if the
question is interesting, I'll sometimes spend some time looking into
the question. Even if I can't then answer the question, I'll usually
have learnt something new. Or I'll provide half an answer and invite
others to extend it to where I cannot - and learn from that.

The day I stop learning is the day I die.

I completely agree.


Armin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top