My previous post on class helpers provoked a passionate response from some quarters who believed that they could be used “safely”.  More worrying was an apparent belief that their use was actually endorsed by CodeGear – tacitly or otherwise.  A rather odd view given the advice from CodeGear themselves is to not use them.

No-one actually described a safe usage scenario though and those scenarios that were described all contained immediately apparent flaws of their own.  However, I have realised that there is, if not a safe way then at least a responsible one, to create class helpers.

Using them is still not entirely safe however.

Scope: The Problem AND The Solution

The problem that using class helpers creates is caused by the fact that the compiler will only recognise one class helper for a given class at a time.  If there are multiple helpers then normal scoping rules apply, and the “nearest” helper class is the one that the compiler will accept.  Any other helpers do not exist as far as the compiler is concerned.

The potential result is that the simple act of adding a unit to your uses clause can break your code, if that code relies on some helper that is now hidden by the inclusion of that other unit.

Numerous strategies were offered if this should arise, including changing the ancestry of your class helper to extend the other helper, which obviously potentially breaks down if there are more than two helpers involved from different sources.

But the solution lies in the problem itself – scoping.

The Devil In The Implementation Detail

Class helpers are, by definition, an implementation detail of your application code – they modify a class outside of your direct control to fit the needs/desires of your code to be able to use a class in a way not supported by the class author, but they have no useful purpose as far as any declarations in your code are concerned.

There is absolutely no reason to ever expose a class helper in the interface of a unit – except of course in a unit that declares and implements a helper, obviously.

By restricting the scope of your class helpers to the tightest possible and requiring helpers to be deliberately and explicitly brought into scope you eliminate the possibility that your helper might accidentally “collide” with another helper in someone else’s code:

unit MyStreamHelper;

interface

  type
    TStreamHelper = class helper for TStream
      :
    end;

implementation

As long as everyone that uses class helpers sticks to this simple convention of placing helpers in their own unit, then the problem of “helper hiding” should be largely mitigated.  Think of it as the one time when “one class per unit” is not just a nice-to-have, but an absolute necessity.

Sadly, even then the solution is not perfect.

Certainly you can be sure that class helpers that you create will not pose any risk for anybody else, unless they deliberately use your helper unit themselves in which case one must judge that they know what they are doing.  But still, somebody carelessly exposing a class helper in the interface of a unit containing other code that might be more generally useful could still break your code.

Consider for example someone implementing a useful stream class of their own, the implementation of which uses a class helper for TStream itself to aid the implementation of their specialised stream class and which they use in other units in their library or framework which they have shared with you:


  unit SpecialisedStream;

interface

  type
    TStreamHelper = class helper for TStream
      :
    end;

    TSpecialisedStream = class(TMemoryStream)
      :
    end;

In this situation someone may wish to use TSpecialisedStream but they cannot do so without also bringing that helper class into scope, with the potential that has to break their code using their own TStream helper (after all, if class helpers are good enough for the creator of TSpecialisedStream, why not everybody else?).

So yes, there are ways to responsibly create and consume class helpers, but everyone has to stick to a safe pattern if they are to avoid creating “unsociable” code.

Unlike with, goto or untyped pointers or any other abusable language feature quoted to justify use of this abusable feature, the unique problem with class helpers remains:  that abuse risks breaking code other than your own.  Yes, you can write bad and even flat-out incorrect code using with or goto etc, but you can’t write code using these things that will fundamentally break code in an entirely separate unit, as you can with a class helper.

It also remains the case that (so far at least) with the exception of the original, highly specialised purpose for which class helpers were created (VCL / VCL.NET compatability at the framework level) there is no use to which a class helper can be put for which a safer alternative does not exist, and in many cases those alternatives are arguably “better” for reasons other than just being considerate.

The Verdict

I believe (and this is after all a personal blog, reflecting the thoughts and opinions of it’s author which I in no way seek to impose on others) the warning issued with class helpers is justified and a non-class helper approach should always be preferred where such an approach exists.

But if someone is going to insist on using class helpers in code that may be – and most especially if it is intended to be – shared with others, then they should do the community the courtesy of implementing those helpers in the above described fashion, so as to avoid the risk of breaking other people’s code.

It would seem to me to be the responsible and considerate approach.

11 thoughts on “Class Helpers – Ruling from the Appellate Court

  1. I have managed to do without class helpers so far, but I do see the potential for good use where you have to solve an extraordinary problem.

    I would probably save them for a really rainy day though, and keep them well away of any general use library, and try to limit their use to application specific problems instead of class specific problems – if you see the difference.

    I do wonder though – why they didn’t add an interface-like behaviour to the class helper – allowing the compiler to isolate the helper to a specific scope?

  2. Hi Lars – I think the problem (and I’m only speculating) is that they were designed to solve a very specific problem, not as a general purpose language feature, and that specific problem required them to be used without having to identify them as such (or at least that was desirable).

    i.e. to be able to use the “helped” class as if it actually contained the helper additions.

    For that design goal to be realised, there has to be only one helper “allowed”, otherwise you have all sorts of problems if two helpers introduce methods with the same signature.

    Or you have to devise a complicated mechanism to allow such collisions to be resolved, but if you never intended them to be used in situations where collisions could arise, why bother?

    Similarly the presumably helpers in the Win32 VCL didn’t require virtual method and override support, so whilst that is implemented and supported in the .NET compiler, the Win32 compiler supports the *syntax* but the RTL implementation isn’t actually complete – as of Delphi 2007 at least.

    http://blog.excastle.com/2007/08/29/unfinished-delphi-feature-of-the-day-virtual-class-helper-methods/

    Note CodeGear’s response to being told of this “unfinished” implementation….. “As Designed”.

    I read this as indicating that – as more or less already stated – class helpers were implemented to meet a specific, internal need. They were documented to explain their purpose, but they were never designed nor intended for general purpose use.

    Some people choose not to see it that way, I guess. 🙂

    Whether the design and/or implementation will ever be finished/revised to a point where they may be respectably considered a “first class” language feature for general use is still open to question I suppose.

  3. For me, the mere facts that

    1) There is no compiler warning emitted when the compiler encounters a CLASS HELPER definition

    2) The ability to inherit from a previous CLASS HELPER exists

    show me that

    1) Borland/CodeGear didn’t really mean the warning at the time of implementation – at least not at the time of designing the feature

    2) The implementors have at least thought “outside the box” in that two class helpers for a given class CAN be active AT THE SAME TIME. Therefore it was not solely intended for the use you describe – otherwise why go to the extended trouble of implementing CLASS HELPER inheritance?

    Also, class helpers doesn’t create problems that doesn’t already exists with inheritance. You can have name conflicts and signature conflicts in a classical OO hiearachy just as you can in a CLASS HELPER hiearachy.

    CLASS HELPERs can also call parent CLASS HELPERs using the INHERITED syntax, such as in this nonsense-example:

    ——————————————————————————–

    UNIT Helper1;

    TYPE
    TClassHelper1 = CLASS HELPER FOR TComboBox
    FUNCTION Add(CONST STR : STRING ; OBJ : TObject = NIL) : INTEGER;
    END;

    { TClassHelper1 }

    FUNCTION TClassHelper1.Add(CONST STR : STRING ; OBJ : TObject) : INTEGER;
    BEGIN
    Result:=Items.AddObject(STR,OBJ)
    END;

    ——————————————————————————–

    UNIT Helper2;

    TYPE
    TClassHelper2 = CLASS HELPER(TClassHelper1) FOR TComboBox
    FUNCTION Add(CONST STR : STRING ; OBJ : TObject = NIL) : INTEGER;
    FUNCTION UncheckedAdd(CONST STR : STRING ; OBJ : TObject = NIL) : INTEGER;
    END;

    { TClassHelper2 }

    FUNCTION TClassHelper2.Add(CONST STR : STRING ; OBJ : TObject) : INTEGER;
    BEGIN
    IF STR=” THEN Result:=-1 ELSE Result:=UncheckedAdd(STR,OBJ)
    END;

    FUNCTION TClassHelper2.UncheckedAdd(CONST STR : STRING ; OBJ : TObject) : INTEGER;
    BEGIN
    Result:=INHERITED Add(STR,OBJ)
    END;

    ——————————————————————————–

    UNIT Main;

    USES Helper1,Helper2;

    procedure TForm2.FormCreate(Sender: TObject);
    begin
    ComboBox1.Add(”);
    ComboBox1.Add(‘1234’)
    end;

    ——————————————————————————–

    which also demonstrates the ability to “Rename” a parent’s class helper method in descendant class helpers so as to provide access to both from programs that use both ClassHelper1 and ClassHelper2.

  4. @Keld

    So let me see, depending on which class helper is “visible”, then this line of code:

    ComboBox.Add(”);

    could do two entirely different things? And simply changing the order of your uses list could change that behaviour?

    And you are offering this to support an argument in FAVOUR of class helpers?

    Hmmmmmmm.

    😉

    As for the substance of your observations, I shall address the “inheritance” issue first then come back to the documentation issue.

    Yes, name collisions occur with inheritance, but there are legitimate and reliable mechanisms for dealing with those.

    Most typically if you have a method in a base class that has the same name in a derived class it is normally because that method is polymorphic – it will be virtual in the base class and overridden in the derived class.

    I would say “Try that with a class helper” but I wouldn’t want to waste your time, so instead simply read this:

    http://blog.excastle.com/2007/08/29/unfinished-delphi-feature-of-the-day-virtual-class-helper-methods/

    Class helpers do not support “proper OO” as far as virtual methods are concerned. Or perhaps more accurately, the Win32 compiler and RTL do not support it beyond allowing the syntax (*remember this, it will be crucial in my “closing arguments”. lol).

    Can you “reintroduce” with a class helper?

    Even if you can, you do not get the same behaviour that you would get with a regular class since you cannot qualify using a class helper name so there is no way to get at the hidden method as you can with an OO, but non-polymorphic, class – your derived helper would permanently and unavoidably deny access to any inherited method with the same signature (overloads will – I should say “might” – allow methods that differ in parameters alone to propogate into the derived helper).

    And worse – as your own example demonstrated quite nicely – you risk having code that could inadvertently change behaviour in response to a simple change the order of units in a uses list.

    The compiler won’t warn you if you derive Helper2 from Helper1 but then have Helper1 (accidentally or otherwise) HIDE Helper2.

    Far from going to “extended trouble to support helper inheritance” it is clearly not (fully) supported at all.

    As far as virtual method support is concerned, this – as I understand it – is a limitation of the Win32 implementation. Virtual methods on class helpers ARE supported in Delphi.NET.

    “Ah see! They just haven’t got around to finishing the Win32 implementation yet.” (speculated response)

    You might think that – if it hadn’t already been indicated that class helpers are working according “As Designed” in Win32.

    This makes perfect sense if you remember that they were designed for CODEGEAR to use “internally” so only had to suit the purposes to which CodeGear intended to put them, and that was to address a cross-platform issue between VCL and VCL.NET code. If there were different needs in the Win32 compiler vs the .NET compiler at that time, that would explain the differences in the implementation.

    As clarified by other commenters, class helpers were introduced first in Delphi.NET (Delphi 8) – if I understand correctly, they are used in D2007 primarily to avoid a breaking change between D2006 and D2007 – I doubt there will be any class helpers in the Delphi 2009 VCL source as this will be a breaking release so such temporary fixes are not needed.

    Again, if I understand correctly, the VCL.NET is a different matter of course – in that case class helpers are a permanent fixture required to address that VCL/VCL.NET issue (the details of which I don’t have to hand but I’m sure can be found quite easily if you are interested)

    “But they are documented, so we are clearly supposed to use them” (paraphrase)

    1) this ignores the fact that the same documentation being held up as validation their use contains a warning specifically suggesting that you do not.

    Do we trust the documentation as an authority, or dismiss it as irrelevant? You seem to want to do both.

    2) if the VCL source were not published there would have been no need to even mention class helpers, let alone document them. But since class helpers were inevitably going to be “on view” they had to be documented. Even without documentation someone would have found them in the VCL source, figured out how to use them and then excitedly told everyone the secret they had discovered.

    Who would have heeded any warnings then?

    People would have felt that Borland/CodeGear were just trying to keep some candy treats for themselves.

    “They could yet implement them fully?”

    Indeed they could, but why should they?

    CodeGear have – from the outset – told us that we should not be using them.

    They might just as easily decide that they were a bad idea – or at least a poor implementation of a necessary idea – and choose to fundamentally change them or even remove them from the language completely and replace them with something else.

    I’m not saying they will (as I said before, I suspect they will remain in some form or another in connection to support a LINQ implementation), but if they did – or if they were changed in a way incompatible with current usage – no-one could reasonably complain that they weren’t warned.

    Let’s review the facts:

    1) the documentation suggests, quite directly and really quite strongly, that class helpers are something that should not be used

    2) the apparent OO features and seeming OO syntax of class helpers clearly does not follow the OO implementation found in the rest of Delphi

    3) even when used “responsibly” in an area of code, irresponsible use in another area (let us call it the “problem area”) can lead to side effects – namely compilation failures – outside of the problem area itself. This is not typically a characteristic of a “first class” language feature.

    Finally, and most damning of all:

    4) the Win32 compiler supports a syntax that produces code for which runtime support is not provided (resulting in access violations)

    5) the lack of runtime support is not considered a bug – it is “As Designed”

    Yet despite all this, you believe that I am wrong to suggest that it would be sensible, at the very least, to heed that warning at #1, above.

    The case for the prosecution rests.

    🙂

    (But even after all that, I am not going to “send the boys round” if you wish to dance with this particular devil, by the pale moonlight or otherwise.

    But I myself shall sit this one out and wait for the Gentlemen’s Excuse Me)

    🙂

  5. You wrote:

    So let me see, depending on which class helper is “visible”, then this line of code:

    ComboBox.Add(”);

    could do two entirely different things? And simply changing the order of your uses list could change that behaviour?

    My reply:

    Yes – but so could any OO hieararchy using inheritance – there’s no difference there…

    You wrote:

    Yes, name collisions occur with inheritance, but there are legitimate and reliable mechanisms for dealing with those.

    My reply:

    So are there for Class Helpers :).

    You wrote:

    Most typically if you have a method in a base class that has the same name in a derived class it is normally because that method is polymorphic – it will be virtual in the base class and overridden in the derived class.

    My reply:

    Yes – that’s the “typical” way, but even with inheritance, you can hit problems if you have written a descendant class for which the parent class suddenly is changed (which in essense if what you do with class helpers – modify the parent class, but without impacting code that aren’t using your extensions).

    You wrote:

    I would say “Try that with a class helper” but I wouldn’t want to waste your time, so instead simply read this:

    http://blog.excastle.com/2007/08/29/unfinished-delphi-feature-of-the-day-virtual-class-helper-methods/

    My reply:

    I *have* read it, and have yet to need virtual methods in class helpers, since the way I use them mainly is to OO’ize old-style procedural-calls.

    Like I said yesterday, I don’t expect to use Class Helpers to implement advanced routines, but for the simple extensions I am using them (like my TStream example yesterday), I find them extremely useful.

    You wrote:

    Can you “reintroduce” with a class helper?

    Even if you can, you do not get the same behaviour that you would get with a regular class since you cannot qualify using a class helper name so there is no way to get at the hidden method as you can with an OO, but non-polymorphic, class – your derived helper would permanently and unavoidably deny access to any inherited method with the same signature (overloads will – I should say “might” – allow methods that differ in parameters alone to propogate into the derived helper).

    My reply:

    If I f.ex. introduce a method with identical sugnature in a class helper for TComboBox, I can call the original TComboBox method in one of two ways:

    1) Introduce a wrapper call in my class helper (as illustrated in my example today). By marking it INLINE, I can even eliminate any code overhead.

    2) If the call really originates in a parent to TComboBox, I can cast my variable to that parent (TCustomComboBox) in order to “escape” the class helper.

    You wrote:

    And worse – as your own example demonstrated quite nicely – you risk having code that could inadvertently change behaviour in response to a simple change the order of units in a uses list.

    My reply:

    What’s the difference in this and any other naming conflict you can encounter by having two libraries both defining a class TExtDialog, f.ex.? You could run into the exact same problem there, but I don’t see you objecting to normal class inheritance or ordinary OO programming :).

    You wrote:

    This makes perfect sense if you remember that they were designed for CODEGEAR to use “internally” so only had to suit the purposes to which CodeGear intended to put them, and that was to address a cross-platform issue between VCL and VCL.NET code.

    My reply:

    But then, why did CodeGear

    1) Allow the syntax in Delphi Win32?

    2) Allow Class Helper inheritance

    3) Not make the compiler issue a warning, like it does with so many other things (deprecated, platform specific, hides earlier implementation, etc. etc.)?

    You wrote:

    if I understand correctly, they are used in D2007 primarily to avoid a breaking change between D2006 and D2007 – I doubt there will be any class helpers in the Delphi 2009 VCL source as this will be a breaking release so such temporary fixes are not needed.

    My reply:

    But then:

    1) Why was Class Helpers (buggy) supported even in Delphi 2005?

    2) Why was Class Helpers (fixed) supported even in Delphi 2006?

    In other words – Class Helpers were NOT implemented in Delphi 2007 for Win32 to allow this non-breaking release. It’s the other way around – the non-breaking release TOOK ADVANTAGE of already existing Class Helper support in order to make the release non-breaking.

    You wrote:

    “But they are documented, so we are clearly supposed to use them” (paraphrase)

    1) this ignores the fact that the same documentation being held up as validation their use contains a warning specifically suggesting that you do not.

    Do we trust the documentation as an authority, or dismiss it as irrelevant? You seem to want to do both.

    My reply:

    I can’t remember I have ever seen that warning. I just tried it on my Delphi 2007, and there’s a warning there, but I can’t recall ever seeing that warning in neither Delphi 2005 nor Delphi 2006. So to my mind, the warning is an after-rationalization that they have come up with post-haste to try to put the cat back in the bag. Unfortunately, they are too late – the cat’s already out of the bag, all the way back from Delphi 2005 (where I started using them).

    You wrote:

    2) if the VCL source were not published there would have been no need to even mention class helpers, let alone document them. But since class helpers were inevitably going to be “on view” they had to be documented. Even without documentation someone would have found them in the VCL source, figured out how to use them and then excitedly told everyone the secret they had discovered.

    My reply:

    But why document them FULLY. Why not just – from the very onset (Delphi 2005) – state in the help file:

    Class Helpers are an internal feature used by CodeGear to allow interface between .NET and VCL and is not to be used by other people.

    and nothing more? And why – in the first place – port it to Win32, if it wasn’t that we were supposed to use them (and no – it wasn’t ported to Win32 to allow the non-breaking release of Delphi 2007, since they were there all the way back in Delphi 2005).

    You wrote:

    “They could yet implement them fully?”

    Indeed they could, but why should they?

    My reply:

    Because it’s a NICE feature that allows me (and others) to implement small snippets of code into the VCL hieararchy without the need to re-compile it (and thus break compatibility with old code).

    Yes – there are some problems and pitfalls with the specific implementation, but that could probably be solved in various ways – least of all are compiler warnings, where a class helper introduces methods that override or conflicts with existing names, and/or warnings where there’s a possibility for ambiguity in the use of a class helper (no need to warn about TStreamHelper.WriteInteger unless there’s a descendant or parent class that also has a WriteInteger with the same signature).

    One could even allow these warnings to be promoted to errors on a project-by-project basis to force the programmers to resolve any ambiguity before allowing the program to compile.

    You wrote:

    CodeGear have – from the outset – told us that we should not be using them.

    My reply:

    Like I said, that’s a statement I don’t believe is true. I’ll try to see if I can find my old, dusty Delphi 2005 compiler and see if the warning is there in the help file all the way back then, but I don’t remember ever reading a warning about it in any help file until I today looked it up in Delphi 2007.

    You wrote:

    1) the documentation suggests, quite directly and really quite strongly, that class helpers are something that should not be used

    My reply:

    Yes – at least in Delphi 2007. Whether or not it was there in the Delphi 2005 documentation remains to be seen…

    You wrote:

    Yet despite all this, you believe that I am wrong to suggest that it would be sensible, at the very least, to heed that warning at #1, above.

    My reply:

    If by “heed that warning” you mean “don’t EVER use class helpers”, then, yes, I think you are wrong. Like any tool, class helpers can be mis-used, but if one is aware of the pitfalls, I don’t see anything wrong with using them.

    If they are used (as I do) to make code more readable and maintainable, then I am all for it. Use the tools that you have available, but use them responsibly…

    Should cars be illegal because they can kill people? 🙂 How about a power drill? ;).

  6. If you do a search on the Delphi 2007 VCL (excluding the VCL.NET) source code you’ll find only 2 instances in which class helpers are used. I’m assuming that since Delphi 2009 will be a breaking release both of these instances will disappear with the additional methods being added into the respective classes proper.

    Since CodeGear makes such limited use of the class helper feature the chance of running into side effects resulting from duplicate class helpers are extremely minimal.

    If you’re using class helpers, which I do, the burden is on you to search the VCL and any third party code to make sure that you aren’t conflicting with their potential usage of class helpers. Chances are though that you won’t be, but you must check!!!

  7. “So let me see, depending on which class helper is “visible”, then this line of code:

    ComboBox.Add(”);

    could do two entirely different things? And simply changing the order of your uses list could change that behaviour?

    And you are offering this to support an argument in FAVOUR of class helpers?

    Hmmmmmmm.”

    I’m not trying to be pedantic or obtuse here, but how is that different than normal Pascal scoping rules? Suppose Unit A and Unit B both have a global function Foo: Integer; Depending on the order that those units appear, either the Unit A version or the Unit B version would be called. The same thing happens with types or all interfaced symbols. So Units A & B both define a type X, and depending upon the order of usage, code would refer to one or the other. You can even “override” the meaning of “Integer” by defining your own symbol.

    I guess the one difference would be that you can always fully qualify the symbol with the unit name to get around this “problem.” However, this “problem” has long been considered a language feature.

    ‘5) the lack of runtime support is not considered a bug – it is “As Designed”’

    As you assert, this feature was implemented to the point that it served CodeGear’s purpose. As of right now, in Delphi/Win32, non-virtual methods are the only “safe” kinds of methods to add. Delphi/.NET got a more complete implementation because we needed a more complete implementation for .NET.

    Allen.

  8. @Allen:

    Thank you for joining the discussion. It’s always nice to get some information straight “from the horse’s mouth” (not that you are a horse :)).

    A couple of questions I have in this discussion, could possibly be clarified by you:

    1) Why was the CLASS HELPER ported to Delphi 2005 Win32 in the first place? At that time, CodeGear had no need for it (at least no need that I am aware of).

    2) Why was CLASS HELPER inheritance allowed? As far as I know, CodeGear doesn’t use it, so if CLASS HELPERs were *only* intented for use by CodeGear, why implement a feature that CodeGear doesn’t need?

    3) Why – if CodeGear wants to discourage its use – doesn’t the compiler issue a warning when encountering a CLASS HELPER definition?

    4) Was the warning that is now present in Delphi 2007 Help already present in the Delphi 2005 Help?

    And, finally, a question that you probably can’t/won’t answer :):

    Are CodeGear planning to extend the CLASS HELPER support in Win32 to the point where the pitfalls we have discussed here will be addressed, or are CodeGear playing with the idea to remove them altogether from the Win32 compiler?

  9. Oh, and one question to you, Jolyon:

    Why is my comment from 02:00am “awaiting moderation” when my comments at 04:28am and this one aren’t?

  10. @Allen

    I think you identified the difference yourself. In any other case you can qualify to make the desired scope explicit – something that isn’t possible with class helpers (without adjusting unit order in the uses list).

    The other difference is that whilst it may be possible to accidentally run into this situation even without class helpers, here was a suggestion that we deliberately *create* a possible breaking change as a way to work around a different possible breaking change. The methods were specifically devised to have different behaviours but identical signatures to give the illusion of a method from the base helper propogating into the derived helper but with different behaviour – simulating a virtual method in a way.

    Yes, such collisions can arise in other cases, but is less likely – certainly not impossible, but definitely less likely than a *deliberately* crafted situation. imho.

    @Keld

    There IS a difference between scope affecting helpers and scope effects in OO hierarchies generally – see Allen’s comment and my reply to him, above .

    Your questions about why CodeGear did not implement warnings etc can of course only be answered by CodeGear.

    Although one might speculate that there is little point in implementing compiler support for warnings for a feature that people shouldn’t be using if they are paying attention to the warnings in the documentation…. maybe?

    Even if the compiler were warning you, I suspect you would just be suppressing/ignoring those warnings anyway?

    😉

    As for what happened with your comment, I’m not entirely sure.

    Did you post comments from different machines or using a different email address? Ordinarily once a comment has been approved then the system seems to accept all comments from that author without requiring separate approval for each one, but I haven’t looked into how non-registered visitor comments are associated with a particular author (by email? IP address). Mostly WordPress “just works” well enough for me – I’m by no means an expert on it though.

    On the other hand it’s possible I might have just missed it – it was a late night after a long (and frankly tedious) day at Tech Ed and I had two browsers open on my blog doing different things simultaneously.

    It certainly wasn’t deliberate.

    In future however I think I would ask that if you have detailed discussion points, I would prefer you to email them. If nothing else having to maintain the thread of a conversation in a comment stream is awkward.

    If an email discussion leads to useful follow-up content, I will post it separately, even if it involves my changing my mind on some subject. In fact, even more assuredly so in that case.

    That is not going to happen in this case though.

    🙂

  11. @Lachlan

    Yes, the chances of running into problems with a /CodeGear/ helper are minimal.

    But the chances of running into a helper for a CodeGear class in someone else’s code will increase if more and more people start to feel comfortable using them.

    Keld is not the only person to have struck on the idea of a TStream helper, for example.

    People obviously won’t create helpers for their *own* classes – they can just modify their own classes (the need that CodeGear had was pretty unique).

    But the VCL is the single most significant, if not largest, common codebase that all Delphi developers have in common and is the codebase that helpers are most likely to be created for.

    If everyone starts helping themselves to classes in the VCL, their ability to share code with other Delphi developers is subject to an unnecessary and avoidable risk.

    I am increasingly convinced that the name is the biggest problem with class helpers. Anything that “helps” has got to be good, right?

    If they had been called “class patchers” or “class customizations” I don’t think people would be in nearly so much of a hurry to expose themselves to them.

    🙂

    But if you never share code with/from anyone else and never will, no worries.

Comments are closed.