views:

220

answers:

1

Does the extended RTTI in Delphi 2010 offer a way to list defined Class and Record Helpers at run time?

As far as I know Delphi does not show a hint or warning when more than one class helper is defined for a class, class helper detection might be a helpful routine in 'quality assurance'.

p.s. of course I know I should never ever use third party components or libraries without source code, which would make it easy to grep class helpers.

+6  A: 

Since class helpers only apply to a class based on what helper is "closest" in scope, a class simply cannot know that a helper exists. For example, you can create a class helper in your unit to "help" a class from another unit for which you have no source. The class in the other unit has no clue about any helpers. If it did have this knowledge, then it would have to be recompiled to take this into account... which leads to the next issue;

Consider this: You could have a class declared in one common unit that is used by many other units throughout your application. In each of those units you declare a new helper for this common class with different methods and "helper" functions. Since each unit knows nothing about the other units that also declare their own helper, there is, by design, no way to somehow coalesce all the helpers. Now consider that this common unit now lives across a pre-compiled package boundary.

Class helpers are seductive little heathens. They promise fame and fortune, but too often they rain down death and destruction... long after you've given yourself over to their wiles.

For this reason, their introduction into the language solved very specific problems, namely the ability to "appear" to introduce functionality into an existing framework. As long as you adhere the "one helper only" rule, and do not stray from that path, you may emerge relatively unscathed. Regardless, you will need to have the combined intestinal fortitude of Beowulf, Leonidas (of Sparta), and Frodo Baggins to navigate through these waters.

Given that, here on the RAD Studio team, we are loath to ever use a class helper where it can be avoided. And when we do use them, an appropriate phalanx is formed before we even begin...

There be dragons here...

Allen Bauer
François
Ya know, I've always sorta wondered why it was implemented that way. Why do class helpers have to be so scary that even the Delphi team is afraid of them? Why are we restricted to using only one on a class at any given time?
Mason Wheeler
It mainly has to do with the scoping rules of the language. We were not about to break down those rules, as that would have created an even larger chasm of confusion.They're not scary, if and only if, you really, truly understand the rules and the pitfalls thereof. The problems comes in when you are using helpers as an integral part of your framework's API. Then you run the real risk of wrestling with dueling helpers.
Allen Bauer
@Mason: Because they were never intended as a general purpose extension to the language!!! They were introduced to solve a very specific problem in the VCL. The documentation has always warned people NOT to use them for more general purposes (and there are alternative techniques that achieve the same AND MORE which are imho better (more opaque) and have always worked in all versions of Delphi!)
Deltics
@Deltics: No, there are a few things that only class helpers can do, such as add a method to a base class (and all its descendants) that's able to use that class's protected members. There's no other language feature that can do this AFAIK. Also, if it were implemented properly, it would be a lot more useful. Take a look at LINQ to see the sorts of things that you can accomplish with properly-done class extensions.
Mason Wheeler
What exactly would "implemented properly" mean? That is a very vague statement. "Make them like C# extension methods" isn't an answer. And, remember, that C# extension methods also have similar scoping rules, and can also get you into just as much trouble. Extension methods are not the only thing that makes LINQ, LINQ. It is the heavy use of type inferencing and and a fluent style API that does that.
Allen Bauer
@Mason: You can implement a psuedo class extender to do that. The *only* difference is that to use that pseudo extender you have to explicitly cast to it. But I see that as a benefit for code maintenance because it makes it entirely obvious that what you are doing is not supported directly by the instance but is using a "trick". With a class "helper" the fact that the method is not directly supported by the instance is obfuscated and with potentially multiple class helpers in existence but only one helper in scope, changing scope can break code in a way that explicit pseudo casts cannot.
Deltics
@Mason 2: There is nothing that a class helper can do that alternative techniques cannot do, save for the fact that the "class helper" does it in a less opaque, more transparent, more fragile way and are therefore more dangerous. Introducing class helper "A" - perhaps unknowingly/inadvertently - can *break* [fail compilation of] previously valid code already using class helper "B" or damage it [if both helpers provide methods with the same name(s) but doing slightly different things].
Deltics