Powershell class: property vs argument naming

Viewed 96

In this old Microsoft doc Richard Siddaway states

I use variable names that are reminiscent of the property name. These variables are arbitrary and you can use any legal variable name – avoid the name of the property though!

This results in a constructor that looks like this

RStimezone(
   [int]$idx,
   [string]$desc,
   [string]$tmzn,
   [bool]$crnt
   ){
   $this.Index = $idx
   $this.Description = $desc
   $this.Timezone = $tmzn
   $this.Current = $crnt
}

But there is no explanation of WHY this naming convention is suggested. So far as I can tell there is no scopeing issue, so using arguments with the same name as the class properties should not cause issues. And to my eye this is a much more readable approach.

RStimezone(
   [int]$index,
   [string]$description,
   [string]$timezone,
   [bool]$current
   ){
   $this.Index = $index
   $this.Description = $description
   $this.Timezone = $timezone
   $this.Current = $current
}

Am I missing something here?

1 Answers

Note: I personally prefer descriptive parameter names, even if they happen to collide with property names - but that's not the question here :)

I obviously can't speak for Richard, for I can think of two reasons why someone would decide to avoid method parameter names colliding with property names:

Avoiding a future refactoring "gotcha!"

The article in question was written in September 2016!

Around that time Visual Studio Code was still in its infancy - and LSP (the Language Server Protocol) had barely been standardized.

This meant that in many editors - bar PowerShell ISE, and perhaps SAPIEN PowerShell Studio - proper and contextual "language support" for PowerShell was purely syntactical, and in many cases based on shoddy regex-based tokenizers.

.NET based editors could take advantage of the new Parser/AST API introduced in PowerShell 3.0, but this was a bit of an undertaking, since the post-3.0 language also made some syntactical allowances around implicit attribute arguments, literal array handling etc.

So by the time 5.0 came around, and the only major change to the language was the introduction of the class and enum type definition statements, very few editors were quick to implement full support for these new (and slightly complicated) features - because the rest of the language was virtually the same and many syntactical analyzers sorta worked.

What does this have to do with naming method parameters and class properties, you say?

Well, imagine a syntactical analyzer attempting a variable-rename operation on the $myString parameter in the (valid) constructor below:

class MyClass
{
    [string]
    $myString

    MyClass([string]$myString)
    {
        $this.myString = $myString
    }
}

A naive refactoring tool would leave you with this (invalid) constructor:

class MyClass
{
    [string]
    $renamedString

    MyClass([string]$renamedString)
    {
        $this.myString = $renamedString
    }
}

Cargo-culting

As the article by-line notes, Richard, already in 2016, had over 25 years of experience in IT, and I can assure you he's spent a significant portion of his career working with C#.

If I show you an equivalent pattern in C#, it might become obvious why this specific type of naming collision/overlap is discouraged, from a readability point-of-view:

class MyClass
{
  private string myString;

  MyClass(string myString)
  {
    this.myString = myString.Substring(Math.Min(1, myString.Length));
  }

  string SomeMethod()
  {
    return myString;
  }
}

In the above class, the bare token myString is now representing two distinct values depending on which method body you're looking at. If you think "that's not weird, I can read it just fine", take a turing test, because you might be a compiler ;-)

Related