Должен ли я заботиться о том, чтобы передача в представлении класса файла настроек XML нарушала закон Деметры? - PullRequest
4 голосов
/ 11 сентября 2010

Я использую инструмент для автоматического создания представления класса иерархически организованного XML-файла.XML-файл - это файл настроек, к которому мое приложение должно иметь доступ (только для чтения).

Если я передаю узел верхнего уровня (например, AppSettings) в класс, к которому требуется доступодна или несколько настроек, я легко могу получить код, который выглядит примерно так:

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

Это кажется серьезным нарушением закона Деметры, но мне интересно, стоит ли мне беспокоиться.Я мог бы приложить огромные усилия, чтобы передать только точные настройки, которые мне нужны для каждого класса, но у меня возникают проблемы, когда я вижу, как эти множественные точки могут повредить мне в этом случае.

тесно связывает мой код смой формат файла XML может вызвать проблемы с обслуживанием или другие проблемы в будущем, или это пример, в котором имеет смысл не религиозно следовать принципу разработки ООП?

Ответы [ 4 ]

6 голосов
/ 15 сентября 2010

Да, вы должны заботиться по очень прагматичной причине!

Классы, в которых вы хотите использовать свои настройки, абсолютно не должны зависеть от способа хранения этих настроек.

Представьте себе, что в будущем вы хотите поддерживать несколько тем для своего приложения. В итоге вы получите не одну, а множество возможностей для вашего размера панели, например:

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

Вашему классу пользовательского интерфейса все еще нужна только одна вещь, значение для его переменной windowSize, ему не нужно знать, какая тема используется в настоящее время.

Это правда, где бы у вас не был интерфейс XML, вы не хотите зависеть от схемы везде в вашем коде, но только в одном центральном месте.

Например, вы можете поместить настройки в Карту для внутреннего использования, например:

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 (для java я не знаю других языков).

1 голос
/ 17 сентября 2010

Все относительно, это действительно зависит от размера проекта, и если вы заботитесь о техническом обслуживании.

Если вы заботитесь о техническом обслуживании, тогда вы не хотите вводить какие-либо ограничения, налагаемые вашей конфигурацией.исходный код остальной части вашей кодовой базы.

Лучший способ добиться этого - кодировать интерфейсы и скрывать за этим свою реализацию.Таким образом, ваш код имеет контракт с вашим интерфейсом конфигурации и не заботится о том, как загружается фактическая конфигурация.

public interface IConfiguration
{
    Size ViewSize { get; }
}

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

Затем весь код потребления должен быть закодирован в интерфейс IConfiguration.Это означает, что вы можете изменить способ получения конфигурации с минимальным воздействием.

1 голос
/ 11 сентября 2010

Если вы выплевываете глупые данные, то на самом деле нет лучшего способа сделать это.

Я бы попытался найти решение, в котором вы могли бы использовать контексты и толкать их.

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

Обычно разные Pushes бывают в разных функциях или файлах, но показаны здесь для иллюстрации. В любом случае, если вы вставляете в контекст Views, вы просто анализируете это, как будто вы находитесь в корне объекта.

Однако, если это DumbData, вы также можете просто передать тип того, что представляет «Views», в код, который его анализирует. На верхнем уровне ваш код будет выглядеть так:

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

Это, безусловно, будет "чище" по сравнению с LOD POV, но оно может не стоить того количества настроек, которое у вас есть. Однако, учитывая глубину области действия, возможно, это означает, что у вас много настроек, поэтому целесообразно разделить их на зоны ответственности (для загрузки и сохранения настроек).

0 голосов
/ 14 сентября 2010

Автоматические поколения могут быть проблемой для больших проектов.

Если вы будете использовать сгенерированный код из одного места (например, из одного пакета), возможно, проблем нет.

Если вы воспользуетесь кодом:

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

во многих местах вы можете захотеть скрыть некоторые из этих связей, создавая метод на AppSettings:

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

Но если вам нужно сделать это для всех классов, возможно, это нежизнеспособно.

Лучшее решение зависит от размера вашего проекта (и если он намеревается расти), времени, которое вы должны сделать, и количества сгенерированного кода.

...