Форум программистов, компьютерный форум, киберфорум
krapotkin
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
Блог. Двадцать пять лет Делфи-практики

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

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

Начав с Делфи-2 двадцать пять лет назад, я прошел все версии, испробовал массу технологий, включая работу с БД, с графикой DirectX, связью с серверами и интернетом, разработку на Андроид и IOS, и многое, многое другое.
________________________________________ ________________________________________ ____
P.S. все, о чем здесь написано, всего лишь измышления из головы.
совпадения с реальными людьми и фактами случайны.

Процесс инициализации программы, с настройками и подключением к БД

Запись от krapotkin размещена 20.08.2017 в 20:01
Показов 8161 Комментарии 2
Метки db, delphi

Пока не началось
Все шаги по разбору на старте приложения я стараюсь выполнять в переопределенном конструкторе главной формы.
Это не догма, просто так удобнее.
Мы можем делать это и в событии OnCreate, но тогда если мы решили выйти из приложения, то сначала все равно создастся и криво покажется форма и после этого сразу мигнет и пойдет на выход.
Чтобы исключить эти спецэффекты пишем в классе формы переопределение конструктора
Delphi
1
2
3
4
TMainForm=class(TForm)
...
  constructor Create(AOwner:TComponent); override;
end;
и в конструкторе всё, что нужно на старте.
Вызов исключения в конструкторе приводит к НЕсозданию объекта (а еще вызову деструктора!), поэтому в случае выхода из программы никаких миганий - сразу до свидания...

К главному
Обычно я использую следующие шаги на старте приложения
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
constructor TMainForm.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  // см. примечание 
  ReadSettings(Settings);
  // в загруженные настройки иногда можно внести изменения, запуская программу с ключами командной строки
  // поэтому выполним еще один метод
  ParseParams(Settings);
  // иногда, как в 1С, нужно при старте выбрать БД для подключения, или еше что-нибудь
  // возможно, это просто форма для логина
  // там же клиент может решить вообще отказаться от входа в программу
  ShowSettingsAndLoginForm(Settings);
  // если клиент отказался, то выходим
  if Application.Terminated then
    Abort; // Abort в конструкторе главной формы приведет к мягкому и тихому выходу из приложения
  // если Settings были изменены в форме, то можно их сохранить. Вот пример
  if Settings.RecentConnections.IndexOf(Settings.Database.ConnectionString)=-1 then
  begin
    Settings.RecentConnections.Add(Settings.Database.ConnectionString);
    Settings.SaveToFile(GetSettingsFilename());end;
  end;
  // создать модуль данных и подключиться к БД
  CreateDatamodule();
  // метод Init для всякой остальной работы - прочитать справочники, заполнить структуры данных
  // слазить в интернет, короче все, что нужно для запуска программы
  // лучше всего запустить для этого отдельный поток а форма тем временем покажется и будет рисовать часики
  // в общем, все, что угодно, что требуется для старта программы
  Init();
end;
Примечание. Про хранение настроек программы я писал в другой заметке

Обращу ваше внимание, что у меня есть глобальная переменная Settings, но в каждый метод я передаю её как параметр.
Это связано с тем, что мы когда-нибудь можем решить, что нам нужны более одного комплекта настроек. Для разных пользователей, для проверки подключения к БД, да и просто для исключения любых зависимостей от глобальных переменных.
Инкапсуляция - замечательная вещь. Все работают только с тем, что им дают непосредственно для работы.

Давайте посмотрим, что может находиться внутри каждого из методов.
ReadSettings. Тут все просто.
Delphi
1
 Settings:=TAS_Settings.CreateFromFile(GetSettingsFilename());
ParseParams
Кликните здесь для просмотра всего текста
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure TfMain.ParseParams;
var
  i:integer;
begin
  Settings.Database.ParseParams;
 
  i := 1;
  while i <= ParamCount do
  begin
    if AnsiSameText(paramstr(i), '-ClearReports') then
      Settings.ClearReports := true
    else if AnsiSameText(paramstr(i), '-lang') and (i<paramcount) then
    begin
      Settings.reportuiresource := paramstr(i+1);
      inc(i);
    end;
    inc(i);
  end;
end;

тут стоит обратить внимание, что настройки БД у меня сами умеют лазить по строке параметров и заполнять себя данными оттуда

ShowSettingsAndLoginForm
Здесь стоит конструкция, описанная в заметке Как правильно сделать форму логина
может, с небольшими вариациями
Кликните здесь для просмотра всего текста
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  fSettings:=tfsettings.Create(Self);
  try
    // форма настроек заполняется из хранилища этих самых настроек
    // которое передано в этот метод через параметр Settings
    fSettings.LoadFrom(Settings); 
    repeat
      if fsettings.showModal()=mrOk then
      begin
        // форма сохраняет то, что навводил пользователь, в хранилище нестроек
        fsettings.saveTo(Settings);
        try
          // пробуем подключиться к БД с теми настройками, что получились, включая логин/пароль 
          fSettings.fDBSettingsFrame.TryConnect(Settings.Database);
          Break;
        except
          on e:Exception do
            ShowMessage(e.Message);
        end;
      end
      else
        Application.Terminate;
    until Application.Terminated;
  finally
    fSettings.free;
  end;


CreateDatamodule
Именно здесь, а не в AutoCreate создается мой главный модуль данных. Ведь настройки для подключения мы читали и изменяли тоже здесь.
Delphi
1
2
  dm:=TDM.Create(Application);
  dm.tryConnect(Settings.database);
попытка коннекта выглядит примерно так:
Delphi
1
2
3
4
5
6
7
8
9
10
procedure TDM.TryConnect(DBSettings: TDBSettings);
begin
  Db.DBParams.Values['sql_role_name'] := DBSettings.Role;
  Db.DBParams.Values['user_name'] := DBSettings.user;
  Db.DBParams.Values['password'] := DBSettings.pass;
  Db.DatabaseName := DBSettings.ConnectionString;
  if DBSettings.lib <> '' then
    Db.LibraryName := DBSettings.lib;
  Db.Open();
end;
кстати, коннект вообще говоря я проверял еще в ShowSettingsAndLoginForm
но есть вероятность, что за эти несколько миллисекунд что-то пошло не так и подключение не состоится.
Что ж. В этом случае мы получим Exception в конструкторе и, следовательно, выйдем из программы.
Метки db, delphi
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 2
Комментарии
  1. Старый комментарий
    Возможно, чего-то не понимаю, но вроде в конструкторе "inherited;" в начале забыли.
    Запись от DIEsel_92 размещена 10.01.2019 в 13:00 DIEsel_92 вне форума
  2. Старый комментарий
    Аватар для krapotkin
    Да) Вычищал куски ненужные, лишнее вычистил )
    Запись от krapotkin размещена 10.01.2019 в 13:02 krapotkin вне форума
 
Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru