After reading the "Creating Well-Designed Code (Based on Delphi/VCL)" I wrote last time, many friends told me that I felt that I could accept the viewpoints in it, but it seemed to be too simple and not specific enough; some friends also expressed doubts about it. A small example of some objections. Hence this article.
Last time, the example I gave was this: Suppose you want to get a list of strings from somewhere and then display it in a TListBox. The code I recommend is:
ObjectXXX := TObjectXXX.Create;
ListBox1.Items := ObjectXXX.GetStringList;
ObjectXXX.Free;
Indeed, I admit that judging from these three lines of code alone, it seems to be suspected of "object abuse". Maybe the example is too simple, giving the impression that TObjectXXX only has one public member function, GetStringList. If this is true, it is really "object abuse". A class is an abstraction of an object, and an object is composed of a collection of states and operations (that is, data and operations on data). Therefore, an object without state is not an object! The design of a class without private data members is a failed design (that is not a class, but an interface).
Okay, let me give you a detailed example to illustrate how to separate interface code and function code.
Suppose I want to make a simple personal address book management software. Obviously, the entire software is divided into two parts: one part is user-oriented, which is the so-called interface part. I can provide four buttons (respectively "add", " "Delete", "Modify", "Search") and an edit box (displaying address book information and accepting user input) are used to interact with the user; the other part is functional, that is, the access operation of the address book within the software .
So, there is a TAddrBook class, which is an abstraction of the functional part.
TAddrBook = class
PRivate
//Some private members
public
constructor Create;
destructor Destroy;override;
GetCount: Integer;
FindRecord(strString): Integer;
GetRecord(nIndex:Integer): String;
SetRecord(nIndex:integer; strRec:String): Boolean;
AddRecord(strRec:String): Boolean;
DelRecord(nIndex): Boolean;
//Other shared member functions
end;
The reason why private members cannot be determined mainly depends on the implementation of this class.
In this way, the logic of access operations to the address book can be encapsulated. The code in the interface part will not involve these access logics. The interface part code is as follows:
var
Form1: TForm1;
AddrBook: TAddrBook;
nCurRec: Integer;
implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
AddrBook := TAddrBook.Create;
nCurRec := AddrBook.GetCount;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
AddrBook.Free;
end;
//Add button
procedure TForm1.Button1Click(Sender: TObject);
begin
if not AddrBook.AddRecord(memo1.Text) then
ShowMessage("error");
end;
//Delete button
procedure TForm1.Button2Click(Sender: TObject);
begin
if not AddrBook.DelRecord(nCurRec) then
ShowMessage("error");
end;
//modify button
procedure TForm1.Button3Click(Sender: TObject);
begin
if not AddrBook.SetRecord(nCurRec, memo1.Text) then
ShowMessage("error");
end;
//Find button
procedure TForm1.Button4Click(Sender: TObject);
begin
memo1.Text := AddrBook.GetRecord(AddrBook.FindRecord(memo1.Text));
end;
The code in the above interface part does not involve any access logic. The code of each module is simple, easy to understand, and easy to maintain. In fact, the interface code does not know whether the address book is saved in a database or a text file. If a database is used, whether the database is accessed through ODBC, ADO, or BDE, the interface code does not know. In fact, these access logics depend on the implementation of the TAddrBook class. The implementation of the TAddrBook class can be placed in a separate .pas file. Any changes to the implementation of the TAddrBook class will not affect the interface part. When maintaining code, it is wise to limit changes to a single module.
Nicrosoft([email protected]) on 2001.7.14