parameter passing策略 – 环境variables与命令行

我们开发人员编写的大部分应用程序需要在启动时进行外部参数化。 我们传递文件path,pipe道名称,TCP / IP地址等。到目前为止,我一直在使用命令行将这些文件传递给正在启动的应用程序。 我必须parsingmain的命令行,并将参数引导到需要的地方,这当然是一个好的devise ,但是很难维护大量的参数。 最近我决定使用环境variables机制。 它们是全球性的,可以从任何地方进行访问,从架构的angular度来看,它不那么优雅 ,但却限制了代码量

这些是我对这两种策略的第一个(也可能是很浅的)印象,但是我想听听更有经验的开发人员的意见 – 使用环境variables和命令行参数来将parameter passing给进程的起伏是什么? 我想考虑以下事项:

  1. devise质量(灵活性/可维护性),
  2. 内存限制,
  3. 解决scheme便携性。

备注:

广告。 这是我感兴趣的主要方面。

广告。 这有点务实。 我知道目前很大的 Windows上的一些限制(超过32kB的命令行和环境块)。 我想这不是一个问题,因为你只是应该使用一个文件来传递大量的参数,如果你需要的话。

广告。 3.我对Unix几乎一无所知,所以我不确定这两种策略是否像Windows一样可用。 如果你喜欢,请详细说明一下。

1)我build议尽可能避免环境variables。

优点环境variables

  • 易于使用,因为它们从任何地方都可见。 如果有很多独立的程序需要一个信息,这个方法就更方便了。

环境variables的缺点

  • 很难正确使用,因为它们从任何地方都可见(可删除,可设置)。 如果我安装一个依赖于环境variables的新程序,他们是否会踩踏现有的程序? 我昨天在瞎逛时,是不是偶然搞砸了我的环境变数?

我的想法

  • 对于那些对程序的每个单独调用来说最有可能不同的参数都使用命令行参数(即对于计算n的程序来说,n是)
  • 使用configuration文件的参数,用户可能会合理想要更改,但不是很经常(即显示大小,当窗口popup)
  • 谨慎使用环境variables – 最好只用于预期不会改变的参数(即Python解释器的位置)
  • 你的观点They are global and accessible from anywhere, which is less elegant from architectural point of view, but limits the amount of code我想到使用全局variables的理由;)

我亲身经历的伤疤是环境variables过度使用的恐怖

  • 我们在工作中需要两个程序,由于环境冲突,无法同时运行在同一台计算机上
  • 多个版本的程序同名,但有不同的错误 – 由于程序的位置被从环境中拉出,并且(默默地,微妙地)错误,所以整个研讨会几个小时就跪下了。

2)限制

如果我推动命令行能够控制的范围或环境能够处理的范围,我会立即重构。

我过去曾经使用过JSON作为一个需要大量参数的命令行应用程序。 能够使用字典和列表以及string和数字是非常方便的。 该应用程序只需要几个命令行参数,其中之一是JSON文件的位置。

这种方法的优点

  • 不需要编写很多(痛苦的)代码来与CLI库进行交互 – 让许多公共库执行复杂的约束是非常痛苦的(通过“复杂的”我指的是比检查特定键或一组键之间的交替)
  • 不必担心CLI库对参数顺序的要求 – 只需使用JSON对象即可!
  • 容易代表复杂的数据(回答What won't fit into command line parameters? ),如列表
  • 易于使用来自其他应用程序的数据 – 既可以通过编程来创build和parsing
  • 容易适应未来的扩展

注意 :我想将它与.config-file方法区分开来 – 这不是用于存储用户configuration的。 也许我应该把这叫做“命令行参数文件”的方法,因为我用它来做一个需要很多不适合在命令行中使用的值的程序。


3)解决scheme的可移植性:关于Mac,PC和Linux在环境variables和命令行参数方面的差异,我不太了解,但我可以告诉你:

  • 所有三个都支持环境variables
  • 他们都支持命令行参数

是的,我知道 – 这不是很有帮助。 对不起。 但关键的一点是,你可以期望一个合理的解决scheme是可移植的,虽然你一定要validation你的程序(例如,在任何平台上的命令行参数在所有平台上是否区分大小写?我不知道)。


最后一点:

正如托马斯(Tomasz)提到的那样,参数来自大多数应用程序并不重要。

你应该使用策略模式抽象阅读参数。 创build一个名为ConfigurationSource的抽象,其中包含readConfig(key) -> value方法(或返回一些Configuration对象/结构),其中包含以下实现:

  • CommandLineConfigurationSource
  • EnvironmentVariableConfigurationSource
  • WindowsFileConfigurationSource – 从C:/Document and settings...的configuration文件加载C:/Document and settings...
  • WindowsRegistryConfigurationSource
  • NetworkConfigrationSource
  • UnixFileConfigurationSource – 从/home/user/...configuration文件
  • DefaultConfigurationSource – 默认值

你也可以使用责任链模式来链接各种configuration的源代码,如:如果没有提供命令行参数,尝试环境variables,如果一切都失败,则返回默认值。

广告1.这种方法不仅可以让你抽象读取configuration,而且可以轻松地改变底层机制,而不会对客户代码产生任何影响。 您也可以同时使用多个源,从不同的来源收集或回收configuration。

广告2.只要select适合的实施。 当然一些configuration条目不适合例如命令行参数。

Ad 3.如果某些实现不是可移植的,当不适合给定的系统时,有两个,一个默默地忽略/跳过。