Original in Russian: http://18delphi.blogspot.ru/2013/11/supports.html
Thoughts about - (in Russian)
For some reason, MANY people (if not anybody) regard my posts as “a seeking for absolute” or “an attempt to be a guru” and create “a cow in a vacuum”.
It is not AT ALL the case.
I do not seek for absolute and I am not trying to get a silver bullet or create “a spherical cow in a vacuum”.
Quite the reverse!
I am a PRACTICAL MAN,
with no HIGHER EDUCATION.
I am not trying to find “a universal recipe”.
Quite the opposite. Personally I think there is NO UNIVERSAL recipe.
I only describe what I faced IN PRACTICE.
I do not “pull” ANYBODY ANYWHERE. I do not force ANYTHING upon ANYBODY.
I’ve written a TRIVIAL thing about Supports - "can be done in this way", and "can also be done in this way".
Obviously, the solutions are not EQUIVALENTS.
One solution is MORE GENERAL and the other one is MORE EFFECTIVE.
I base on my PRACTICE, nothing more.
I hold DEEP PREJUDICE against Supports and QueryInterface.
I really do.
I try not to use them “all other things being equal”. For example, using the “technique” described at a link above. Generally speaking, there are lots of techniques for DIFFERENT “special cases”.
I am motivated by my PRACTICE, nothing more.
It is just that once interfaces appeared, everybody understood “WOW! Interfaces are cool”.
Everybody was “ENTHUSIASTIC” about using the interfaces in general and Supports in particular.
I was not a “black sheep”.
I had to pay for it a lot, with my time spent on debugging and work with profiler.
You see, time is the most VALUABLE thing. (People “closer to 40” would probably understand me.)
I’ll try to give an example.
In the era of the RAGE for interfaces (we were young and had “three sheets in the wind”) – I, BY MY OWN, created the following IDIOTIC structure:
TmyObject = class(TPersistent) f_Owner : TPersistent; function GetOwner: TPersistent; override; begin Result := f_Owner; end; procedure SetOwner(anOwner : TPersistent); begin f_Owner := anOwner; end; function QueryInterface(anIntf : TGUID; out Obj): hResult; begin if Self.GetInterface(anItf, Obj) then Result := S_OK else if Supports(f_Owner, anIntf, Obj) then Result := S_OK else Result := E_NoInterface; end; end;//TmyObject
What is this about?
Objects TEND TO have owners.
If an interface is called from an object, first we try to get an interface from it.
If we FAIL, we try to get the interface from the OWNER.
Let the recursion go on.
The code is sure IDIOTIC. I UNDERSTAND it NOW unlike 15 or so years ago.
If you call it idiotic at a glance – my hat’s off. Kudos to you. Stop to read an “old fool”...
However, “some time ago” it seemed to me this code is “not too bad at all”.
It seemed to me it “accomplished a mission”.
If we do not get the interface from the object, we try to get it from its owner – quite “logical”...
In most cases it “WORKS”.
Let’s slip the cases when using this approach caused “parasite interfaces”. Such cases were RARE and there were SPECIAL “crutches” and “grinds” for them...
But, GENERALLY, ALL worked PROPERLY.
LATER ON, I spent long HOURS under debugger and profiler seeking to find the answer to “why it is SO slow”.
IT HAPPENED TO BE VERY SIMPLE – first of all, GetOwner – NOT THE FASTEST method (dynamic, but not virtual, if I am not mistaken), well, hell with it...
Objects NESTING WAS (and is) deep ENOUGH.
Another factor came in the picture.
We called for the interface from the object. It does not support the interface. So we ask from the parent and the next parent. They do NOT SUPPORT is, TOO. Same is through the ENTIRE CHAIN. As a result, we PASSED THROUGH THE ENTIRE CHAIN, performed lots of computation and got nil and E-NoInterface (which was to be expected).
As a matter of fact, there is a vast of Supports and QueryInterface’s of many sorts for VARIOUS PURPOSES.
ANY of these performs COMPUTING which is “actually” NOT NECESSARY.
As a result, profiler and debugger showed it to me and I finally GOT RID of this CHAOS.
It took “much valuable time” that I could spend on something else.
May be, I am a FOOL or an IDIOT to have created such a TERRIBLE CHAOS. May be you are more CLEVER than me and you’re lucky.
However, I have seen such TERRIBLE CHAOS of other developers “under different pretexts”.
So I am not so special.
If you are more clever than our “gang” of FOOLS and IDIOTS, then you are lucky :-)
Personally I “hold prejudice against” Supports and QueryInterface.
Should you need MORE examples, I’ll give them to you, not only from my personal experience.
I do not “pull” anybody anywhere, do NOT PREACH and don’t “try to help”...
I only want to SHOW MY OWN MISTAKES to prevent OTHER people from making them.
“Wise men learn by other’s faults, fools by their own”...
Though it is not true for Russians...
P.S. It is time to rename my blog to “Old fool’s notes”... It would be more close to the idea... People would treat me with “indulgence”… What you can expect of a poor man...