(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Упростите свои Delphi-приложения - Часть 2

Источник: deviabe

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

1. Введение

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

2. Старый код

Обычно разработчики предпочитают считывать настройки приложения в тот момент, когда пользователь может захотеть их изменить. Когда пользователь закончил редактирование, они снова записываются в реестр. Также, очевидно, что чтение и сохранение настроек происходит при открытии и закрытии формы соответственно.

Итак, на главной форме мы имеем какой-то такой код:

01.procedure TfrmMain.FormShow(Sender: TObject);
02.var
03.  aRegistry: TRegistry;
04.begin
05.  aRegistry := TRegistry.Create;
06.  try
07.    aRegistry.OpenKey('the_registry_path', True);
08.    // FString, FInteger и FBoolean локальные поля
09.    // формы TfrmMain.
10.    FString  := aRegistry.ReadString('string_setting_key');
11.    FInteger := aRegistry.ReadInteger('string_setting_key');
12.    FBoolean := aRegistry.ReadBool('string_setting_key');
13.  finally
14.    aRegistry.Free;
15.  end;
16.end;
17.  
18.procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
19.var
20.  aRegistry: TRegistry;
21.begin
22.  aRegistry := TRegistry.Create;
23.  try
24.    // FString, FInteger и FBoolean локальные поля
25.    // формы TfrmMain.
26.    aRegistry.OpenKey('the_registry_path', True);
27.    aRegistry.WriteString('string_setting_key', FString);
28.    aRegistry.WriteInteger('string_setting_key', FInteger);
29.    aRegistry.WriteBool('string_setting_key', FBoolean);
30.  finally
31.    aRegistry.Free;
32.  end;
33.end;
34.  
35.procedure TfrmMain.mnuEditSettingsClick(Sender: TObject);
36.var
37.  aEditSettingsForm: TfrmEditSettings;
38.begin
39.  aEditSettingsForm := TfrmEditSettings.Create(Self);
40.  try
41.    aEditSettingsForm.TheString := FString;
42.    aEditSettingsForm.TheInteger := FInteger;
43.    aEditSettingsForm.TheBoolean := FBoolean;
44.  
45.    if (aEditSettingsForm.ShowModal = mrOK) then
46.    begin
47.      FString  := aEditSettingsForm.TheString;
48.      FInteger := aEditSettingsForm.TheInteger;
49.      FBoolean := aEditSettingsForm.TheBoolean;
50.    end;
51.  finally
52.    FreeAndNil(aEditSettingsFrom)
53.  end;
54.end;

3. Как это будет работать?

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

4. В чем же проблема?

Выполняется ли код в нужный момент времени?

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

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

Что произойдет в случае ошибки при загрузке/сохранении настроек?

Данный код не идеален, и интересные вещи могут произойти, если в реестре отсутствует требуемый ключ. Код вызовет исключение, что приведет к загрузке/сохранению только части настроек и получению неверных значений. В нашем случае было бы неплохо использовать значение по умолчанию при отсутствии соответствующего ключа в реестре.

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

Неужели главная форма должна загружать/хранить настройки?

Нет, абсолютно нет!

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

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

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

5. Есть ли лучшая альтернатива?

Сказать, что это плохо - не трудно, но в таком случае нужно предложить что-то получше. Давайте немного подумаем, что мы хотим, и что нам требуется. В общем, нам нужен кто-то, кто будет загружать и сохранять настройки приложения. Было бы замечательно, если бы у нас был код, который можно было использовать в любом приложении в будущем. На самом деле не важно, какое количество настроек мы хотим сохранить, как они называются, или в каком формате они хранятся, единственное, что нам нужно - возможность Загрузки/Сохранения/Редактирования и Применения их. Как это будет сделано не важно, но, предположим, класс ApplicationSettings позволяет это делать.

Если мы хотим применить настройки к приложению, нужно добавить код наподобие следующего:

01.var
02.  aApplicationSettings: TApplicationSettings;
03.begin
04.  aApplicationSettings := TApplicationSettings.Create('<OUR Key Registry>');  
05.  try
06.    // Код для загрузки настроек  
07.    aApplicationSettings.LoadFromRegistry;
08.      
09.    // Код для редактирования настроек
10.    if (aApplicationSettings.EditSettings) then    
11.    begin
12.      // Настройки изменены, и, возможно, 
13.      // мы что-то хотим при этои сделать.
14.    end;
15.          
16.    // Код для сохранения настроек
17.    aApplicationSettings.SaveToRegistry;    
18.  finally
19.    FreeAndNil(aApplicationSettings);  
20.  end;
21.end;

Кто что делает?

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

С другой стороны наш класс настроек должен знать какие настройки нужны приложению, какие это настройки, и как их необходимо загружать/сохранять.

Есть ли преимущества у данного подхода?

Конечно, иначе бы я не стал тратить на это время. Наша главная цель - использовать Delphi как объектно-ориентированный язык программирования, а не просто как RAD-инструмент. В дальнейшем мы создадим несколько классов, основанных на данном подходе и основном смысл в том, что использовать эти классы когда нам необходимо.

Если завтра нам потребуется написать другое приложение и ему будет необходимо загружать/сохранять настройки, мы только укажем классу, какие это настройки, их название и тип. Остальная часть кода останется такой же. Мы потратим больше времени на создание класса настроек и написание соответствующего кода, но в следующий раз, все (почти все) уже будет готово.

Что дальше?

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

Конечно, это возможно, я видел такое...

Печально, но однажды я был тем, кого наняли для отладки приложения 5-ти летней давности в поисках ошибки в работе некоторых классов. Я также был в ситуации, когда пришлось пробегаться по тысячам строчек кода, удивляясь, почему некоторые настройки никогда не сохраняются или получают неверные значения. И конечно, я всегда желал, что они уделили подумали над кодом до его написания :-P.

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



 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 11.05.2011 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Delphi Professional Named User
Enterprise Connectors (1 Year term)
Oracle Database Personal Edition Named User Plus License
Bamboo
Quest Software. TOAD for Oracle Edition
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
CASE-технологии
СУБД Oracle "с нуля"
Новые материалы
Краткие описания программ и ссылки на них
Проект mic-hard - все об XP - новости, статьи, советы
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100