将配置传递给与应用程序无关的模块的最佳方法是什么?
我正在开发一个由多个模块组成的应用程序,这些模块也将在其他应用程序中使用。 每个模块都需要一些配置选项,但不应该知道其他模块的选项,也不应该要求其他模块存在。 一些设置在模块之间共享。
假设模块 A 需要设置 x 和 y,模块 B 需要设置 y 和 z。
设置存储在注册表或一个或多个 .ini 文件中。
到目前为止,我已经考虑了以下方法:
- 有一个全局单元(“global.pas”) 包含在所有模块中并且 包含全局变量 设置。 我不喜欢这种方法 非常因为它需要 所有应用程序都有这样一个单元 势必会收集大量 与此无关的附加代码 与最初的目的做。 所以 最终每个应用程序都会 有自己不兼容的全局 单元。
- 每个模块都有配置类,其中包含该模块所需的所有设置。 它们从应用程序中的某个中心点传递到模块中,该应用程序还处理将它们读取和写入某种永久形式(例如使用 JvAppStorage)。 这需要模块之间进行一些同步,因为某些选项将在它们之间共享,因此如果在一个模块中更改选项,则此更改必须以某种方式反映在另一个模块的配置中(不一定是实时的,而是下一次模块已初始化)。
- 有一个传递给每个模块的通用配置类,其中包含所有模块的设置作为属性。 每个模块仅访问它知道的那些设置。 这里的问题可能是名称冲突可能会发生而不被注意到。 另外,我不喜欢传递模块不需要的配置选项的想法。 此外,每个应用程序将包含不同的模块子集,但最终将包含相同的配置类以及所有可能模块的选项。 (这与上面的全局单元方法没有太大不同。)
- 有一个传递给每个模块的通用配置类,如上所示。 但模块没有属性,而是通过名称访问其设置(在最简单的情况下,这可能是 TCustomIniFile)。 这避免了在所有应用程序中都可用的所有模块的设置,但引入了可能的类型兼容性问题,并且名称冲突可能再次成为问题(除非每个模块都以其名称作为其选项的前缀,但随后它们不能再共享选项)。
我想每个编写模块化系统的人都遇到过这个问题,并找到了一些他们后来坚持的解决方案,无论他们是否仍然喜欢它们。 我也去过那里好几次,并且仍在寻找金子弹。
也许其他人已经找到了理想的解决方案?
(这是 Delphi 2007,以防万一。我已经在使用 JCL / JVCL。)
I am working on an application that consists of several modules which in turn will be used in other applications as well. Each of these modules needs some configuration options, but should not be aware of the options of other modules, and also should not require other modules to exist. Some settings are shared between modules.
Lets say Module A requires settings x and y, Module B requires settings y and z.
Settings are stored either in the registry or in one or more .ini files.
So far I have considered the following approaches:
- Have a global unit ("global.pas")
that is included in all modules and
contains global variables with the
settings. I don't like this approach
very much because it would require
all applications to have such a unit
and it is bound to collect lots of
additional code that has nothing to
do with the original purpose. So
eventually each application will
have its own incompatible global
unit. - Have configuration classes for each module that contain all the settings required for that module. These are passed into the module from some central point in the application which also handles reading and writing them to some permanent form (e.g. use JvAppStorage). This requires some synchronisation between the modules because some options will be shared between them, so if the option is changed in one module, this change must somehow be reflected in the configuration of another module (not necessarily in real time but the next time the module is initialized).
- Have a generic configuration class that is passed to each module and that contains the settings for all modules as properties. Each module accesses only those settings it knows about. The problem here might be that name clashes can occur whithout being noticed. Also I don't like the idea of passing configuration options around that are not necessary for a module. In addition, every application will contain a different subset of modules but would end up containing the same configuration class with the options for all possible modules. (This isn't very different from the global unit approach above.)
- Have a generic configuration class that is passed to each module, like above. But instead of having properties, the modules access their settings by name (in the easiest case this could be a TCustomIniFile). This avoids having settings for all modules available in all applications, but introduces possible type compatibility problems and again, name clashes may become an issue (unless each module prefixes its options with its name, but then they can no longer share options).
I guess everybody who wrote a modularized system has faced this issue and found some solutions they later on were stuck with, whether they still liked them or not. I have been there too, several times and am still looking for the golden bullet.
Maybe somebody else has already found the ideal solution?
(This is Delphi 2007 in case it matters. I am already using the JCL / JVCL.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我可能会创建一个通用配置类,并让每个模块依赖于一个或多个单例的具体配置类。 模块依赖于具有仅对该模块重要的设置的配置类实例,并且可选地依赖于具有与多个模块相关的设置的一个或多个其他配置类实例。 由于配置对象是单例,共享配置对象的模块会自动获得相同的设置。
您将根据功能而不是根据模块使用情况来创建配置类。 模块使用的功能暗示了它需要哪些配置对象。
添加到应用程序的每个模块都会添加所有所需的配置类作为依赖项,而不会添加其他配置类。 单例配置对象在应用程序启动时将自身添加到此类对象的列表(或注册表,如果您愿意的话)。 应用程序本身不需要了解细节,只需从持久存储加载和保存设置就足够了。 如果需要,它可以使用相同的基础设施。
一般来说,我会根据接口来实现所有内容,并将持久性机制留在外面。 因此,您稍后可以自由地在 INI 文件、注册表甚至数据库中进行配置(这将为您提供一种实现配置更改历史记录的简单方法)。 我发现自从我开始针对接口而不是类的层次结构进行编程以来,我并没有将自己过多地限制在某种做事方式中。
I would probably create a generic configuration class, and have each module depend on one or several concrete configuration classes that are singletons. A module depends on a configuration class instance with settings that are significant for that module only, and optionally on one or more other configuration class instances with settings that pertain to more than one module. Due to the fact that the configuration objects are singletons the modules that share configuration objects automatically get the same settings.
You would create the configuration classes according to functionality, not according to module usage. The functionalities a module uses implicate which configuration objects it will need.
Every module that gets added to an application adds all the needed configuration classes as dependencies, other configuration classes are not added. The singleton configuration objects add themselves to a list (or registry if you will) of such objects on application startup. The application itself does not need to know about details, just loading and saving the settings from and to persistent storage is enough. It can OTOH make use of the same infrastructure if it needs to.
Generally I would implement everything in terms of interfaces, and leave the persistence mechanism outside. Thus you would be free later on to have configurations in INI files, the registry, or even a database (which would give you a simple way of implementing a history of configuration changes). I have found that I have not locked myself that much into a way of doing things since I started programming against interfaces instead of hierarchies of classes.
我曾经有过这样的应用程序(用 C++Builder 编写)。
我有一个基本模块 (BaseClass.BPL),所有其他模块(如 Payment.BPL)都继承自 . 因此,您可以使用基类来读取公共参数并覆盖继承的模块来读取特定设置。
我将设置保存在 INI 文件中 - 处理该注册表要容易得多。 为了避免与相似名称发生冲突,每个模块在 INI 中使用不同的部分。
I once had application like that (written in C++Builder).
I had one basic module (BaseClass.BPL) that all others (like Payment.BPL) inherited from . So you can use base class to read the common parameters and overwrite the inherited modules to read specific settings.
I kept settings in INI file - much easier to handle that registry. To avoid clashes with similar names each module used different section in INI.