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而不是环境? _那就是问题._ –