Хранение и вызов внутренних параметров (констант) программы

Предисловие:
Любая более менее серьезная программа имеет какие-то внутренние константы необходимые для ее работы. Часто эти константы необходимо изменять без внесения изменений в код программы. Для этого большинство юзают ini или реестр.


К примеру я в своих проектах себя приучил хранить такие константы в таком виде (если кому не понравилось сильно не пинать, ну можете положительно оценить задумку :), ниже описанное привожу скорее для новичков может кому навеет свежие мысли):
1. Храню константы (да и переменные) программы в древовидной структуре созданной с помощью Record;
2. Создаю отдельный юнит в котором описываются все типы и больше ничего:

пример

unit Unit_MyClass;

interface
uses Classes, SysUtils;
type
// куски записей основной записи настроек
TMessageRec = record        // параметры системных межпрограмных сообщений
WM_LogUpdate: Integer;
end;
//
TDB_one = record                // параметры подключаемых баз данных
DBType,
Path,
UserName,
Pass,
Note    : String;           // описание базы
end;
//
TDB_many = record                // параметры подключаемых баз данных
Num        : Integer;     // к-во подключаемых БД
Settings   : array of TDB_one;
end;

TAutoCallSettings = record      // параметры отзвона
ServerEnable    : boolean;
ServerPort      : integer;
URLBack         : string;
Retry_Count,
Retry_Timeout,
LifeTime,
Msg_NoCar,
Msg_CarWaiting  : integer;    // код сообщения
end;

/////////////////////

TSettingsRec = record
FTerminal  : record         // параметры формы терминала
Active   : boolean;
Left,
Top      : integer;
end;
AutoCallSet  : TAutoCallSettings;
DB_Orders    : TDB_many;      // параметры удаленной БД
DB_CC        : TDB_one;          // параметры локальной БД
DB_Log       : TDB_one;          // параметры локального лога
end;

implementation

end.

Обычно сначала описываю подтипы которые могут использоваться для передачи параметров процедурам и объектам (TMessageRec, TDB_one, TDB_many) а потом описываю основную запись которая хранит в себе все параметры программы TSettingsRec.
Чем удобно: а)описание типов и констант сведено в одном месте,б) при добавлении изменении констант все делается в одном юните с) «маленькие» собственные типы (н-р TDB_one) очень легко используются в процедурах функциях как параметры д) быстрое написание кода т.к. необязательно помнить дословно название переменных достаточно начать вводить и делфя сама будет показывать какие переменные у тебя есть и т.д. и т.п. для себя нашел неоспоримое преимущество такой организации хранения констант и переменных.
3. Объявляю в проге в одном месте (обычно var PS : TSettingsRec) от слова програм сетингс :) т.е. достаточно ввести PS. и интерпретатор вывалит что у тебя там есть.

Но это так лирическое отступление.

Программа уже давно выросла из пеленок и уверенно лопатит кучу баз данных и хочется хранить все константы программы не в ини файле а БД. У этого тоже есть ряд плюсов. Один из них это изменение констант в реальном времени без останова программы. Вот и начал я размышлять как бы это сделать чтобы было очень удобно и код проги значительно не менять.

Вариант первый.

Идея следующая (а вот тут жду жесткой критики или рац предложений :) ) :
В бд параметры хранятся в след виде:
FNAME FVALUE FTYPE
ServerEnable 0 b
ServerPort 80 i
URLBack http://forum.chertenok.ru s
LifeTime 10 i
Msg_NoCar 10 i
Msg_CarWaiting 10 i

Достаточно компактно удобно с возможностью наращивания функционала. Далее загоняю при старте проги или по событию из базы локально это дело в двумерный вариант массив (название,значение) а сам параметр потом в программе вызываю функцией типа:

function pp(name:string):variant;
begin
// здесь правда придется все время пробегаться циклом по єтому двумерному массиву в поисках имени а потом из соседнего столбца присваивать result значение
//красивее внутренностей процедуры не придумал, смущает этот цикл поиска т.к. констант может быть 30-40 штук и все время их лопапить как то не то, дырку в память протереть можно :--D
end

Второй вариант.
Не париться не создавать проблем себе и не забивать и так больные головы форумчанам :) и выгруженные константы из базы присвоить уже существующим переменным в проге. Склоняюсь к этому варианту.

Итого: Хочется услышать ваши варианты хранения констант программ в БД в реальных проектах … и услыхать критику первого варианта, он вообще жизнеспособен?

Как Вы чаще всего храните настройки программы?

Результат

Загрузка ... Загрузка ...

11.05.2010 · Artyom-Ace · 20 комментариев
Метки: , ,  · Рубрики: Artyom-Ace, delphi

20 комментариев

  1. Artyom-Ace - 11.05.2010

    Еле разобрался с єтим блогом, как тут все сложно! (даже де аватарку поставить не нашел). Может потому что до этого блогами никогда не пользовался :)

  2. 13-ый - 11.05.2010

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

  3. 13-ый - 11.05.2010

    Я бы сделал так — написал класс / набор функции — обертку для работы с настройками/константами (судя по примеру всё же речь видимо больше идет о настройках). что то типа :

    tSetting=class
      public
       function LoadSetting(Name:ShortString);
       procedure SaveSetting(Name:ShortString;Value:ShortString);
     end;
    

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

    К минусам хранения настроек в виде рекордов можно отнести то, что для изменения настроек надо перекомпилировать программу, что весьма не удобно, ини файл или другое внешние хранение лишено этого недостатка :)

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

    В таком виде вполне можно хранить в БД.

    А значения я бы хранил локально, или переменными или в какой то структуре типа рекорд.
    Загружал бы перед использованием (при создании объекта/формы и тд) и сохранял назад с использованием выше указанных функции при завершении работы с ними.

    А параметры подключения к БД, если они не прошиты жестко, что не есть хорошо, всё равно придется хранить не в БД, я обычно храню в ini файле с шифровкой пароля

  4. Ktf - 11.05.2010

    Юзал, юзаю и буду юзать все выше упомянутые варианты.
    Был удивлен, что блог не дал мне проголосовать за все варианты.

    Вообще, как правило, способ хранения настроек сильно зависит от проекта.
    Где-то и ini-файлы или реестр пойдет, где-то xml, ну а где-то БД.

    Я для каждого из вариантов давно соорудил универсальные решения в виде классов. Подключаешь юнит — и сразу получаешь нужный функционал.

    По поводу отдельного юнита.
    Обычно я в нем же объявляю глобальную переменную (если по-твоему, то это PS), ведь один фиг аттачишь этот юнит везде, где идет обращение к константам… :)

    Ну и по поводу хранения в БД.
    Идея, в общем-то, не нова, много раз видел ее воплощение в серьезных коммерческих проектах, да и сам использую.
    Структура таблицы примерно как у тебя (конечно не без вариаций на тему хранения в блобах или разные столбцы под каждый тип).

  5. 13-ый - 11.05.2010

    Я для каждого из вариантов давно соорудил универсальные решения в виде классов. Подключаешь юнит – и сразу получаешь нужный функционал.

    Показал бы что ли… интересно же посмотреть кто как решает этот вопрос…

    или у тебя опять всё секретно ? :)

  6. 13-ый - 11.05.2010

    что касается голосования, поправил, но ключевая фраза — чаще всего, поэтому таблетка была от жадности из 3х вариантов

  7. Ktf - 11.05.2010

    спасиб. отметил все :)

  8. Artyom-Ace - 12.05.2010

    «Я для каждого из вариантов давно соорудил универсальные решения в виде классов. Подключаешь юнит – и сразу получаешь нужный функционал.»

    Да действительно нада такие вещи унифицировать и облагородить проєкт. Просто для остальных функциональных блоков программы (которые чаще всего модифицируются) уже такие универсальные юниты написаны, а с настройки еще тянуться с начала создания проекта поэтому «растут не в плечах а в талии» тем самым теряя привлекательность :). Пора потратить чуток времени и прокачать их :) с учетом приведенных примерчиков, а то стыдно сказать из ini файла читаю и сохраняю еще вызовом соотв процедур из CreateForm 8)
    Осталось додумать как при обновлении параметров их запыжовывать в потоки но это отдельная история …

    З.Ы. Очень хотелось бы услышать в каких случаях удобно хранить параметры в xml? И где народ его вообще использует его в своих проэктах (тут скорее вопрос стоит о применении в локальных НЕ WEB ОРИЕНТИРОВАНЫХ проэктах) А то формат вроде как гибкий и интересный, но куда его притулить пока ума не приложу. Единственное удобное применение для себя нашел это передача пакетных данных между прогами по сети. Вопрос этот может уже выходит за рамки обсуждения этой ветки блога и стоит создать новую? :)

  9. Ktf - 12.05.2010

    Очень хотелось бы услышать в каких случаях удобно хранить параметры в xml?

    последнее приложение, где я использовал xml — это самописный установщик.

    <?xml version="1.0" encoding="UTF-8"?>
    <setup version="MyApplication v.1.7.11">
    <option title="Main application">
     <option title="Application Core Files" required="true">
      <action type="copy" id="1.1">
       <source>data.cab\MyApp.exe</source>
       <destination>%AppDir%\MyApp.exe</destination>
      </action>
      <action type="copy" id="1.2">
       <source>data.cab\AppCore.dll</source>
       <destination>%AppDir%\AppCore.dll</destination>
      </action>
      <action type="inline" id="1.3">
       <file>%CommonFiles%\MyAppconfig.xml</file>
       <find failed="append">
        <begin><myapp><path></begin>
        <end></path></myapp></end>
       </find>
       <add place="after">%AppDir%</add>
      </action>
     </option>
     <option title="Data convertor from v.1.6.xx">
      <action type="copy" id="2.1">
       <source>data.cab\Conv16.dll</source>
       <destination>%AppDir%\Conv16.dll</destination>
      </action>
     </option>
    ...
    </setup>
  10. Bonart - 11.05.2010

    Для командной разработки не годится — если в константу нельзя писать, то это должна быть именно константа, или функция, или свойство только для чтения, но не никак не переменная, тем более глобальная. Хранить настройки в БД как отдельный вопрос не вижу — настройки заворачиваются в класс, класс сериализуется, сериализованное содержимое сохраняется куда угодно.

  11. Artyom-Ace - 12.05.2010

    «Хранить настройки в БД как отдельный вопрос не вижу – настройки заворачиваются в класс, класс сериализуется, сериализованное содержимое сохраняется куда угодно.»

    С этим согласен на 100%. Вопрос не «хранить или не хранить в БД» а как рациональнее организовать взаимодействие этих констант хранимых БД и их копий в программе. В голове то уже отложилась кое какая мысля, но опыт форумчан не пропьешь :) и он часто дает свежие мысли.

  12. anonim - 11.05.2010

    Вы бы ещё код форматировали, цены бы вам тогда не было.

  13. 13-ый - 11.05.2010

    код был форматирован, при копировании форматирование несколько утратилось :)

  14. JayDi - 11.05.2010

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

  15. JayDi - 11.05.2010

    P.S. Код из статьи — отличный пример того, к чему может привести использование табов.

  16. Artyom-Ace - 12.05.2010

    Всем спасибо что поставили на путь истинный :), в голове все утряслось начинаем работать [:-}

  17. Игорь - 12.05.2010

    Рекомендовал бы посмотреть вот сюда:

    Там 4 части, две первых есть в переведенном виде вот тут:

  18. Artyom-Ace - 12.05.2010

    Угу, ссылки уже глянул. Посути это что что высказали хором в этой ветке т.е. настройки (да и все остальные модули и части приложения) оптимальнее и правильнее описывать как объект. В статье дан хороший пример максимально унифицированного модуля работы с настройками программы. Много лишнего но за основу вполне можно взять! Спасибо!

  19. Игорь - 12.05.2010

    Ссылка на перевод
    http://keeper89.blogspot.com/2010/03/delphi-1.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+Keeper89+(Keeper's+blog)

  20. r3code - 21.05.2010

    Такой подход со структурами приемлем, но лишает вкусностей ООП, например, проверки значения перед записью свойства с помощью методов.

    По-моему удобнее сделать класс-обертку для свойств, с методами для сериализации и десириализации. И к этому несколько видов сериализаторов с своими настройками.

    Вопрос где хранить не столько важен, как сама структура класса для хранения настроек.
    Я использую подход — класс-синглтон для хранения настроек, где каждая опция прописана явно, так удобнее программировать, потому что Delphi подсказывает что можно выбирать. Сериализация ручная в INI.
    Для автоматической сериализации можно использовать RTTI, об этом писали на delphikingdom.ru

Написать комментарий