(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
Enterprise Connectors (1 Year term)
Delphi Professional Named User
IBM Domino Enterprise Server Processor Value Unit (PVU) Annual SW Subscription & Support Renewal
Купить WinRAR : 5 : Академическая лицензия 1 лицензия
SAP® Crystal Presentation Design 2016 WIN INTL NUL
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
CASE-технологии
СУБД Oracle "с нуля"
Новые материалы
Вопросы и ответы по MS SQL Server
Работа в Windows и новости компании Microsoft
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100