Wednesday, December 20, 2023

Delphi Tip of the Day: Use Your Own Unique Prefix for Types and Constants

I'm in the process of converting an old Delphi 5 VCL application to Delphi 11 FMX. Yeah, I have Delphi 12 but I'm waiting for the first bug release before I start using it. Well, this morning I learned a valuable lesson. A lesson which stopped me dead in my tracks. 

There's nothing stopping you from creating an already existing type!

I was making some refactoring changes to my code. I didn't realize I was about to make a huge mistake. I went plodding ahead pleased with the progress I was making and admiring the beautiful, refactored code I was creating. When boom... I renamed a type that stepped on a type already inside the System.UITypes unit.

There's nothing to stop you from creating an already existing type. Of course I didn't use the preview changes function. I just hit go!

I had defined my own enumerated type called TMyImageIndex. I decided to just simply call it TImageIndex. So, that's what I did using Refactor > Rename type TMyImageIndex CTRL+SHIFT+E

I knew I messed up when I saw way too much code show up in the results panel.

How dare Embarcadero define a type called TImageIndex

WTF.  If it already existed the IDE should have prevented me or at least warned me. How dare Embarcadero define a type called TImageIndex.

type
//TImageIndex = (iiAdd = 2, iiUpdate = 3);)
  TZwImageIndex = (iiAdd = 2, iiUpdate = 3);)

const
  ZW_WIDTH_COLUMN_GLYPH  = 20;
  ZW_WIDTH_COLUMN_DATE   = 90;
  ZW_WIDTH_COLUMN_AMOUNT = 74

It took me about 30 minutes, but I was able to get the original code back in place, And working.

So going forward I have created my own unique prefix of  TZw (Zw = ZilchWorks). Going forward I will preface all Types and Constants.

Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com

8 comments:

  1. Hi Michael,

    Those mistakes can always happen. I am, as you are, not a professional programmer, but have been using Delphi since version 1. For years now I have been using AJC Active Backup (https://www.ajcsoft.com/active-backup.htm) to safeguard me from all kinds of mistakes. It is not expensive and not difficult to use. Version control system like Git... well, I found them to difficult to use. And like you, I am the only one coding. There is a 30 day trial. It works. Only for comparing the differences I use Beyond Compare rather than the build-in tool in AJC Active Backup. For the record: I am just a happy user of the product. Nothing else.

    Best regards,
    Fons

    ReplyDelete
  2. The prevailing sentiment among many [most?] gurus (in any computer language) is the notion that you don't need comments in a program if your names are well chosen. In my view this is simply wrong on many levels. Your prefixing, however, gets it right and this is a case that clearly identifies a name as belonging to a special class of names that is easily recognizable as unique to the system/developer. I have yet to see a really good discussion of naming and commenting that is really useful for the average developer. (Maybe something by Uncle Bob Martin, but I haven't yet read all of his books.)

    ReplyDelete
    Replies
    1. Thank you Milan. I've only read small portions of two of Uncle Bob's books. The one book that I really find helpful is William Meyer's "Delphi Legacy Projects. He does a great job pointing out the good, the bad, and yes the ugly. Highly recommend this one. https://www.amazon.com/Delphi-Legacy-Projects-Strategies-Survival/dp/B0B2TY6ZZ4

      Delete
    2. Thanks. That is a good book and I have used portions of it as a reference. I haven't had a chance to digest most of it however. I'll take a closer look—soon! :-)

      Delete
    3. The problem with comments is that they are usually not as well maintained as the code, so over time they get stale and in the worst case are wrong and misleading.

      Delete
    4. That's a great point Thomas. Thank you.

      Delete
  3. While it is true that comments are often not well-maintained, the same can be said of the code. The actual "problem" is neither the code nor the comments, but the developer. When code remains poorly commented (or not commented at all) we tend to make excuses for the omission. When the code itself is poorly maintained we call that "technical debt." In all cases, the problem is the developer who produces sub-standard product, or the manager who fails to provide ways to improve the entire package. I view most of this as a problem involving the misuse of the so-called "agile" methodology, that too frequently emphasizes only "burn-down" and "velocity" as a measure of any kind of success. But those are topics for another discussion.

    ReplyDelete
  4. This is not just a problem for types, but also constants, global variables, functions, classes etc. with same names in two or more units.

    In case of a name clash, which definition is used in a unit depends on the order of units in the uses statements. The unit listed LAST has the highest priority.

    To avoid name clashes I prefix interfaced types and other definitions with the unit name. This also makes it obvious where it is defined. With your example it would be as if the unit was named Zw.

    ReplyDelete