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

相關問題