一个人应该如何管理多种语言的常量?


13

我遇到的情况是我在功能上支持多种语言的同一库。这些常量之间通常需要共享常量(例如,json字段名称键或错误代码)。

我目前这样做的方式是让代码定义每种语言的常量。

问题来自维护。如果添加新的错误代码,则需要在每个库中手动更新它。虽然这对几个人来说很好,但是如果我说要更新5个SDK,就变得很乏味。也有一个单一的真理来源真是太好了。

我已经考虑过某种类似config的文件,但是它需要包含在每个已部署的软件包中,这会增加我们的构建/发布过程的复杂性。

有没有更好的方法来处理在多种语言之间共享的常量的维护?


恩德兰,你的方法很好。我试图找到一种更好的重新定义解决方案,因为很多时候很多客户端都在使用我编写的API,而实际上并没有一个优雅的解决方案。常量重新定义仍然是最直接的。
安迪

5
@DavidPacker不,不,不,您应该为我提供一个非常优雅的解决方案。不要告诉我这是最好的!:-)
enderland

1
我当时在质疑自己的选择,但后来意识到常量就是常量。它们是可预测的,因为它们是恒定的。通过将它们存储为JSON或其他任何通常可解析的格式,它们不再是常量。在我的工作流程中,一个典型的示例是一个通知对象,其中包含一个type属性,该属性用于在通过导线传输结构时进行结构识别。有了这个,移动客户端只定义他们当时可以理解的常量(类型),而忽略任何未知类型。动态定义会引起很多问题。
安迪

您需要一个表表,这些表映射到语言表中的常量行。
约翰尼

Answers:


10

尽管我认为您当前的方法可能是最简单,最直接的方法,但是这里有一些替代方法:

  • 将常量(也许是模型)提取到交叉编译为所有语言的其他程序包中。您也许可以交叉编译整个库,但这可能会带来很多问题。只是交叉编译常量应该足够简单,以免出现太多问题。您可以发布常量包,并在特定于语言的库中依赖它。Haxe可以做到。这种方法很好,因为您仍然需要进行编译时检查(对于已编译的语言)
  • 将配置存储在中央服务中。例如,肥皂网络服务具有Web服务描述语言(WSDL),而REST服务具有Web应用程序描述语言(WADL),用于描述服务的操作和消息。还有一些通用的集中式配置服务,例如Spring Cloud Config
  • 配置文件。我知道您已经提出了建议,但是我认为它并不需要使您的构建/发布过程变得非常复杂。将您的配置文件放在一个单独的构建项目中(可以在其中进行版本控制)。将项目发布到所有特定语言的软件包存储库(Maven,Nuget,NPM等),然后在特定语言的库中可以依赖于软件包。这不应该比在构建管道中包含其他项目更复杂。
  • 正如RubberDuck所建议的那样,代码生成是交叉编译的一个很好的选择。您可以使用通用配置为每种语言生成常量定义。

5
@RubberDuck代码生成听起来很有趣(特别是对于我的一个切向用例之一,无论如何,它已经涉及到代码生成器了)。
enderland '17

3

好问题!我有同样的问题;我的常量本质上是:我的应用程序支持哪些语言,以及与这些语言有关的附加信息(与应用程序的功能有关)。

不幸的是,我发现的(正如您所拥有的)最好的是,就像您当前正在做的那样,简单地为每种语言重新定义常量(我知道,您一定想听听)。

显然,这是错的,因为它与DRY(WET ??)相反。但是,常量应该很少更改,以至于5-10分钟的时间为每种语言重新定义它们并不会真正困扰我。归根结底,某些“优雅”解决方案(如共享配置或代码生成)的小问题可能需要数小时或数天才能解决,那么,真正获得了什么呢?我要处理的不是增加的复杂性,而有发生错误的风险,可能需要付出更多的努力才能解决。

此外,如果您的应用程序具有如此多的常量,以至于在添加或更改它们时每种语言重新定义它们都需要花费大量时间,那么您可能只需要处理更重要的代码味道,此时,您可能需要转向到更复杂的东西。

简而言之,为每种语言重新定义它们是我最好的解决方案,而且我还没有想到任何DRY不会带来比我要处理的风险更大的风险因素。

但是,绝对要做的一件事是确保以通用(且与语言无关)的方式很好地记录您的常量(我们有公司文档回购,其中包含规范,其他文档,“绘图”文档等)这个文件)。还要确保您有适当的机制来使它们的定义保持同步。与复制方法一样,这与您将面临的问题一样大,除了有意的代码复制造成的少量心理困扰。但是最后,您的不断更改应该是非常有意很少发生的,因此同步性问题基本上应该是零。


我还要提到的是,多年来,我看到同一个小组编写的各种库的多语言端口(实在很难记住它们的当前含义),这些端口总是在语言本身中定义了常量。没有共享的配置,没有代码生成(除了Google API客户端库...,但是,谷歌有能力负担这种复杂性)。所以我认为我们已经在这堵砖墙上撞了。也许有人最终会想出一个图书馆来解决这个问题;)


0

希望您的库的核心使用一种语言编写,而其他库使用FFI(https://en.wikipedia.org/wiki/Foreign_function_interface)来调用核心库。这将为您提供中心位置,以提供一个API来发布常量和定义。这样,所有内容都将自包含在库中。我仅提及这一点,因为它似乎并未包括在塞缪尔的回应中。

我认为这实际上取决于您的用户群的能力。是否有足够的能力来处理其他配置文件的传递?他们有能力设置新服务吗?对于我所支持的绝大多数用户,我希望所有内容都是独立的-这样用户就不必考虑了。


1
Hopefully, the core of you library is written in one language, and the other libraries use FFI 不幸的是,我们同时拥有用于Web客户端和服务器代码的库(多种语言),因此...推出并不是一件容易的事(如果可以在Web应用程序中开始的话,可能是一个安全漏洞)。
enderland

我建议您提高安全性,因为我永远不会信任我的用户足够保密配置文件。
罗伯特·巴伦

如何部署处理错误代码的Web应用程序?还是JSON字段名称?您认为我正在执行的操作感到困惑,这是一个安全问题。在我的客户端计算机上运行任意代码绝对是一个安全问题,除非我遗漏了某些东西,否则允许他们从服务器解析json似乎不是。
enderland '17

我在公司工作过,这些公司的安全基础是DOS样式的随机数生成器和作为常量存储的种子值。在指出这些问题后,往往会很快修复它们。但是,如果您将种子价值发布给世界,那么您将失去了王国的钥匙。由于您的软件似乎主要是基于Web的,因此将配置保留在JSON对象中,并让每种语言都解析相同共享文件。
罗伯特·巴伦

JSON字段名称可能不是而且不需要保持不变。这些字段名称需要更改的可能性是什么,但是您不更改常量本身的名称呢?生成代码来访问条目或使用诸如ObjectPath之类的表达语言,您可能会更有可能受益。
Lie Ryan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.