Как лучше всего передать конфигурацию модулям, независимым от приложений? - PullRequest
1 голос
/ 27 января 2009

Я работаю над приложением, состоящим из нескольких модулей, которые, в свою очередь, будут использоваться и в других приложениях. Каждый из этих модулей нуждается в некоторых параметрах конфигурации, но не должен знать о параметрах других модулей, а также не должен требовать наличия других модулей. Некоторые настройки являются общими для модулей.

Допустим, для модуля A требуются настройки x и y, для модуля B требуются настройки y и z.

Настройки хранятся либо в реестре, либо в одном или нескольких файлах .ini.

Пока я рассмотрел следующие подходы:

  1. Иметь глобальную единицу ("global.pas") который включен во все модули и содержит глобальные переменные с Настройки. Мне не нравится этот подход очень много, потому что это потребовало бы все приложения имеют такой блок и он обязан собрать много дополнительный код, который не имеет ничего делать с первоначальной целью. Так в конечном итоге каждое приложение будет иметь свой собственный несовместимый глобальный блок.
  2. Иметь классы конфигурации для каждого модуля, которые содержат все параметры, необходимые для этого модуля. Они передаются в модуль из некоторой центральной точки приложения, которая также обрабатывает их чтение и запись в некоторой постоянной форме (например, использует JvAppStorage). Это требует некоторой синхронизации между модулями, потому что некоторые параметры будут совместно использоваться ими, поэтому, если параметр изменяется в одном модуле, это изменение должно как-то отражаться в конфигурации другого модуля (не обязательно в режиме реального времени, но в следующий раз, когда модуль инициализируется).
  3. Иметь общий класс конфигурации, который передается каждому модулю и содержит настройки для всех модулей в качестве свойств. Каждый модуль имеет доступ только к тем настройкам, о которых он знает. Проблема здесь может заключаться в том, что конфликты имен могут происходить без замечаний. Также мне не нравится идея передачи параметров конфигурации, которые не нужны для модуля. Кроме того, каждое приложение будет содержать разные подмножества модулей, но в конечном итоге будет содержать один и тот же класс конфигурации с опциями для всех возможных модулей. (Это не очень отличается от глобального подхода к единице, описанного выше.)
  4. Иметь общий класс конфигурации, который передается каждому модулю, как указано выше. Но вместо того, чтобы иметь свойства, модули получают доступ к своим настройкам по имени (в простейшем случае это может быть TCustomIniFile). Это позволяет избежать установки параметров для всех модулей, доступных во всех приложениях, но приводит к возможным проблемам совместимости типов и, опять же, конфликты имен могут стать проблемой (если каждый модуль не префиксирует свои параметры своим именем, но тогда они больше не могут совместно использовать параметры). *

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

Может, кто-то другой уже нашел идеальное решение?

(Это Delphi 2007 на случай, если это имеет значение. Я уже использую JCL / JVCL.)

Ответы [ 2 ]

3 голосов
/ 27 января 2009

Я бы, вероятно, создал общий класс конфигурации, и каждый модуль зависел бы от одного или нескольких конкретных классов конфигурации, которые являются синглетонами. Модуль зависит от экземпляра класса конфигурации с настройками, которые важны только для этого модуля, и, необязательно, от одного или нескольких других экземпляров класса конфигурации с настройками, которые относятся к более чем одному модулю. В связи с тем, что объекты конфигурации являются единичными, модули, которые совместно используют объекты конфигурации, автоматически получают одинаковые настройки.

Вы должны создавать классы конфигурации в соответствии с функциональностью, а не в соответствии с использованием модуля. Функциональные возможности, которые использует модуль, подразумевают, какие объекты конфигурации ему понадобятся.

Каждый модуль, который добавляется в приложение, добавляет все необходимые классы конфигурации в качестве зависимостей, другие классы конфигурации не добавляются. Объекты конфигурации singleton добавляют себя в список (или реестр, если хотите) таких объектов при запуске приложения. Само приложение не должно знать о деталях, достаточно просто загрузить и сохранить настройки из и в постоянное хранилище. OTOH может использовать ту же инфраструктуру, если это необходимо.

Как правило, я бы реализовал все с точки зрения интерфейсов и оставил бы механизм персистентности снаружи. Таким образом, позже вы будете свободны иметь конфигурации в INI-файлах, реестре или даже базе данных (что даст вам простой способ реализовать историю изменений конфигурации). Я обнаружил, что с тех пор, как начал программировать с использованием интерфейсов, а не иерархий классов, я не так уж сильно привязан к способам ведения дел.

0 голосов
/ 27 января 2009

У меня когда-то было такое приложение (написано на C ++ Builder). У меня был один базовый модуль (BaseClass.BPL), от которого унаследованы все остальные (например, Payment.BPL). Таким образом, вы можете использовать базовый класс для чтения общих параметров и перезаписать унаследованные модули для чтения определенных настроек.

void PaymentForm::Readsettings()
{
   BaseClass::ReadSettings(); //to read common stuff
   IniFile->ReadString("Payment Module", "setting1,...); //read specific stuff
}

Я сохранил настройки в INI-файле - намного проще работать с этим реестром. Чтобы избежать столкновений с похожими именами, каждый модуль использовал разные разделы в INI.

[Common]
Datapath=...
Server=...

[MainModule]
setting1=..

[Payment module]
setting1=....
setting3=....
...