PSScriptAnalyzer icon indicating copy to clipboard operation
PSScriptAnalyzer copied to clipboard

Avoid using cmdlet aliases.

Open yutingc opened this issue 10 years ago • 46 comments

What aliases should we put on the white-list? This is a open thread for discussion.

yutingc avatar May 26 '15 18:05 yutingc

I would assume if a script is being run through the Analyzer it is being prepared for distribution. Aliases should then only be used if they increase readability for the enduser.

Example gl doesn't make much sense, but del would. If you're going to allow aliases at all, maybe only allow the ones that match existing, commonly used, non-powershell commands.

GoodOlClint avatar May 28 '15 11:05 GoodOlClint

I've been thinking about the idea of a white-list some more, and reviewing my internal scripts and profile, and now that I have done so (and remembered some changes I have made to my environment), I'm going to turn direction on this and suggest the following:

  1. Any use of aliases in a script or module being run through Script Analyzer should generate a warning for all aliases
  2. Authors of modules or scripts that define aliases where use of an alias would be a best practice must be able to disable that warning for the users of that module (this was already proposed in another issue).

The reason I've backpedaled on this is because of how easy it is to change built-in alias behaviour, and why it may even be beneficial for users to do so.

In my profile, I have the following script snippet:

#region Fix important *nix commands.

# PowerShell comes with some predefined aliases built-in that are designed to
# ease the transition from *nx to PowerShell. While this is well-intentioned,
# it hides the true power that is available in these *nx commands, and it
# makes it much more difficult to compare and contrast between native commands
# in PowerShell and their *nx counterparts. This block of code removes the
# predefined aliases that would otherwise hide these important *nx commands
# that are made available through Cygwin.

foreach ($nxCommand in @('cat','cp','curl','diff','echo','kill','ls','man','mount','mv','ps','pwd','rm','sleep','tee','type','wget')) {
    if (Test-Path -LiteralPath alias:${nxCommand}) {
        Remove-Item -LiteralPath alias:${nxCommand} -Force
    }
}

New-Alias -Name type -Value cat

function ls {
    param()
    if ($args -notcontains '--color') {
        $args += '--color'
    }
    & ls.exe @args
}

#endregion

This script snippet is important for me because I use cygwin on my system, and I find it much more convenient if *nix commands I enter actually run those *nix commands. I don't want curl invoking Invoke-WebRequest. Nor do I want ls invoking Get-ChildItem. I have iwr and gci as aliases for those so that I can save time when using them ad-hoc. Instead when I run curl or ls, I want the actual *nix command from Cygwin to run. This allows me to take *nix examples from the web and run them, have them work, plus compare and contrast with PowerShell equivalent functionality all from the same shell. It is very convenient. Also, the *nix commands run very, very fast, so I can compare performance with PowerShell equivalent functionality as well. That benefit has proven quite advantageous to me already, because there is a lot of functionality behind *nix commands that is not in PowerShell. Sure, I don't get objects back, just text, but when I need objects I know how to get those, and I have aliases that I can use that are PowerShell specific. This mixed-mode approach is better for me, as I have never really liked the over-simplified approach of having a *nix command be an alias because command arguments aren't the same at all.

It doesn't matter if aliases are built-in and read-only. You can remove them with a very simple command in PowerShell. And rightly so, because there are scenarios where you would want to (as I identified here). Even if you were to argue that aliases should be allowed for *-Object commands, tee is an alias by default for tee-object, but tee is also a *nix command and when I invoke that, I want the *nix command to invoke.

If any aliases at all are whitelisted, I would limit it to a very, very small set, like foreach and where (because those commands are rather exceptional in that they are used very commonly, perhaps more commonly than any other command, and because they also have corresponding keywords with the same name, so newcomers can understand them more easily that way -- the idea of foreach vs ForEach-Object can confuse people). But even then, is Script Analysis about making scripts readable and easy to understand by others or is it about making scripts reliable in every environment? I think it's about the latter, in which case I think there should be no whitelist of aliases, and the only exceptions should be when attributes are used to make them exceptions, by a script or module consumer or by a script or module author.

KirkMunro avatar May 28 '15 14:05 KirkMunro

I am in almost complete agreement, @KirkMunro. You've articulated extremely well the point that I was trying to make on Monday. My only nitpick is here:

But even then, is Script Analysis about making scripts readable and easy to understand by others or is it about making scripts reliable in every environment?

I would argue that it's intended for both purposes: manageability of code among many people, and reliability of code among many environments. However, this doesn't change your point which is that there should be no whitelist.

Again, though, I think this becomes less of an issue for those that still love aliases in their scripts when we enable global rule suppression.

joeyaiello avatar May 29 '15 22:05 joeyaiello

Hmm, I kind of like the whitelist approach. We use CA dictionary.xml (https://msdn.microsoft.com/en-us/library/bb514188.aspx) files for almost all of our C# source code. We have any industry specific terms and abbreviations that CA flags as misspellings. I could see a generic PSSA config file that has a section for global suppressions, a section for whitelisted aliases, eventually a section for recognized words (if PSSA ever does spell checking). Over time, this config could be expanded to add new capabilities to configure PSSA.

This config file could also serve as a basis for the "profile" functionality we have discussed. For instance, I can almost guarantee that the folks I work with, who will see dozens to perhaps a hundred alias warnings in their scripts about Where, Foreach and Select, will suppress the whole rule. That is a shame as I think it would be better to allow them to whitelist those three aliases so they won't suppress the rule. I can make a good case that they shouldn't be using ? and % and encourage them to fix those spots in their scripts. But if they globally suppress the rule, well, none of theses will get fixed.

I could see a "Existing Script" profile that is a config that suppresses all but the most serious errors and warnings and is perhaps pre-populated with a few, what I would call "canonical" aliases like Where, Foreach and Select.

rkeithhill avatar May 30 '15 01:05 rkeithhill

I don't think suppression is black or white. For example, for uninitialized variables, you can suppress that warning for individual named variables. So the "whitelisting" concept could come from partial suppression, but whitelisting specific aliases in PSScriptAnalyzer for anyone who uses it doesn't seem like the right approach given how people may change their aliases.

KirkMunro avatar May 30 '15 01:05 KirkMunro

I don't think suppression is black or white.

Let's put it this way, and I've seen this time and time again with C# devs, if there are too many instances of a particular rule firing, they will globally suppress the rule instead of suppressing per instance. That's just human nature (path of least resistance) and I fully expect that to be the case with folks using PSSA. A whitelist/config file provides both finer control and is easy i.e. it is easier to whitelist the foreach alias once than to suppress it individually in dozens of places.

I think a high degree of configurability is important for this tool otherwise folks will write it off as just too noisy. I ran PSSA against our nightly regression test scripts - about 10 scripts with a total of ~13,000 lines. The script ran for 7.5 minute and I got 3758 diagnostic records.

45> $res | group RuleName | sort count -desc

Count Name                      Group
----- ----                      -----
 2179 PSAvoidUninitializedVa... {Microsoft.W
  942 PSAvoidUsingPositional... {Microsoft.W
  230 PSUseDeclaredVarsMoreT... {Microsoft.W
  141 PSAvoidUsingInternalURLs  {Microsoft.W
  108 PSAvoidUsingCmdletAliases {Microsoft.W
   56 PSAvoidUsingWriteHost     {Microsoft.W
   35 PSAvoidUsingInvokeExpr... {Microsoft.W
   32 PSAvoidTrapStatement      {Microsoft.W
   12 PSAvoidUsingWMICmdlet     {Microsoft.W
    8 PSPossibleIncorrectCom... {Microsoft.W
    6 PSUsePSCredentialType     {Microsoft.W
    4 PSUseApprovedVerbs        {Microsoft.W
    2 PSAvoidGlobalVars         {Microsoft.W
    1 PSUseCmdletCorrectly      {Microsoft.W
    1 PSAvoidUsingComputerNa... {Microsoft.W
    1 PSProvideVerboseMessage   {Microsoft.W

Yeah, that could be a bit intimidating to tackle without just globally suppressing say the first six rules. But global suppressions are a very big stick and any new code will not get checked against globally suppressed rules.

rkeithhill avatar May 30 '15 04:05 rkeithhill

In my opinion, if users remove Constant or ReadOnly aliases and scripts break on them, that's user error.

Particularly the built-in ones:

  • Especially the short, verb-only form of the invalid verb object commands (Where-Object, Sort-Object, Select-Object, Tee-Object) which are more readable in short form,
  • But also the DOS and UNIX commands which "everyone knows" and which are therefore readable in a script without full verb-noun syntax
  • In general, aliases that are defined in such a way that they work without the user importing a module by hand first.

Needlessly warning about aliases just validates the complaints about the overly verbose syntax of PowerShell.

For what it's worth, @rkeithhill, I would argue that it would probably logical to disable five of your top six ;-)

  • PSAvoidUninitializedVariables is often silly, since half the time your first use is to check if it's null ... but I guess I'd inspect a few instances of it before deciding.
  • PSAvoidUsingPositionalParameters is almost always silly. Changing positional parameters would be a breaking change, so using them isn't really that big of a deal -- maybe make it warn if you use more than two for the sake of readability, but that's one where I feel like it depends on the command.
  • PSAvoidUsingInternalUrls is probably complaining about regex patterns like \s+ being passed to -split ...
  • PSAvoidUsingCmdletAliases is probably just complaining about stuff like the use of "Where" instead of "Where-Object" and "Select" instead of "Select-Object" and I'm always going to come down on the side of using the short forms of those, they're far more readable (especially without parameter names).
  • PSAvoidUsingWriteHost is probably something you've thought about and decided deliberately to do ...

The one thing I'd check on is PSUseDeclaredVarsMoreThanAssignments, which in my experience is probably right, but it's basically impossible for that warning to represent actual errors or problems.

Jaykul avatar Nov 25 '15 04:11 Jaykul

For those new to the language PSAvoidUsingCmdletAliases is a crucial rule to get them to understand that PowerShell is Object orientated and not text driven especially for those that are from an interchanging multi OS mixed environment.

We should be catering this for the much wider scope than those that have 3+ dedicated years of working with the Language

For what its worth regarding aliases as a whole I see there being a usecase for using them in interactive sessions only - they shouldn't be used in scripts at all for the reasons given by @KirkMunro and as we are analysing scripts and not the interactive sessions I think having a Whitelist of aliases is counter intuitive and more damaging than fully enforcing to use the language in its full manner i.e using the verb-noun convention

kilasuit avatar Nov 25 '15 19:11 kilasuit

I definitely don't see the connection between long names and object oriented output.

More to the point, those are the exact people who will be turned off PowerShell as a shell if you insist on writing out fully verbose commands like Get-ChildItem -LiteralPath $Pwd instead of dir

As long as you (and this tool) insists on not using aliases at all in scripts, not to mention positional parameters and short form parameters -- I guess we have very little to talk about. I passionately disagree.

For what it's worth, I think you're trying to use default rules to force people to write things a certain way that you like, without regard for any useful metrics.

@KirkMunro wrote

It doesn't matter if aliases are built-in and read-only. You can remove them with a very simple command in PowerShell. And rightly so, because there are scenarios where you would want to (as I identified here). Even if you were to argue that aliases should be allowed for *-Object commands, tee is an alias by default for tee-object, but tee is also a *nx command and when I invoke that, I want the *nx command to invoke.

The truth is:

Using Where-Object is no safer than using Where -- any user or module can override Where-Object by just defining a function -- in fact, it's easier to override the command name: they don't have to deliberately override the built-in defaults with -Force and -Option AllScope.

There is just no difference.

One is not inherently more dangerous than the other, nor more inherently built-in.

  • So why are you more concerned about aliases than you are about functions?
  • Why are you worrying about the difference between an alias and a partial command name? The only thing that's safe is a module-qualified name.
  • Why does this rule not care if I've defined aliases within my script? When I define an alias in my script, it doesn't matter if you change the alias outside.
  • Why are you even writing rules about aliases at all if you haven't even figured out how to check to see if the script properly #requires the sources of the commands it uses? It's far more important to deal with dependencies than syntax shortcuts.

In point of fact, if Where is defined with the fully qualified name (as it should be):

Set-Alias -Name Where -Value Microsoft.PowerShell.Core\Where-Object -Force -Option AllScope, ReadOnly, Constant

The alias "where" is now safer than the simple name Where-Object because it won't be broken if another module exports Where-Object....

Jaykul avatar Nov 27 '15 00:11 Jaykul

@Jaykul. I still stand by my last point.

But even then, is Script Analysis about making scripts readable and easy to understand by others or is it about making scripts reliable in every environment? I think it's about the latter, in which case I think there should be no whitelist of aliases, and the only exceptions should be when attributes are used to make them exceptions, by a script or module consumer or by a script or module author.

Sure people can still cause stuff to break by creating functions with the same names as cmdlets. Even Microsoft employees do that sometimes. But that's a completely separate issue that is outside of the scope of what PSScriptAnalyzer should deal with.

Intellisense and other tools make it trivial to use full command names. Scripts using full command names (not fully qualified, just no aliases) have a much higher chance of success when run on any system than scripts using aliases.

For examples shared on the web and in repositories like the Gallery, I think that is the better way to go for everyone involved, regardless of individual personal feelings on what aliases are safe vs what are not.

For other stuff (scripts that you write for private or corporate use that are not broadly shared, where you have more control over the reliability of aliases because you control the environment), you don't have to use this rule, do you? Because you can configure a profile ("profile" is a bad name, it's really just configuration) that controls which rule sets get used by script analyzer. For things like Code integration, if it's to run script analyzer all the time, maybe they should just provide better support for script analyzer profiles so that you can define one that works for content you produce for your environment.

KirkMunro avatar Nov 27 '15 16:11 KirkMunro

@jaykul wrote:

in fact, it's easier to override the command name

Indeed. I think it is far more likely that you will run into an issue using a resolved, but not fully qualified cmdlet name such as Where-Object or in a recent example Expand-Archive.

PSCX has had an Expand-Archive command for a long time. Recently, PowerShell V5 added an Expand-Archive command. The vscode-powershell extension has a bit of PowerShell script that was used to install the extenion before VSCode had proper extension installation support. That script would fail on machines with PSCX installed because the PSCX version of Expand-Archive took precedence over the built-in one (and used different parameter names). However the script was written with the built-in command in mind.

With PSCX we can deprecate our Expand-Archive in deference to the built-in one. Still, I think this is likely to continue to be a problem down the road. The safe way to reference built-in commands is to always use a module-qualified name. Personally I think the resulting script would be nigh unreadable if every command were module-qualified. :-) So how do you protect yourself from this real danger?

Scripts executing in a user's PowerShell console are executing in dangerous waters

Personally, I wish that once you got into script scope, PowerShell would A) no longer auto-load modules and B) would not give a command precedence unless it was explicitly imported by the script. If you take defensive programming to the extreme, you have to protect your script against every possible thing thousands of users have done to their global enviornments including (but not limited to):

  • Command proxies
  • Imported (auto or explicit) modules that implement the same named command (but semantically different)
  • Redirected aliases
  • Defined variables you weren't expecting to be defined
  • Removed globals you were expecting to be defined
  • Already loaded module (but wrong version).

Do we need more of a wall between a script's execution environment and the user's potentially polluted global scope? You could run a script using powershell.exe -noprofile that helps with a lot of the above issues. I wish the equivalent of a "clean, no-profile" global scope could be enforced for script execution yet still allowed be run from a user's polluted global scope. Perhaps a #Requires NoGlobalSession or something like that?

WRT to auto-loaded modules, I think that some of these features that were added to help with CLI discovery of commands are hurting the reliability of scripts. Once you are writing a script, you should have more control over what is loaded and used by your script.

rkeithhill avatar Nov 27 '15 20:11 rkeithhill

Maybe something like:

#requires -Modules ... -Preferred

or

using ModuleName

where either of these would set the preferred command resolution order (look in the specified modules first).

I'd gladly welcome such a change.

It would be very nice if there was a way to disable auto-loading as well (a new parameter for Set-StrictMode maybe).

This idea is similar to PSDefaultParameterValues -- it's a powerful, very useful feature, but you don't want to inherit the values that are set in it inside of your module because it can break things. In v5 they changed it so that PSDefaultParameterValues are automatically cleared in script module scope, but modules in v3 and v4 still are vulnerable to it, as are script files themselves.

Keith, have you logged that on Connect? If not, please do, I'll vote it up.

KirkMunro avatar Nov 27 '15 21:11 KirkMunro

@KirkMunro Here you go Kirk. Please feel free to embellish the description of the issue with a comment.

https://connect.microsoft.com/PowerShell/feedbackdetail/view/2065573/scripts-need-better-isolation-from-the-users-global-session-state

rkeithhill avatar Nov 27 '15 21:11 rkeithhill

OK, circling back around to the original topic ... :-)

I could see going two ways here.

First option - implement a configurable whitelist (perhaps empty by default) in which case I would add the aliases: Where, Foreach, Select, Group, Sort, Tee, Measure, Compare, Measure. I would also add cd, pushd, popd. Sorry but I see scripts littered with cd, I just don't see much benefit in changing a bunch of working scripts to use Set-Location. Ultimately I think this works best if the whitelist is configurable by the user. Having used FxCop and StyleCop for about a decade on C# source, I can tell you that we would have stopped using these tools if they weren't pretty configurable. A tool like this has to be careful about being too opinionated or you'll just turn off folks to using it - especially for rules of debatable value.

Second option - no whitelist but have a "Minimum" profile that does not include this rule. And the minimum profile (or ruleset) should be the default. I think it should be up to the user to move up the chain of more rigorous profiles. This will give a better, "first use" experience of showing warnings/errors on what would truly be problems in the user's script. Next step up is perhaps a "Normal" profile that checks for more stuff. Then perhaps there is a "PSGallery" profile that is even more stricter.

At the end of the day, you want to provide a tool that folks can get value out of, that has a positive "out of the box" experience and doesn't force debatable policies down your throat. Yes I know I can disable the "avoid using cmdlet aliases" rule and if nothing changes that is exactly what I will do for my team. However that is a shame as I would like to avoid using all other aliases except for those I listed above.

rkeithhill avatar Nov 27 '15 22:11 rkeithhill

I'm resisting the urge to repeat arguments which have already been made above, so let me just say that the fact that this rule is still in the default set after all this time makes me feel we're being ignored, and is the number two reason why I don't like ScriptAnalyzer.

Jaykul avatar Jul 11 '16 22:07 Jaykul

@Jaykul You may not agree with the rule and I understand your reasons behind it - however I find it important for those that aren't as experienced with the language to be able to run it and understand that they are using aliases.

I'd be one for having a separate rule that allows us to define whitelisted aliases but would expect the defacto standard rule to just kick out a warning on all alias uses.

You choice on which rule to use is then upto you but I know that I'd personally use the defacto rule.

@joeyaiello / @raghushantha - could we get a new Rule PSAvoidNonWhitelistedCmdletAliases to combat @Jaykul concerns about ability to be configured appropriately for the more advanced user whilst being able to be a tool that is useful to the casual/newcomer to the PowerShell World

kilasuit avatar Jul 13 '16 17:07 kilasuit

PS Created new issue for the PSAvoidNonWhitelistedCmdletAliases rule #580

kilasuit avatar Jul 13 '16 17:07 kilasuit

@kilasuit In my opinion, you're repeating the same mistake made earlier in the conversation. Why does it matter if they are using built-in aliases?

Jaykul avatar Jul 18 '16 17:07 Jaykul

I'm submitting a PR to get deprecated of this ill formed rule. It is bad for the community and people are abusing the rationale 'aliases are bad' instead of embracing idiomatic powershell as awesome.

rismoney avatar Apr 12 '18 23:04 rismoney

@rismoney Times have moved on since this issue was created. PowerShell Core came out and as part of it some alias had to be removed on some platforms, which makes it much more important to not use aliases in scripts. Aliases are meant to be used when typing command but not in scripts due to readability and the fact that the alias might not exist in the given version of PowerShell or platform. The future direction is even to take out aliases completely and provide them via modules. You can call Invoke-ScriptAnalyzer with -ExcludeRule PSAvoidUsingCmdletAliases if the rule is not suitable for your environment but I think the rule still makes sense to be there. This needs further discussion and approval before PR #970 that you opened can continue. From me it is a no to this change but I'm happy to be convinced otherwise. Can you please comment @SteveL-MSFT

bergmeister avatar Apr 13 '18 07:04 bergmeister

Times have moved on since this issue was created.

True but in the duration this issue has caused irreparable harm to the ecosystem in favor of removing aliases from scripts for poor foundational reasoning. This now accounts for unneccesary verbose scripts that don't embrace a powershell's idiomatic style capabilities.

PowerShell Core came out and as part of it some alias had to be removed on some platforms, which makes it much more important to not use aliases in scripts.

Disagree. Powershell core can do what it wants. It is clear that Microsoft has been ambiguous on what to provide in core. Feature parity isn't implied through the Core nomenclature. Plenty of scripts have no intention for ever running on Core yet are perfectly compliant on their current platform. When other linters and analyzers for other languages have cross version incompatibilities these exceptions are managed as such and not excluded via a misleading catch-all category. Specific alias usage discouragement is then understood as a deprecated feature, and not as all aliases are bad. If my exception rule was conformtoPSstandard that would make sense. But if all aliases included in core are banned that's a new wave of broken.

Aliases are meant to be used when typing command but not in scripts due to readability and the fact that the alias might not exist in the given version of PowerShell or platform

Disagree with first part entirely. It's idiomatic powershell that you are rejecting. ? and % are wonderful and should be encouraged everywhere. The latter as I previous stated should be addressed via versioning incompatibilities not on the alias usage perspective.

The future direction is even to take out aliases completely and provide them via modules.

The future direction is machine names > 15 characters... Largely irrelevant today.

You can call Invoke-ScriptAnalyzer with ExcludeRule PSAvoidUsingCmdletAliases

Exceptions imply you are breaking a generally accepted rule. In this case as I've stated the rule should be cross version alias compatibility not using aliases in general. Aliases are great and you should embrace them in scripts everywhere. When I see an Invoke-Expression instead of iex I cringe that people see this as a horrific language of really verbose cmdlet names that are encouraged. Embrace the idioms! Now if Microsoft regrets aliasing curl to iwr that's a different story. Their intentions haven't been pure on that. At the time they wanted to publically demo powershell as friendly to Linux folks, albeit deceptively. Look curl gets a url on Powershell!! But iwr has been in the product for 6 versions and it shouldn't, like many other aliases be discouraged for misguided reasons and people spouting mantras like 'aliases are bad'

rismoney avatar Apr 13 '18 12:04 rismoney

Exceptions imply you are breaking a generally accepted rule. In this case as I've stated the rule should be cross version alias compatibility not using aliases in general.

I agree that the version compatibility argument isn't the best one when it comes to aliases. I'd like to see a separate rule that warns about specific aliases if you've already excluded PSAvoidUsingCmdletAliases, for those who prefer aliases.

The stronger argument is readability for those just starting to learn PowerShell. You can instantly tell what Invoke-Expression does, but you're much more likely to need to google iex if you haven't come across it. Honestly I absolutely love aliases and use them a bunch at the prompt, but if I saw sujb 1 in script it'd take me at least a couple seconds to guess that was Suspend-Job. There's definitely arguments to be made that some aliases are more readable to new comers than their referenced commands, but I don't think many would argue that all of them are.

Now, it may be the case that none of that is important to you. That's perfectly fine, that's why you can customize rules. If you are more productive using aliases as much as possible, then absolutely continue to do so.

In fact, if you're so inclined a better approach to this might be to submit an alternate opt in rule that requires the use of aliases. I don't speak for PSSA, but I can't see any reason why that shouldn't be an option.

like many other aliases be discouraged for misguided reasons and people spouting mantras like 'aliases are bad'

I will say that the PowerShell community is one of the most welcoming communities I've seen, but yeah the pitchforks do come out when a few specific things come up (aliases, Write-Host, backticks). It can suck to disagree with the crowd sometimes, but what's important is that you're doing what works for you. There's nothing wrong with disabling a rule you disagree with, you may get some flack for it, but that's just the cost of going against the grain.

SeeminglyScience avatar Apr 13 '18 21:04 SeeminglyScience

? and % are wonderful and should be encouraged everywhere

I use these interactively all the time but I also work with folks that have to tweak my scripts. These folks are not PowerShell experts but can Google with the best of them. Cryptic syntax puts those people off where-as seeing Where-Object and Foreach-Object is significantly more "obvious" to them. That said, folks are never going to agree on what rules should be enabled/disabled by default which is why PSSA is configurable in that regard. Disable that rule and party on. :-)

rkeithhill avatar Apr 13 '18 21:04 rkeithhill

It's hardly cryptic. It's idiomatic. If anything the rule should be reversed. Anyone who endorses or uses Foreach-object should use %. foreach is not even a legit verb or word for that matter. I foreach'nt a clue who came up with this one.

Give people credit. People CAN learn simplistic symbols and shorthand used in very common cases. The language has some really rediculous cmdlet names and constructs (operators for example) which clearly add more confusion to end users than aliases ever did. It's overblown.

Overall the recommendation to the community should be to embrace them instead of curtail. The trend I see -people point to PSSA as the community's best practice voice when there is a lot misguidance here.

The subsequent issue is being labeled a rule breaker by not conforming pssa and this becomes toxic.

Deprecation notices for aliases are the way to go to bridge version gaps. But alias usage is a foundational capability since the get go.

rismoney avatar Apr 13 '18 23:04 rismoney

Totall support for @rismoney and the patch !

Times have moved on since this issue was created. PowerShell Core came out and as part of it some alias had to be removed on some platforms, which makes it much more important to not use aliases in scripts

This is invalid argument. Everyting changed, including bunch of cmdlets. Some cmdlets do not exist just the same as aliases, and some are substantially different like iwr.

Aliases are meant to be used when typing command but not in scripts due to readability and the fact that the alias might not exist in the given version of PowerShell or platform.

Another one when developers thought that they know how people use their tool, but the life thought differently, even with all that "no aliases" propaganda. I see people all around offereing 'contributions' to remove aliases. On each posh project I mantain there is always an army of little hobbits trying to remove aliases from my world (and the universe), multiple times (1 typical example)

Aliases are WAY MORE READABLE then full verbose strings. To bring only few points:

  • To the linux comming person, many aliases are well known and so on boarding is quicker. Actually, ANY worthy IT engineer already knowns about shell commands that exist as long as computer existed.
  • To the n00b person it doesn't make any difference as both variants are unknown, but he might still heard for ls/ps rather then Get-ChildItem
  • To the experienced Powershelll user aliases are better because shorter code is generally better code, easier and quicker to read and review, shorter sentences impose less cognitive load, you can put thoughts on the lines (verbosity forbids "line based thinking" in programming which people love - for example lambdas are often used to acomplish shorter expressions in many langs) lower human input (always good) etc. I would dig into neurolinguistics of it and why shorter expressions are always better ( you can entertain yourself by reading Babel-17 ) but I don't find the trouble worthwile.
  • Redefinition of aliases problem is also invalid argument (people ususally redefine rm to trash to bin) as it should be done via proxy functions correctly. Modules can also redefine cmdlets. The only way to make sure you are calling the right thing is to use fully quialified cmdlet path which is something I have seen in the wild 3 times total.

In my company, default aliases are basically mandatory. Working with many and large teams, I can't remember when we had alias problem. But I remember all sort of cmdlet problems when somebody is using non-current posh version or multiple module versions and so on. If you want to judge aliases we need facts, metrics. Not phylosophy, not intutition, not projections. Otherwise, arch desisions are baseless in reality, serve nobody and are not worthy an engineer.

The future direction is even to take out aliases completely and provide them via modules.

Amazingly bad direction really - its total insanity. Aliases are first class citizens in any shell.

majkinetor avatar Apr 14 '18 06:04 majkinetor

I use these interactively all the time but I also work with folks that have to tweak my scripts. These folks are not PowerShell experts but can Google with the best of them. Cryptic syntax puts those people off where-as seeing Where-Object and Foreach-Object is significantly more "obvious" to them

Really @rkeithhill ? Is that even happening, someobdy searching on Google for % and ? and not finding them and abandoning powershell forever ? <sarcasm> So we lost potential valuable member of community or invaluable IT worker </sarcasm>

People that want to use Powershell usually just open some tutorial or book or quick intro first and % and ? are on the first page, probably in the first few paragraphs.

This line of thinking isn't IT, its babysitting buisnis.

majkinetor avatar Apr 14 '18 06:04 majkinetor

Of course one can have different views on aliases, but a matter of fact is:

  • PSSA has to support all PowerShell versions and as some aliases do not exist on some platforms, it makes total sense to warn on some aliases as behaviour might differ. Currently, there is no version mode for it to make a more detailed judgement
  • PSSA has some cleverness built in and can also see if you have aliases defined in your session, for example the following will trigger a warning: New-Alias foo Get-ChildItem; Invoke-ScriptAnalyzer -ScriptDefinition foo. This is very helpful to avoid having a script that just works on the developer's machine because of the developer's profile/session.
  • A lot of people have to be able to read languages nowadays without knowing anything about it and just re-use their common knowledge. I myself have read and written JavaScript myself without having much of a clue how the thing works. Due to code reviews it is totally OK to make changes without much domain specific knowledge. Having a slightly longer command does not readability of a script. In VSCode one can write using aliases and then automatically replace the aliases with the full cmdlet name and in the next release of PSSA, there will be a -Fix switch that can automatically fix those warnings for you if you want to save time when writing.
  • There are quite some people that find the rule useful and that is why it still makes sense to have it. PSSA is not a religion but it is customizable and extensible. You can either customize or disable the rule if you disagree.

Therefore I do not think that a deprecation of the rule is going to happen. Rather think about something that could add value to it like for example adding a customization setting of the rule to whitelist common aliases that are available in every PowerShell version and platform like e.g. select.

bergmeister avatar Apr 23 '18 20:04 bergmeister

Whitelist common aliases from a rule that discourages use? This is backwards. If you want to block a particular alias then you should cite a reason such as incompatibility across versions (your first bullet) But I stand by, if you can't substantiate a valid reason not to use a particular alias, beyond noob understanding I think the rule is a farce and a disservice.

If you are writing code you do not understand how it works I strongly discourage you from publishing it. Aliases need not apply.

rismoney avatar Apr 23 '18 22:04 rismoney

For the record, this is the opposite of cleverness:

PSSA has some cleverness built in and can also see if you have aliases defined in your session, for example the following will trigger a warning: New-Alias foo Get-ChildItem; Invoke-ScriptAnalyzer -ScriptDefinition foo. This is very helpful to avoid having a script that just works on the developer's machine because of the developer's profile/session.

Analysis of aliases based entirely on the user's current environment is fragile, brittle, and pretty useless ...

# NO ERRORS, even though the command doesn't exist, and the script will THROW
Invoke-ScriptAnalyzer -ScriptDefinition NoSuchCommand 

Set-Alias NoSuchCommand Where-Object
# ERRORS, even though this script now actually WORKS
Invoke-ScriptAnalyzer -ScriptDefinition NoSuchCommand 

Set-Alias Where-Object NoSuchCommand
# ERRORS, because the local scope has a dumb alias -- NOT because the script is bad
Invoke-ScriptAnalyzer -ScriptDefinition Where-Object

Jaykul avatar Apr 24 '18 23:04 Jaykul

Honestly, @bergmeister maybe it's worth revisiting all those points, now that I've thought about it..

PSSA has to support all PowerShell versions and ... some aliases do not exist on some platforms

Unless we have hardcoded the lists of pre-defined aliases into it, PSSA does not know anything about aliases -- except that the current session has some. Therefore, all PSSA can reasonably do is make sure I know that my SESSION has aliases which might affect the behavior of this code. Something like:

INFO: This session has an alias Where -> Where-Object which will be used by this code. This may cause this code to behave differently in this session than in other environments.

It's hard to say that this should be more than informational since PSSA is not making a determination of whether this is a common alias present on all systems, or a built-in alias exported by the same module that exports the command, a local alias defined by the code under test, or a personal alias defined by the developer and used in error. Only the latter aliases are legitimate errors, the rest are all fine, and constitute the vast majority of aliases in real use.

Perhaps PSSA could upgrade it to a warning if it could determine the alias is shadowing a command of some other type, or is unlikely to exist on other systems.

PSSA has some cleverness built in and can also see if you have aliases defined in your session

I don't believe this is cleverness: if PSSA is a STATIC analysis tool, it shouldn't be concerned with the state of my session.

A lot of people have to be able to read languages nowadays without knowing anything about it...

The readability argument simply doesn't hold water. We've gone over this argument time and time again in threads on this project, and the bottom line is that, readability is simply not something PSSA is capable of judging, and has nothing to do with aliases.

  • dir is (for example) readable to a much larger group of people than get-childitem
  • ls is readable to a different, but still much larger group of people.

There are many examples of aliases which improve readability to certain user groups.

Additionally, there are many examples of aliases created by module authors because they renamed a command and are using aliases for backwards compatibility.

there will be a -Fix switch that can automatically fix those warnings for you

Changing the command name I have been using for months or years to the new command name that I've never seen before has a negative effect on readability for me and my team -- nevermind any other potential users.

There are some people that find the rule useful

On this we agree. I wouldn't lobby for removing the rule, but I do think it should be INFO only, and that any potential -Fix switch should have a severity or rule-name option...

Jaykul avatar Apr 25 '18 16:04 Jaykul