หลังจากอ่าน "การสร้างโค้ดที่ออกแบบมาอย่างดี (อิงจาก Delphi/VCL)" ที่ฉันเขียนเมื่อครั้งที่แล้ว เพื่อนหลายคนบอกฉันว่าฉันรู้สึกว่าฉันยอมรับความคิดเห็นในนั้นได้ แต่ดูเหมือนว่าจะง่ายเกินไปและไม่เฉพาะเจาะจงเพียงพอ เพื่อนบางคนยังแสดงความสงสัยเกี่ยวกับเรื่องนี้ด้วย ตัวอย่างเล็กๆ น้อยๆ ของการคัดค้านบางประการ ดังนั้นบทความนี้
ครั้งล่าสุด ตัวอย่างที่ฉันให้คือ: สมมติว่าคุณต้องการรับรายการสตริงจากที่ไหนสักแห่งแล้วแสดงใน TListBox โค้ดที่ฉันแนะนำคือ:
ObjectXXX := TObjectXXX.สร้าง;
ListBox1.Items := ObjectXXX.GetStringList;
ObjectXXX.ฟรี;
อันที่จริงฉันยอมรับว่าเมื่อพิจารณาจากโค้ดสามบรรทัดนี้เพียงอย่างเดียว ดูเหมือนว่าจะสงสัยว่าเป็น "การละเมิดวัตถุ" บางทีตัวอย่างอาจดูง่ายเกินไป โดยให้ความรู้สึกว่า TObjectXXX มีฟังก์ชันสมาชิกสาธารณะเพียงฟังก์ชันเดียว นั่นคือ GetStringList หากเป็นจริง แสดงว่าเป็น "การละเมิดวัตถุ" จริงๆ คลาสเป็นสิ่งที่เป็นนามธรรมของวัตถุ และวัตถุประกอบด้วยชุดของสถานะและการดำเนินการ (นั่นคือ ข้อมูลและการดำเนินการกับข้อมูล) ดังนั้นวัตถุที่ไม่มีสถานะจึงไม่ใช่วัตถุ! การออกแบบคลาสที่ไม่มีสมาชิกข้อมูลส่วนตัวถือเป็นการออกแบบที่ล้มเหลว (นั่นไม่ใช่คลาส แต่เป็นอินเทอร์เฟซ)
เอาล่ะ ฉันขอยกตัวอย่างโดยละเอียดเพื่ออธิบายวิธีแยกโค้ดอินเทอร์เฟซและโค้ดฟังก์ชัน
สมมติว่าฉันต้องการสร้างซอฟต์แวร์การจัดการสมุดที่อยู่ส่วนบุคคลแบบง่ายๆ แน่นอนว่าซอฟต์แวร์ทั้งหมดแบ่งออกเป็นสองส่วน: ส่วนหนึ่งเป็นส่วนที่มุ่งเน้นผู้ใช้ ซึ่งเรียกว่าส่วนอินเทอร์เฟซ ฉันสามารถจัดให้มีปุ่มสี่ปุ่มตามลำดับ ("เพิ่ม" ตามลำดับ) , " "ลบ", "แก้ไข", "ค้นหา") และกล่องแก้ไข (แสดงข้อมูลสมุดที่อยู่และยอมรับการป้อนข้อมูลของผู้ใช้) ใช้เพื่อโต้ตอบกับผู้ใช้ ส่วนอื่น ๆ ใช้งานได้นั่นคือการดำเนินการเข้าถึงของ สมุดที่อยู่ในซอฟต์แวร์
ดังนั้นจึงมีคลาส TAddrBook ซึ่งเป็นนามธรรมของส่วนที่ใช้งานได้
TAddrBook = คลาส
ส่วนตัว
//สมาชิกส่วนตัวบางส่วน
สาธารณะ
ตัวสร้าง สร้าง;
destructor ทำลาย; แทนที่;
GetCount: จำนวนเต็ม;
FindRecord(strString): จำนวนเต็ม;
GetRecord(nIndex:จำนวนเต็ม): สตริง;
SetRecord(nIndex:integer; strRec:String): บูลีน;
AddRecord(strRec:String): บูลีน;
DelRecord(nIndex): บูลีน;
//ฟังก์ชันสมาชิกที่ใช้ร่วมกันอื่น ๆ
จบ;
สาเหตุที่ไม่สามารถระบุสมาชิกส่วนตัวได้ส่วนใหญ่ขึ้นอยู่กับการใช้งานคลาสนี้
ด้วยวิธีนี้ ตรรกะของการดำเนินการเข้าถึงสมุดที่อยู่จึงสามารถสรุปได้ รหัสในส่วนอินเทอร์เฟซจะไม่เกี่ยวข้องกับตรรกะการเข้าถึงเหล่านี้ รหัสส่วนอินเทอร์เฟซมีดังนี้:
var
แบบฟอร์ม 1: TForm1;
AddrBook: TAddrBook;
nCurRec: จำนวนเต็ม;
การดำเนินการ
ขั้นตอน TForm1.FormCreate (ผู้ส่ง: TObject);
เริ่ม
AddrBook := TAddrBook.Create;
nCurRec := AddrBook.GetCount;
จบ;
ขั้นตอน TForm1.FormClose (ผู้ส่ง: TObject; var Action: TCloseAction);
เริ่ม
AddrBook.ฟรี;
จบ;
//เพิ่มปุ่ม
ขั้นตอน 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]) เมื่อ 2001.7.14