2016-10-02 45 views
5

我有幾個使用全局變量的腳本和模塊。我的日誌記錄可以採取三種形式之一; Terse,Verbose和Validation(詳細記錄,沒有實際操作,只是驗證提供的數據)。我還有許多函數根據它們在(用戶或機器)中運行的上下文而作出不同的響應,並且正在執行的操作(Rollout,Remove,Conform,Relocate)也會影響事物。 因此,到目前爲止,我已經使用了三個全局變量,它已經工作,但我知道最好的做法是避免全局變量。也就是說,解決這個問題的唯一方法似乎是在一個模塊和腳本級別的變量中使用Get和Set函數。這看起來似乎增加了複雜性,但沒有真正處理很多問題,因爲我仍然有比使用它們的函數更高的範圍的變量。或者,我可以將這三個值傳遞給每一個需要它們的函數,但這也是很多沒有增加價值的參數。所以我開始想知道,這個地方全球變量真的是正確的答案嗎?他們的存在表明,必須有某種情況下應該使用它們,而這正開始感覺到這種情況。全局變量用例

+0

隨着全局變量的命名成爲一個關鍵因素。你給了什麼名字的三個全局變量? –

回答

5

在特定場景中使用全局變量沒有任何問題,特別是對於一次定義的全局設置或單例對象,然後在整個餘下的代碼中使用,無需進一步修改。關鍵是要避免更改變量。

你應該使用全局變量是運輸狀態,即改變的值。如果您在代碼中的不同位置更改全局變量的值,則排除故障成爲後面的巨大痛苦,因爲您將信息傳遞到常規「通道」(參數,返回值)之外。如果您需要在代碼的其他地方修改全局變量,那麼實際上總是表明您應該重新評估您的架構。

+0

我認爲這是事情變得粘滯的地方,因爲那個行動肯定會改變。也許我需要着眼於處理不同的行爲,其餘的使用全局常量。我正在做一個大的重構,所以現在是時候重新思考了,那是肯定的。 也就是說,一對Set-Action&Get-Action函數是否解決了這個問題,還是真的被認爲是同一個問題的一個變種?基本上我會將Action設置爲Remove,循環執行一系列任務,設置爲Rollout,循環,設置爲Conform並循環。 – Gordon

2

使用動態範圍界定

的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全球變量,而不是他們的自由變量誰的範圍尚未確定。在運行時,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)