После прочтения книги «Создание хорошо спроектированного кода (на основе Delphi/VCL)», которую я написал в прошлый раз, многие друзья сказали мне, что я чувствую, что могу принять изложенные в ней точки зрения, но она показалась мне слишком простой и недостаточно конкретной; некоторые друзья также выразили сомнения по этому поводу. Небольшой пример некоторых возражений. Отсюда и эта статья.
В прошлый раз я приводил следующий пример: Предположим, вы хотите получить откуда-то список строк и затем отобразить его в TListBox. Я рекомендую следующий код:
ObjectXXX := TObjectXXX.Create;
ListBox1.Items := ObjectXXX.GetStringList;
ОбъектXXX.Бесплатно;
Действительно, я признаю, что, судя по этим трем строкам кода, его как будто подозревают в «злоупотреблении объектом». Возможно, пример слишком прост и создается впечатление, что TObjectXXX имеет только одну общедоступную функцию-член, GetStringList. Если это правда, то это действительно «злоупотребление объектом». Класс — это абстракция объекта, а объект состоит из набора состояний и операций (то есть данных и операций над данными). Следовательно, объект без состояния — не объект! Проект класса без частных элементов данных — это неудачный дизайн (это не класс, а интерфейс).
Хорошо, позвольте мне привести вам подробный пример, чтобы проиллюстрировать, как разделить код интерфейса и код функции.
Предположим, я хочу создать простое программное обеспечение для управления личной адресной книгой. Очевидно, что все программное обеспечение разделено на две части: одна часть ориентирована на пользователя, и это так называемая интерфейсная часть. Я могу предоставить четыре кнопки (соответственно «добавить»). , «Удалить», «Изменить», «Поиск») и поле редактирования (отображение информации адресной книги и принятие пользовательского ввода) используются для взаимодействия с пользователем; другая часть является функциональной, то есть операция доступа к адресная книга в программном обеспечении.
Итак, есть класс TAddrBook, который представляет собой абстракцию функциональной части.
TAddrBook = класс
Частный
//Некоторые частные члены
общественный
конструктор Создать;
деструктор Уничтожить;переопределить;
GetCount: целое число;
FindRecord(strString): Целое число;
GetRecord(nIndex:Integer): String;
SetRecord(nIndex:integer; strRec:String): Boolean;
AddRecord(strRec:String): логическое значение;
DelRecord(nIndex): логическое значение;
//Другие общие функции-члены
конец;
Причина, по которой частные члены не могут быть определены, главным образом зависит от реализации этого класса.
Таким образом можно инкапсулировать логику операций доступа к адресной книге. Код в интерфейсной части не будет задействовать эту логику доступа. Код части интерфейса следующий:
вар
Форма1: ТФорм1;
Адресная книга: TAddrBook;
nCurRec: целое число;
выполнение
процедура TForm1.FormCreate(Отправитель: TObject);
начинать
AddrBook := TAddrBook.Create;
nCurRec := AddrBook.GetCount;
конец;
процедура TForm1.FormClose(Отправитель: TObject; var Action: TCloseAction);
начинать
АдресБук.Бесплатно;
конец;
//Добавить кнопку
процедура TForm1.Button1Click(Отправитель: TObject);
начинать
если не AddrBook.AddRecord(memo1.Text), то
ShowMessage("ошибка");
конец;
//Кнопка удаления
процедура TForm1.Button2Click(Отправитель: TObject);
начинать
если не AddrBook.DelRecord(nCurRec), то
ShowMessage("ошибка");
конец;
//кнопка изменения
процедура TForm1.Button3Click(Отправитель: TObject);
начинать
если не AddrBook.SetRecord(nCurRec, memo1.Text), то
ShowMessage("ошибка");
конец;
//Найти кнопку
процедура TForm1.Button4Click(Отправитель: TObject);
начинать
memo1.Text := AddrBook.GetRecord(AddrBook.FindRecord(memo1.Text));
конец;
Код в приведенной выше части интерфейса не требует какой-либо логики доступа. Код каждого модуля прост, понятен и удобен в обслуживании. Фактически, код интерфейса не знает, сохраняется ли адресная книга в базе данных или в текстовом файле. Если используется база данных, код интерфейса не знает, осуществляется ли доступ к базе данных через ODBC, ADO или BDE. Фактически, эта логика доступа зависит от реализации класса TAddrBook. Реализация класса TAddrBook может быть помещена в отдельный файл .pas. Любые изменения в реализации класса TAddrBook не повлияют на интерфейсную часть. При поддержке кода разумно ограничить изменения одним модулем.
Nicrosoft([email protected]) 14 июля 2001 г.