I have posted before about new language features introduced in a way that does not adhere to the (admittedly quite notional) “Spirit of Delphi”. It’s time for another one, this time inspired by a post by Paul Klink of the ADUG.
In his post, Paul makes the following observation:
The obvious downside is that class/type declarations are larger and harder to read. With practice, I have gotten better at reading types with nested types but you can only go so far.
I think nested types would be more livable with if we were able to separate the physical organisation in the source code from the logical organisation of the types. Isn’t that what software development languages in particular are supposed to help us do ? To abstract the physical from the logical ?
Indeed, Pascal already contained the exact construct we needed to achieve this: the forward declaration:
type TDocument = class type TParagraph = class; // forward decl of TDocument.TParagraph .. end; TDocument.TParagraph = class .. end;
The fact that a logically nested type is required also to be physically nested shows what appears to me to be a shocking (but sadly all too common) lack of imagination or forward thinking on the part of the developers working on the language spec/implementation.
i.e. It should have been obvious that creating nested types in anything other than trivial cases would quickly lead to convoluted and hard to read source and taken steps to ensure that the “Spirit of Pascal” was preserved in and by their endeavours.
It is that lack of awareness of the heritage and intents of the language they are working with/on in the language feature arms race that is most worrying to me and is the main reason I steer well clear of almost all language features introduced to Delphi in recent years as they almost all suffer from the same problem: Whatever good they do, they also make code harder for mere humans to read and understand.
(another huge problem is the fact that if you are creating code intended to be shared with a broad group, then by using new language features you cut off users of older versions of the compiler for which they may have good reason to be stuck with, no matter how much we might think they should upgrade and could benefit from doing so. But I digress…)
It is far more important to me that a human be able to read and understand code productively than it is for a compiler, because when a compiler doesn’t understand it will tell me in seconds by refusing to compile (or producing strange results), allowing me to identify and correct where I had made the mistake that lead to the compiler’s confusion.
A human on the other hand can go for extended periods working on the basis of flawed interpretations, blissfully unaware of their unenlightened state or, perhaps more commonly, will take an extended period to gain the level of understanding needed to proceed beyond the point of simply acquiring that understanding and doing something useful with the knowledge.
Sadly most language features these days seem designed for easier machine parsing than human.
And it’s not even as if this has lead to decent IDE support for these language features to justify the bias toward ease of machine reading … more often than not, using them not only makes code harder to read but also breaks a great deal of the supposed productivity aids in the IDE, as Martin Franke observes in the comments on Paul’s post.
Interesting proposal, that said, the forward may not even need to be nested, this could work too:
type TDocument = class; type TDocument.TParagraph = class; type TDocument = class ... end; type TDocument.TParagraph = class ... end;
I see your point, but as always I think the most desirable path lies somewhere between the two extremes of entirely abstracted and utterly literal. π
One problem I see in your example is that forward declarations must eventually be fully defined within the same “type” block – the numerous “type” statements aren’t just redundant, they’re problematic (having said that, I don’t know if contiguous type statements may be treated as a single block; perhaps your example is OK after all – I shall try it later). π
Only one “type ” was mean to be there, the others were copy-pasta!
Ah – got you now. Those pesky “type”s, breeding like rabbits! Well, actually, since copy/paste was involved, more like cloned sheep. π
Too much copy-paste, hehe, feel free to ignore the redundant “type ” π
I think the feature Delphi language really miss is forward declaration of advanced records, especially because overloaded operators are not available for classes.
Good IDE support helps enormously, competing products have opened my eyes to this.
IDE support is preferable to those programmer-assisting language features that bulk up the executable.