1

我正在处理的系统可以用不同的布尔属性进行配置。不同配置的理论最大值为2^n,其中n是此类属性的数量。如何组织和加载基于包的可配置属性?

有一个配置工具与生产代码分开,它使用布尔表达式来选择加载哪些代码包。 该工具包含一个类,该类定义了像isWithX或更复杂的方法,如isWithXwithoutYwithZ。 包基本上是定义或重新定义某些方法定义的类扩展列表。 今天的软件包被命名为myPackageWithAWithoutBwithCwithDwithoutE

由于布尔配置属性数量不断增加,不同软件包的数量和名称的大小变得非常荒谬,我们无法一直滚动查看它们的名称。 还有很多代码重复。

编辑:自生产代码具有可配置性的问题是目前仅限于这些问题没有访问:

  • 为每个包的包名称的列表,每个功能
  • 多少方法以及如何它们命名为

眼下的包名称的列表是基本的名字像这样的所有不同的组合:除了那些没有行为特定于该配置,我们需要牛逼myPackageWithAWithoutBwithCwithDwithoutE o实施。

现在为每个包和每个功能:每个包1个方法的功能名称。

+1

您是否允许更改软件包名称?也就是说,你是否允许只有n个包都定义了包含('myPackageWithX'),然后将这些包与你的配置相匹配? –

+0

from myPackageWithXwithoutY and myPackageWithXwithY我可以创建一个名为myPackageWithX的“父”包,并删除一些重复内容,但我无法删除所有子包内容,除非我使用if语句或父类中的某个内容。 – Rivenfall

回答

3

我无法告诉您如何解决您的具体问题,因此我会与您分享一些提示,这些提示可能有助于您开始寻找实际适用于您的设计。

考虑配置对象的层次结构:

ConfigurationSettings 
    ApplicationSettings 
    UserSettings 
    DisplaySettings 
    ... 

抽象类ConfigurationSettings提供基本服务,以读取属于任何特定的部分 /写设置。该层次允许更简单的命名约定,因为选择器可以在不同的子类中重新实现。

ApplicationSettings子类起到不同的作用:它注册的所有部分在其registry实例变量,一个Dictionary,其中键是部分的名称和值对应的子类实例:

ApplicationSettings current register: anEmailSettings under: `Email` 

抽象类提供读写设置的基本服务:

settingsFor: section 
settingAt: key for: section 
settingAt: key for: section put: value 

子类使用这些服务来访问各个设置并实现所需的逻辑客户端测试当前的配置是否为is,has,supports等,特定功能或组合。这些更具体的方法是根据更基本的settingAt:for:来实施的。

当一个新的包注册其自己的子类如下的测试方法可用:

self <section>Settings isThisButNotThat 

,其中例如,

emailSettings 
    ^(ApplicationSettings current for: 'Email') isThisButNotThat 

,同样用于其他任何部分。正如我上面提到的,子类中的分区将允许您更简单的选择器隐式引用该部分(#isThisButNotThat而不是#isEmailThisButNotThat)。

另外一个功能,重要的是要支持应用/取消对话框,为用户修改设置是通过两种方法提供:

ConfigurationSettings >> #readFrom: 

ConfigurationSettings >> #writeOn: 

所以,当你打开GUI显示的设置你不打开它在当前的实例,但在它们的副本上

settings := ApplicationSettings new readFrom: ApplicationSettings current. 

然后在GUI中将此副本呈现给用户。如果用户取消对话框,您只需忘记该副本。否则,你将更改应用这种方式:

settings writeOn: ApplicationSettings current 

这两种服务的实施遵循一个简单的模式:

ApplicationSettings >> readFrom: anApplicationSettings 
    registry keysAndValuesDo: [:area :settings | | section | 
    section := anApplicationSettings for: area. 
    settings readFrom: section] 

ApplicationSettings >> writeOn: anApplicationSettings 
    registry keysAndValuesDo: [:area :settings | | settings | 
    section := anApplicationSettings for: area. 
    settings writeOn: section] 
0

我不完全了解所有的你的问题的方面,但也许你可以使用动态的方法。例如,您可以覆盖#doesNotUnderstand:解析发送到配置选择和提取包名:

doesNotUnderstand: aMessage 
| stream included excluded | 
"parse selectors like #isWithXwithoutYwithoutZ" 
stream := (#isWithXwithoutYwithoutZ allButFirst: 6) asLowercase readStream. 
included := Set new. 
excluded := Set new. 
[ stream atEnd ] whileFalse: [ 
    (stream peek: 3) = 'out' 
     ifTrue: [ 
      stream next: 3. 
      excluded add: (stream upToAll: 'with') ] 
     ifFalse: [ included add: (stream upToAll: 'with') ] ]. 

然后,你需要的是多一点的代码来生成包从该列表中(我希望) 。

+0

这种包名不应该首先存在,我正在寻找框架的不同设计。如果我不关心表演和团队合作,我可以使用doesNotUnderstand,正则表达式,动态编译的方法等方法来破解某些类型的作品,但我甚至不允许使用if语句 – Rivenfall

+1

。你能为你的问题添加更多细节吗?例如:什么是合法修改,它们可以在哪里制作?你的目标是什么(例如,摆脱那些软件包名称)? –

+0

现在我简化了这个问题,我明白了为什么我不能使用if语句 – Rivenfall

相关问题