4

我正在使用一種工具來自動生成分層組織的XML文件的類表示。 XML文件是我的應用程序需要能夠訪問的設置文件(只讀)。我應該注意傳遞XML設置文件的類表示是否違反了demeter的規律?

如果我通過在頂級節點(例如,AppSettings)到需要訪問一個或多個設置的課,我可以很容易地結束了代碼看起來是這樣的:

var windowSize = AppSettings.Views.Windows.Dashboard.Size; 

這似乎嚴重違反了德米特法,但我想知道我是否應該在意。我可以付出巨大的努力,只通過每個班級所需的準確設置,但在這種情況下,我很難看到這些多點會如何傷害我。

我的代碼是緊密耦合到未來可能產生的維護問題或其他問題我的XML文件格式,或這是它有意義的不是宗教遵循OOP設計原則的例子嗎?

回答

6

是的,你應該在乎,爲了一個非常實用的理由!

您想要使用設置的類絕對不需要依賴於這些設置的存儲方式。

想象一下您將來希望支持您的應用程序的多個主題。你將最終不是一個,而是很多可能性爲您的儀表板的尺寸,例如:

AppSettings.Views.ThemeA.Windows.Dashboard.Size; 
AppSettings.Views.ThemeB.Windows.Dashboard.Size; 

你的UI類仍然只需要一個東西,它的變量windowSize的值,它並不需要知道哪些主題目前被使用。

無論您擁有哪種XML接口,您都不希望依賴於代碼中的任何位置的模式,而只能在一箇中心位置。

例如,你可以把設置在一個Map內部使用,如:

public class SettingsReader { 

    public static final String VIEW_WINDOW_DASHBOARD_SIZE = "Views.Windows.Dashboard.Size"; 

    private Map settings = new Hashmap(); 

    public SettingsReader(AppSettings appSettings) { 
     settings.put(VIEW_WINDOW_DASHBOARD_SIZE, appSettings.Views.Windows.Dashboard.Size); 
    } 

    public String getSettingValue(String key) { 
     return settings.get(key); 
    } 
} 

然後你只需要一個地方來重構,以支持一個主題,像這樣:

public class SettingsReader { 

    public static final String VIEW_WINDOW_DASHBOARD_SIZE = "Views.Windows.Dashboard.Size"; 

    private Map settings = new Hashmap(); 

    public SettingsReader(AppSettings appSettings, String theme) { 
     settings.put(VIEW_WINDOW_DASHBOARD_SIZE, appSettings.Views + theme + Windows.Dashboard.Size); 
    } 

    public String getSettingValue(String key) { 
     return settings.get(key); 
    } 
} 

最後一點,僅僅是因爲我的僞代碼和java代碼的混合可能會混淆人們,特別是appSettings.Views + theme + Windows.Dashboard.Size:使用XML接口時,xPath通常非常有用,即使在使用對象時也是如此,這要歸功於良好的庫JXPath(用於JAV a,我不知道其他語言)。

+0

感謝您的回答,達米安。 – devuxer 2010-09-20 23:15:45

1

如果你正在吐出愚蠢的數據,那麼沒有更好的方法來做到這一點。

雖然我傾向於試圖找到一種解決方案,可以推送和彈出上下文。

PushContext(AppSettings) 
    // do child contexts 
    PushContext(Views) 
    // more child contexts 
    PushContext(Windows) 
    // etc. 
    PopContext() 
    PopContext() 
PopContext() 

通常情況下,不同的推壓將是不同的功能或文件,但在此示出爲說明起見。無論如何,如果你推入Views視圖,那麼你只是解析它,就好像你在對象的根部一樣。

如果這是DumbData,那麼您也可以將「視圖」所代表的事物類型傳遞給解析它的代碼。頂級水平,你的代碼看起來像:

views.ParseSettings(AppSettings.Views); 
locale.ParseSettings(AppSettings.Locale); 
network.ParseSettings(AppSettings.Network); 

這肯定會是從LOD POV「清潔劑」,但它可能不會是值得的,你有設置的數量。但是,對於範圍深度而言,可能意味着您有很多設置,因此將它們分解爲責任區域(用於加載和保存設置)可能是明智的。

+0

我想我所擁有的將被視爲DumbData。我通常使用非常小的設置文件,通常5-25個設置。 – devuxer 2010-09-11 04:30:35

0

自動世代可能是大項目的一個難題。

如果您將使用一個地方生成的代碼(例如一個包),也許沒有問題。

如果你會使用的代碼:

var windowSize = AppSettings.Views.Windows.Dashboard.Size; 

在很多地方,你可能需要隱藏一些這種耦合對AppSettings製作方法:

getSize() { 
    return Views.Windows.Dashboard.Size; 
} 

但是,如果你我們需要爲所有課程做到這一點,也許這不是可行的。

最好的決定取決於你的項目(如果它打算種植),你有時間去做,規模和產生的代碼量。

1

所有的事情都是相對的,它取決於項目的大小以及是否關心維護。

如果您關心維護,那麼您不希望強制配置源對您的其他代碼庫施加任何限制。

實現此目的的最佳方法是編寫接口並隱藏您的實現。這樣,你的代碼與你的配置接口有一個契約,並不關心實際配置如何加載。

public interface IConfiguration 
{ 
    Size ViewSize { get; } 
} 

public class AppSettingsConfiguration : IConfiguration 
{ 
    public Size ViewSize 
    { 
      return AppSettings.Views.Windows.Dashboard.Size; 
    } 
} 

然後所有的消費代碼都應該根據IConfiguration接口進行編碼。這意味着您可以在最小影響的情況下改變檢索配置的方式。

相關問題