全局变量用例

时间:2016-10-02 15:18:33

标签: powershell global-variables

我有一些脚本和模块,它们使用全局变量来处理许多事情。我的日志记录可以采用三种形式之一; Terse,Verbose和Validation(详细记录没有实际操作,只是验证提供的数据)。我还有许多函数,这些函数根据它们运行的​​上下文(用户或机器)做出不同的响应,并且正在执行的Action(Rollout,Remove,Conform,Relocate)也会影响事物。 所以,到目前为止,我已经使用了三个全局变量并且它已经有效,但我知道最佳实践是避免全局变量。也就是说,解决它的唯一方法似乎是在一个模块中使用一些Get和Set函数,以及Script级别变量。这似乎增加了复杂性而没有真正解决太多,因为我仍然有比使用它们的函数更高的变量。或者,我可以将这三个值传递给需要它们的每个函数,但也有很多参数几乎没有增加价值。所以我开始想知道,这是一个全局变量确实是正确答案的地方吗?它们的存在表明必须存在一些应该使用它们的情况,并且这种情况开始感觉就像那种情况一样。

2 个答案:

答案 0 :(得分:5)

在特定场景中使用全局变量没有任何问题,特别是对于全局设置或单个对象,这些对象只定义一次,然后在其余代码中使用而无需进一步修改。关键是避免改变变量。

你应该使用全局变量是用于传输状态,即更改值。如果您在代码中的不同位置更改全局变量的值,则问题会在后面引起巨大的痛苦,因为您将信息传递到常规"渠道之外" (参数,返回值)。如果您需要在代码中的其他位置修改全局变量,那么几乎总是表明您应该重新评估您的体系结构。

答案 1 :(得分:3)

使用动态范围保护PowerShell中的全局变量

PowerShell实现Dynamic Scoping。这是当今语言设计中罕见的选择,但正确应用的动态范围使开发人员能够比全局变量更好地控制名称冲突。要了解这可能适用于您的案例,请考虑以下玩具模块:

# File Module1.psm1

$module = "Module1"
$Context = "User"

function Log-Message( $message ) {
    Write-Host "$module/${action}: $message ($LogLevel-$Context)"
}

function CommonCode { 
    Log-Message "In CommonCode"
}


function Invoke-Rollout( $LogLevel = "Terse", $Context=$script:Context) { 
    $action = "Rollout"
    CommonCode  
}

function Invoke-Remove( $LogLevel = "Terse", $Context=$script:Context) {
    $action = "Remove"
    CommonCode
}

function Set-Module1( $Context=$script:Context ) {
    $script:Context = $Context
}

Export-ModuleMember -Function Invoke-Rollout, Invoke-Remove, Set-Module1

重要的是,在Log-Message中,变量$module$action$LogLevel$LogContext < em>全局变量,而不是自由变量,其范围尚未确定。在运行时,PowerShell将根据调用堆栈中的最新定义动态确定其绑定...

不是试图详细解释这个问题,而是最好还是玩这个玩具模块,看看动态作用域对记录的影响。以下是我尝试的一些实验:

PS C:\temp> Import-Module -Force .\Module1.psm1

PS C:\temp> Invoke-Rollout
Module1/Rollout: In CommonCode (Terse-User)

PS C:\temp> # For Sticky Change -- Set-Module1
PS C:\temp> Set-Module1 -Context Machine

PS C:\temp> Invoke-Rollout
Module1/Rollout: In CommonCode (Terse-Machine)

PS C:\temp> Invoke-Remove -LogLevel Verbose -Context XXX
Module1/Remove: In CommonCode (Verbose-XXX)

PS C:\temp> Invoke-Remove -Context User
Module1/Remove: In CommonCode (Terse-User)

PS C:\temp> $Context = "FooBar" # This should have no effet on Module1

PS C:\temp> Invoke-Remove
Module1/Remove: In CommonCode (Terse-Machine)