有众所周知的PowerShell编码约定吗?


18

在PowerShell中编程时是否有任何定义明确的约定?

例如,在要长期维护的脚本中,我们是否需要:

  • 使用真实的cmdlet名称还是别名?
  • 完整或部分指定cmdlet参数名称(dir -Recurse与相对dir -r
  • 在为cmdlet指定字符串参数时,是否将它们括在引号(New-Object 'System.Int32'New-Object System.Int32
  • 在编写函数和过滤器时,是否指定参数的类型?
  • 您是否在(正式)正确的情况下编写cmdlet?
  • 对于像BEGIN...PROCESS...END这样的关键字,您仅将它们写为大写吗?

似乎MSDN缺少用于PowerShell的编码约定文档,而对于C#,则存在这样的文档。




2
有一个社区项目试图记录这些约定。github.com/PoshCode/PowerShellPracticeAndStyle。当然有差异,风格是很个人的事。
克里斯·邓特

Answers:


8

@Robert Harvey引用了一些很好的正式链接。通过不太正式的文件,我的想法是:

使用真实的cmdlet名称还是别名?

仅当别名比全名更清晰时,才使用别名。例如,我想大多数人会发现dirls比脚本更明确Get-ChildItem根据以往的经验(例如,基本上任何人编写PowerShell脚本但在两个DOS批处理脚本或Unix脚本这两个多次之一)。

完全或部分指定cmdlet参数名称(dir -Recurse与dir -r)

在脚本中,我会完全拼写该名称,因为(与上面的示例不同)我想不到较短的开关实际上比拼出它清晰的时间。较短的开关名称是为了节省输入。在命令行上,这势在必行。在脚本中,为增加可读性和可维护性,额外的击键非常值得。

为cmdlet指定字符串参数时,是否将其括在引号中(New-Object'System.Int32'与New-Object System.Int32

阅读代码时,将字符串参数括在引号中似乎更加清晰,因此我将其包括在内。

在编写函数和过滤器时,是否指定参数的类型?

仅在需要这样做时才能解决解释程序的歧义(确实如此)。如果您要尝试在所有内容上都使用类型,则不妨去编写C#命令行应用程序(这并不总是一件坏事,但是它抵消了通过脚本节省的时间)。

您是否在(正式)正确的情况下编写cmdlet?

应该。我通常会。匆匆忙忙时,我被告知对案件有些松懈,因为这在语法上并不重要。

对于像BEGIN ... PROCESS ... END这样的关键字,您仅将它们写为大写吗?

不,这不是FORTRAN。我认为大多数人都比begin或觉得Begin可读性强BEGIN。我们将所有大写字母与在线喊叫相关联是有原因的,而喊叫该程序中最平凡的部分会引起人们的注意,因为这会引起人们对最重要部分的关注,从而降低了可读性。

指导原则应该是可读性。脚本从本质上讲是快速又肮脏的程序,它们倾向于只写代码。您应做出所有决定,以确保您和您的团队在六个月内仍能理解该脚本。在查看代码时,尝试使自己脱颖而出,并提出以下问题:“如果我是一周前开始这项工作的(因此并未真正融入到一般文化中),我是否会找到这种写照的方式?或令人困惑?”


2

Microsoft已编写并发布了一套非常好的Cmdlet开发准则

摘抄:

本节中的主题提供了可用于生成格式正确的cmdlet的开发准则。通过利用Windows PowerShell运行时提供的通用功能并遵循这些准则,您可以轻松开发强大的cmdlet,并为用户提供一致的体验。此外,由于通用功能不需要重新测试,因此您将减少测试负担。

在这个部分

这些准则不限于任何语言(它们都没有提及语言),并且在PowerShell中编写Cmdlet时完全适用。

使用这些准则将帮助您编写清晰,可发现,可用和可重用的Cmdlet。在遵循这些准则创建几个PowerShell模块之后,我发现并不难,并帮助我成为了更好的PowerShell开发人员。在编写简单脚本时,也可以直接使用该技能。


1
这些似乎更多地与如何编写cmdlet有关,而不是与如何编写PowerShell有关。
菲利普·肯德尔2015年

@PhilipKendall他们确实做到了。这可能无法回答完整的问题,但我相信这可以为问题增加价值。请注意,您可以在纯PowerShell中完美地编写Cmdlet,并且这些准则也确实对此有所帮助。如果您可以在PowerShell中编写良好的Cmdlet,则也可以编写良好的PowerShell脚本。
oɔɯǝɹ

1

作为第二个答案;您可以使用PSScriptAnalyzer模块来验证您的代码。

Invoke-ScriptAnalyzer -Path .

它基于使用规则集的代码分析。它将验证代码设计,并将帮助您检测代码中的许多小问题。

我们将其合并到我们的构建中(我们使用构建和模块的专用存储库),以捕获设计和质量问题。

如果您有兴趣,此模块还包含PowerShell代码格式化程序(可以使用多种样式),因此您也可以使用它来标准化代码布局。


0

@oɔɯǝɹ的答案中的文档是很好的(即使是切向的)来源。

如果使用计划替换老化的PowerShell ISE的Visual Studio Code,然后安装VS Code PowerShell扩展,则该扩展包括多个格式设置选项,这些选项至少部分基于非官方PowerShell最佳实践和样式指南。VS Code和PowerShell扩展都由Microsoft管理,因此它的官方发行版可以说是官方的。

我不同意他们所说的一切。例如,我来自PHP,Java,C#和SQL,如果不需要,则应使用分号。没有它们,代码对我来说似乎是错误的,因此我将它们包括在内。如果有,#requires SemicolonTerminator我会在大多数脚本中启用它,这样我就不必担心空格换行。我讨厌回车和其他VB主义。

这些是我的其余观点:

使用真实的cmdlet名称还是别名?

要明确。切勿在已保存的脚本中使用别名;甚至是默认别名。没有什么可以阻止用户更改默认别名。假设它们不是一成不变的,这是更安全的做法。

完全或部分指定cmdlet参数名称(dir -Recurse与dir -r)

同样,要明确。完整的参数名称具有最佳的前向兼容性。 -r在今天可能并不确定,但是没有什么可以阻止命令的未来版本引入新参数的。您将要使用IDE(ISE或VS Code)。点击Ctrl+ Space并自动完成该参数。

注意这ls -r 模棱两可的。 -ReadOnly是的另一个参数Get-ChildItem

为cmdlet指定字符串参数时,是否将其括在引号中(New-Object'System.Int32'与New-Object System.Int32

通常,仅在必要时才使用引号(例如,New-Object -TypeName 'System.Collections.Generic.HashSet[System.Int32]'。时,请使用单引号;当您需要封装单引号或需要嵌入变量时,请仅使用双引号。

在编写函数和过滤器时,是否指定参数的类型?

我通常会这样做,除非我特别需要接受具有相同参数的多种类型,并且不想编写单独的参数集。

您是否在(正式)正确的情况下编写cmdlet?

帕斯卡案。是。

对于像BEGIN ... PROCESS ... END这样的关键字,您仅将它们写为大写吗?

我见过的语句,运算符,和语言结构BeginIfForEach-NotIn以及beginifforeach-notin。就我个人而言,我更喜欢小写字母,而命令却保留为Pascal大小写,但是它们都一样普遍。

其他:

  • 始终指定参数。不要依赖位置顺序。 New-Object -TypeName System.Int32结束New-Object System.Int32。我不知道是否同意这一点,但是,这似乎再次支持“明确”的一般想法。

  • 如果我正在编写模块,则使用指示的标准动词Get-Verb。但是,此列表非常狭窄,因此,只有我自己会运行的脚本的独立脚本名称通常不会。通用动词列表的问题是它趋向于Get-ScriptForSpecificPurposeNoNotThatOneTheOtherOne.ps1。如果我正在编写从PDF文件提取某些页面的脚本,则不会调用它Get-ExtractedAccountPDFPages.ps1。我叫它Extract-AccountPDFPages.ps1。我并不担心脚本本身是否可以作为程序运行,并且其本质并非旨在模块化。

  • 当它更具可读性,更具体或更易于维护时,请打破规则。


-3

多年来,已经有多种方式为变量,函数等编写多词名称。

PROGRAMFORSORTINGLOTSOFTHINGS很难阅读。

PROGRAM_FOR_SORTING_LOTS_OF_THINGS容易一些。

program_for_sorting_lots_of_things比较容易。

ProgramForSortingLotsOfThings消除了下划线并保持了可读性。Powershell大多数情况下会这样做。


Powershell通常会混合使用驼峰式(语法上没有任何意义)和破折号。例如,Get-ChildItem在动词和名词之间加一个破折号。
安德鲁说莫妮卡(
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.