Jump to content
Mike Torrettinni

Prefix unit local variable names

Recommended Posts

Wow, how many different styles/case types  - KebabCase wins the name  😛

 

ALL CAPS
BiCapitalized
BumpyCase
CamelCase
CanonicalStudlyCaps
Capitalization  
EmbeddedUnderscore
German case
HumpBackNotation
InfixCaps
InterCaps
KebabCase 🐑🍽️
Leet
lowerCamelCase
Mixed case
MixedCase
NerdCaps
PascalCase
Sentence case
SMALL CAPS
SNAKE_CASE
StickyCaps
StudlyCaps
Title case
UpperCamelCase
UpperCase with hyphens
WikiCase

 

 

Share this post


Link to post
8 hours ago, Mike Torrettinni said:

I don't get it... too many styles? Everybody can find a style they like 🙂

The great thing about standards is: Everybody can have his own...

  • Like 1

Share this post


Link to post
1 hour ago, dummzeuch said:

The great thing about standards is: Everybody can have his own...

And that's pretty cool. Can you imagine being forced to use the one you don't really like? But I guess you get used to anyone, eventually.

Share this post


Link to post
Guest

Mike this is staying paranoic... sorry! :classic_blink:

Share this post


Link to post

Ref the title "Prefix unit local variable names"

I avoid unit local variables as far as possible.

Those I have made in recent years are declared under the implementation part of the unit.

Any interaction with them from outside the unit uses procedures and/or functions

 

Alternatively, they are implemented as class properties on a specific type.

  • Like 2

Share this post


Link to post
6 hours ago, Lars Fosdal said:

Ref the title "Prefix unit local variable names"

I avoid unit local variables as far as possible. 

Those I have made in recent years are declared under the implementation part of the unit.

Any interaction with them from outside the unit uses procedures and/or functions

 

Alternatively, they are implemented as class properties on a specific type.

Yes, these are the local variables, defined in implementation section. I rarely use them, but still do sometimes. I used to use them a lot, just like global vars, until I learned better.

I only use them for local methods. But as soon as it makes sense I create a class and it becomes a field.

 

In those rare occasions you do specify them, do you use a prefix for them? L, l, x?

Share this post


Link to post
14 minutes ago, David Heffernan said:

Why do variable names need a prefix? 

I kind of got used to assigning prefixes to differentiate between them. Also, for this topic I refer to parameters and class field also variables.

 

You don't prefix any variables?

Share this post


Link to post
1 hour ago, Mike Torrettinni said:

I kind of got used to assigning prefixes to differentiate between them. Also, for this topic I refer to parameters and class field also variables.

 

You don't prefix any variables?

Do you do it for a reason? Surely these things should be intentional. 

Share this post


Link to post
On 12/5/2020 at 8:51 AM, Mike Torrettinni said:

Aha, yes correct, thanks! I just couldn't deal with AArgName/AParamName, these capital prefixes look so out of place - I know it's personal preference, but I'm usually the only developer, so I have a little more wiggle room with namings.

https://stackoverflow.com/questions/156767/whats-the-difference-between-an-argument-and-a-parameter

 

Share this post


Link to post
8 hours ago, Mike Torrettinni said:

Yes, these are the local variables, defined in implementation section. I rarely use them, but still do sometimes. I used to use them a lot, just like global vars, until I learned better.

I only use them for local methods. But as soon as it makes sense I create a class and it becomes a field.

 

In those rare occasions you do specify them, do you use a prefix for them? L, l, x?

No, not really.  I just use a longish descriptive name, and I keep the declaration near the routines where it is used.
F.x.

unit SoAndSo;
interface

 // lots of other declarations

procedure ClearThreadContextLog;
procedure SetThreadContextId(const aId: Integer);
function GetThreadContextId: Cardinal;
function GetThreadContextLog: TArray<String>;
procedure AddThreadContextLog(const aText: String);

implementation

// lots of other code

threadvar
  ThreadContextLog: TArray<String>;
  ThreadContextId: Integer;

procedure ClearThreadContextLog;
begin
  SetLength(ThreadContextLog, 0);
end;

procedure SetThreadContextId(const aId: Integer);
begin
  if (aId <> ThreadContextId)
   then DebugOut(Format('Setting ThreadContextId %d for ThreadId %d', [aId, GetCurrentThreadId]));
  ThreadContextId := aId;
end;

function GetThreadContextId: Cardinal;
begin
  if ThreadContextId > 0
   then Result := ThreadContextId
    else Result := GetCurrentThreadId;
end;

function GetThreadContextLog: TArray<String>;
begin
  Result := ThreadContextLog;
end;

procedure AddThreadContextLog(const aText: String);
begin
  var len := Length(ThreadContextLog);
  SetLength(ThreadContextLog, len + 1);
  ThreadContextLog[len] := Format('%d %s', [TThread.CurrentThread.ThreadID, aText]);
end;

// lots of other code

end.

 

  • Like 1

Share this post


Link to post
9 hours ago, Mike Torrettinni said:

Yes, these are the local variables

I don't think that's a very helpful way to think about it. I would reserve the term local for a variable declared inside the body of a procedure. This includes any by value parameters. 

 

There are two main aspects at play here: lifetime and visibility. 

 

A local variable, as defined above, is created when the procedure is called and destroyed when the procedure returns. This is a narrow time frame of life, worth of the term local. 

 

A variable declared in a unit is created when the program starts and destroyed when it ends. That is a far wider time frame, and the term local is, in my view, ot befitting such a thing.

  • Like 1

Share this post


Link to post
1 hour ago, David Heffernan said:

I don't think that's a very helpful way to think about it. I would reserve the term local for a variable declared inside the body of a procedure. This includes any by value parameters. 

 

There are two main aspects at play here: lifetime and visibility. 

 

A local variable, as defined above, is created when the procedure is called and destroyed when the procedure returns. This is a narrow time frame of life, worth of the term local. 

 

A variable declared in a unit is created when the program starts and destroyed when it ends. That is a far wider time frame, and the term local is, in my view, ot befitting such a thing.

Aha, thanks, it's clear now. Local unit vars and local method vars, I guess I chose x prefix for local unit vars because they are rare and is important to know the scope(visibility?), like you pointed out:

 

interface

type
  TMyClass = class
  private
    fValue: integer;
   end;

const
  cMyConst = 1;

var 
  gGlobalVar: integer;
 
implementation
 
type
  TMyLocalUnitType = integer;

var
  xLocalUnitVar: integer;
   
procedure A(aParam: integer);
var vLocalMethodVar: integer;
begin
  xLocalUnitVar := vLocalMethodVar + aParam;
end;
 

 

Share this post


Link to post
20 minutes ago, Mike Torrettinni said:

I guess I chose x prefix for local unit vars because they are rare and is important to know the scope(visibility?), like you pointed out:

I think this desire to prefix everything is not helpful. I can't see what you are gaining by doing it. And doing so introduces a risk that you will read meaning into something that the compiler does not. Which means that if you ever forget to use your chosen prefix, or use a variable defined in a unit outside your control, you might infer the wrong thing.

 

I personally use F for fields, and T for types, and nothing else. I use F for fields to avoid a clash with properties. I think the language design pretty much forces us to do that. As for types, that's more of a historical choice. I think if I didn't already have a heap of code written that way.

 

Wouldn't your time be better spent improving your code rather than agonising of which letter to use as a prefix? If you decide to prefix your names, then pick a system and stick to it. It doesn't matter which letters you choose!

  • Thanks 1

Share this post


Link to post

Or simply prefix with Local<var name> or even UnitLocal<var name>?  No need to remember any special meanings of a single letter.

Share this post


Link to post

BTW - Technically,
KebabCase 🐑🍽️

should read kebab-case 
since it typically is used for f.x. REST API URLs where each word is on a hyphen skewer, i.e. a kebab of words.
F.x. https//fictivedictionary.com/api/get-meaning-of-word 

Share this post


Link to post
6 minutes ago, Lars Fosdal said:

BTW - Technically,
KebabCase 🐑🍽️

should read kebab-case 
since it typically is used for f.x. REST API URLs where each word is on a hyphen skewer, i.e. a kebab of words.
F.x. https//fictivedictionary.com/api/get-meaning-of-word 

Wow, I never heard of kebab-case before this topic. Interesting how many new things you find out about a simple thing like naming, prefixes and styles in programming 🙂

Share this post


Link to post
9 hours ago, Darian Miller said:

It's interesting that A is used for parameter definition and not P.

 

If you go through Delphi's units, you can find very consistent inconsistency in parameter prefixes:

// parameters
(const AContext: TObject)
(const AsyncResult: TBaseAsyncResult)
(const Waiter: TWaitInfo)
(const Ref: Pointer; ATypeInfo: PTypeInfo)
(const AArray: Pointer; ATypeInfo: PTypeInfo)

same for method vars:

// no prefix
var
  Instances: TDictionary<Pointer, Integer>;
  ReferenceStack: TStack<IntPtr>;

// prefix
var
  LList: IInterfaceList;
  LControlValueObserver: IControlValueObserver;
  LTrack: IObserverTrack;
  
// mixed :-)   
var
  I: Integer;
  LPreamble: TBytes;
  BOMPresent: Boolean;  

 

 I guess I'm making too much out of all these prefixes 🙂

 

 

 

 

Share this post


Link to post
1 hour ago, David Heffernan said:

I personally use F for fields, and T for types, and nothing else.

Likewise, and I for interfaces.

 

As for the RTL/VCL inconsistencies - well any 20+ year old large code base will have those, people come and go, with different ideas, eventually adherence to the initial standard will wane or evolve. My code is no different. These days I use camelCase naming for parameters and variable, with occasional lapses into the old style.  

  • Like 1

Share this post


Link to post

T for types, I for Intfs, E for exceptions, F for fields, rarely A for arguments - when the name without prefix clashes with something but is too good to change. That's all. Other things seem to me just a useless visual noise requiring more time to type

  • Like 1

Share this post


Link to post

Now reading comments again it's good to know we all customize to some extent, to fit the purpose. As most of the time I'm the only one on the team, I can customize prefixes as I want to.

 

I think KebabCase ( kebab-case ) wins the naming war 😉

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×