43

我們開發人員編寫的大部分應用程序需要在啓動時進行外部參數化。我們通過文件路徑,管道名稱,TCP/IP地址等。到目前爲止,我一直在使用命令行將這些傳遞給正在啓動的應用程序。我必須解析main中的命令行,並將參數引導到需要的地方,這當然是好設計,但是很難爲大量參數維護。最近我決定使用環境變量機制。它們是全球性的,並且從任何地方都可以訪問,這從不太優雅從架構的角度來看,但是限制了代碼量參數傳遞策略 - 環境變量與命令行

這些是我對這兩種策略的第一次(也可能是很淺的)印象,但我希望聽到更有經驗的開發人員的意見 - 使用環境變量和命令行參數傳遞參數的起伏是什麼到一個過程?我想考慮到以下事項:

  1. 設計質量(柔韌性/可維護性),
  2. 存儲器約束,
  3. 溶液可移植性。

備註:

廣告。 1.這是我感興趣的主要方面。

Ad。 2.這是有點實用的。我知道在Windows上有一些限制,這些限制目前是huge(對於命令行和環境塊都超過32kB)。我想這不是一個問題,因爲如果你需要的話,你應該使用一個文件來傳遞大量的參數。

Ad。 3.我對Unix幾乎一無所知,所以我不確定這兩種策略是否與Windows一樣可用。如果你願意,請詳細說明。

+0

你會提供更多細節,如參數的實際數量?如果有分組給他們,或者他們都是隨機的?這是什麼語言? Java,C++等...我要求詳細程度的原因是,儘管用任何語言處理這個問題都可能是個問題,但可能有一個您不知道的語言實現特定解決方案。 –

+0

只是提到* nix操作系統,他們沒有像「全局環境變量」,並且每個env var在fork時間從父進程繼承到子進程。所以,「全局」並不是一個用於env var over命令行的專業版,至少對於那些操作系統來說。 – shr

+0

嗨,@ jamesDrinkard。我對一般方法感興趣。如果您想從由32位解釋器運行的Python腳本向使用C++編寫的64位應用程序傳遞20個不同的帶標籤的字符串/整數/實數參數,您將使用哪種方法? –

回答

45

1)我建議儘可能避免使用環境變量。環境變量

  • 容易使用,因爲他們在任何地方看到的

    優點。如果很多獨立程序需要一些信息,這種方法更加方便。

缺點環境變量

  • 困難的,因爲他們是從任何地方可見(刪除-能,集能)正確使用的。如果我安裝一個依賴環境變量的新程序,他們是否會踩踏現有的程序?我昨天在兜風時,是不是在無意中搞砸了我的環境變量?

我的意見

  • 使用命令行參數,用於那些最有可能成爲該計劃的每一個人調用不同的參數(即正爲其計算n程序!)
  • 使用配置文件的參數,用戶可能會合理想要更改,但不是很經常(即彈出窗口時的顯示大小)
  • 節省使用環境變量 - 最好只適用於預期的參數不要改變(即Python解釋器的位置)
  • 貴點They are global and accessible from anywhere, which is less elegant from architectural point of view, but limits the amount of code讓我想起理使用全局變量的;)

我的傷疤,從經歷的第一手環境變量過度的恐怖

  • 我們在工作中需要的兩個程序,由於環境衝突而無法同時在同一臺計算機上運行
  • 具有相同名稱但具有不同錯誤程序的多個版本 - 兄弟因爲該計劃的位置被從環境中拉出來,並且(默默地,巧妙地)錯誤,所以整個研討會都跪了好幾個小時。

2)限制

如果我推在命令行還能持有什麼,或者什麼環境可以處理的極限,我會立刻重構。

我以前使用過JSON來處理需要很多參數的命令行應用程序。能夠使用詞典和列表以及字符串和數字非常方便。該應用程序只需要幾個命令行參數,其中之一就是JSON文件的位置。這種方法的

優勢

  • 沒有寫很多的(痛苦)的代碼與一個CLI庫進行交互 - 它可以是一個痛苦得到許多常見的庫中執行復雜的約束(通過'複雜'我的意思是比檢查特定的密鑰或在一組密鑰之間進行更復雜的操作)
  • 不必擔心CLI庫對參數順序的要求 - 只需使用JSON目的!
  • 容易表示複雜數據(回答What won't fit into command line parameters?)如列表
  • 容易使用來自其它應用程序的數據 - 包括創建和編程方式解析
  • 易於適應未來的擴展

注意:我想區分這與.config文件方法 - 這不是用於存儲用戶配置。也許我應該將這稱爲'命令行參數文件'方法,因爲我將它用於需要大量不適合在命令行上使用的值的程序。


3)解決方案的便攜性:我不知道一大堆關於關於環境變量和命令行參數的Mac,PC和Linux之間的區別,但我可以告訴你:

  • 所有三個有環境變量
  • 它們都支持命令行參數

是的,我知道的支持 - 這是不是非常有幫助。對不起。但關鍵是,你可以可以期望一個合理的解決方案是可移植的,雖然你肯定會想要驗證你的程序(例如,命令行參數在所有平臺上的任何平臺上是否區分大小寫?我不'不知道)。


最後一點:

正如托馬斯提到,它不應該的問題,以最其中的參數是從哪裏來的應用程序。

+0

謝謝,馬特。這是我一直在尋找的一種觀點。你最重要的一條建議是爲執行環境描述使用環境變量,它幾乎不會改變,而cmd-file用於實際執行簡單/複雜的參數傳遞。非常理性,謝謝。但請注意,您可以使用「局部」環境變量,這些變量只會弄亂子進程。這與命令行參數傳遞非常相似,除了Raymond在Tomasz的回答中指出的內容。 –

+1

非常好的答案!關於環境變量可以從任何地方更改的缺點:也可以從應用程序的啓動腳本(例如Bash或批處理腳本)在本地設置環境變量。在這種情況下,可以有一個系統範圍的默認值,但是如果需要,應用程序可以將默認值更改爲自定義值。你對此有何看法? – Lii

+0

考慮如何通過祕密/憑證時是否有任何優點和缺點? – iamyojimbo

3

您應該使用Strategy模式抽象讀取參數。創建名爲具有readConfig(key) -> value方法(或返回一些Configuration對象/結構)與以下實現ConfigurationSource一個抽象:

  • CommandLineConfigurationSource
  • EnvironmentVariableConfigurationSource
  • WindowsFileConfigurationSource - 從配置文件加載從C:/Document and settings...
  • WindowsRegistryConfigurationSource
  • NetworkConfigrationSource
  • UnixFileConfigurationSource - - 從配置文件加載/home/user/...
  • DefaultConfigurationSource - 默認
  • ...

您還可以使用Chain of responsibility模式在各種配置鏈來源,如:如果沒有提供命令行參數,儘量環境變量,如果一切都失敗了,返回defauls。

Ad 1.此方法不僅可以讓您抽象讀取配置,而且可以輕鬆更改底層機制,而不會對客戶端代碼產生任何影響。此外,您可以同時使用多個數據源,回退或從不同來源收集配置。

廣告2.只要選擇適合的實施方式。當然一些配置條目不適合例如命令行參數。

Ad 3.如果某些實現不是可移植的,則有兩個,一個在不適合給定系統時被忽略/跳過。

+0

謝謝,這通常是一個好主意。但是這對決定是否使用環境或命令行沒有幫助。詳細闡述你的Ad.2。的某些配置條目將不適合例如命令行參數',這會有所幫助。什麼不適合一個字符串?如果它不適合,它應該可能間接通過某種文件傳遞,不是嗎? –

+0

我的觀點是:不要強制用戶使用命令行參數**或**環境變量。靈活(並保留可維護的代碼)。我相信配置文件是存儲配置的最佳位置(它可以是任意長的,包含註釋等),但有時使用命令行參數覆蓋文件配置很有用。什麼不適合命令行參數?如果你需要傳遞幾個文件路徑,它可能會工作,但沒有人喜歡過長的命令行。 –

+0

配置文件是最好的參數 - 這是寶貴的意見和支持評論是使用它的一個很好的理由,謝謝。如果從批處理腳本啓動應用程序時使用環境變量,則可以使用['rem'](http://technet.microsoft.com/en-us/library/bb490986.aspx)和[ 'set'](http://technet.microsoft.com/en-us/library/bb490998.aspx)。如果你正在產生一個過程,你只需'在'產卵'之前'想要什麼。它方便,可讀和靈活。爲什麼要使用.config而不是環境? _那就是問題._ –