Спростіть свої Delphi-програми – Частина 2, Комерція, Різне, статті

В першій частині ми коротко розглянули основні правила. Крім того, у нас був час подумати, що повинен робити наш код, тому відобразити це в другій частині буде гарною ідеєю.

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.

У будь-якому випадку, наступного разу я покажу Вам, як це зробити, і сподіваюся, поділюся кодом.



Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*