การปรับโครงสร้างโค้ด - การได้มาซึ่งการห่อหุ้ม ตัวอย่างการเข้ารหัสของ DELPHI การปรับโครงสร้างโค้ดเป็นวิธีหนึ่งในการได้รับโครงสร้างที่ดี เราสามารถปรับปรุงคุณภาพของโค้ดและเพิ่มระดับของการนำโค้ดกลับมาใช้ใหม่ได้ในขณะที่ยังคงรักษาฟังก์ชันไว้ไม่เปลี่ยนแปลง นี่คือตัวอย่างที่ชัดเจนของวิธีปรับปรุงคุณภาพโค้ดและได้รับการห่อหุ้ม (ตัวอย่างใช้ DELPHI) ฟังก์ชันโค้ด: ตั้งค่าตัวกรองสำหรับชุดข้อมูล (TClientDataSet) ผู้ใช้สามารถเลือกฟิลด์ที่จะกรองใน TComboBox จากนั้นป้อนค่าที่จะกรองในกล่อง Tedit ดังแสดงในรูปที่ 1: วิธีการที่พบบ่อยที่สุดคือการฮาร์ดโค้ดชื่อฟิลด์ในชุดข้อมูลของเราในแอตทริบิวต์รายการของ TComboBox จากนั้นเพิ่มตัวพิมพ์จำนวนมากหรือคำสั่ง if ลงในโค้ดเพื่อกำหนดฟิลด์ที่เลือกโดยผู้ใช้ เพื่อตั้งค่าตัวกรองให้กับชุดข้อมูล ...... case ComboBox1.ItemIndex of0: ClientDataSet.Filtered := False; ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + ''''; .กรองแล้ว := False; ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;... end; หรือใช้... ถ้า ComboBox1.Text = 'Material Code' ให้เริ่ม ClientDataSet.Filtered := False; ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;endelse if ComboBox1.Text = 'name' จากนั้นเริ่ม ClientDataSet.Filtered := False; ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;end... รหัสนี้ยังใช้ตัวกรองการตั้งค่าสำหรับชุดข้อมูลผ่านฮาร์ดโค้ด ตรงตามความต้องการ แต่โค้ดด้านบนไม่ยืดหยุ่น หากชุดข้อมูลมีหลายช่อง ผู้เขียนโค้ดจะต้องป้อนข้อมูลในช่องทีละรายการใน Items และจะต้องตรวจสอบลำดับเมื่อเขียนเคส ไม่เช่นนั้นตัวกรองชุดจะผิดและจะทำให้นักพัฒนาแนะนำได้ง่าย บั๊ก นอกจากนี้ยังเป็นเรื่องยากที่จะรักษาคำสั่ง if จำนวนมากเมื่อใช้คำสั่ง if และไม่รองรับการเปลี่ยนแปลงความต้องการ ข้อมูลโค้ดใน TComboBox หากคุณลืม BUG จะถูกนำเสนอ ดังนั้นในการสร้างใหม่ครั้งแรก ฉันพยายามโหลดข้อมูลใน TComboBox แบบไดนามิกและในเวลาเดียวกัน เพื่อให้เกิดการเปรียบเทียบเมื่อผู้ใช้เลือกหลังจากโหลด ฉันเพิ่มฟิลด์ FFields: array[0..20, 0..2] ส่วนตัวลงในแบบฟอร์มแบบสอบถามนี้เพื่อบันทึกข้อมูลข้อมูลฟิลด์ในชุดข้อมูล ในเวลาเดียวกัน มีการนำกระบวนการโหลดข้อมูลไปใช้: PROcedure TFrmSPARealStorageQuery.GetQueryFields;var i, iFieldsCount: Integer;begin iFieldsCount := 0; with DBGride1.DataSource.DataSet do beginning for i := 0 to Fields.Count - 1 ทำ if Fields[ i].Visible จากนั้นเริ่ม FFields[iFieldsCount, 0] := Fields[i].FieldName; FFields[iFieldsCount, 1] := Fields[i].DisplayLabel; Inc(iFieldsCount); สิ้นสุด; ComboBox1.Items.Clear; (FFields[i, 1]); end;end; ช่วยให้สามารถโหลดข้อมูลฟิลด์แบบไดนามิกขณะรันไทม์ได้ การตั้งค่าตัวกรองของฉันจึงเป็นเช่นนี้ ถ้า ComboBox1.Text <> '' thenbeginClientDataSet.Filtered := False; ClientDataSet.Filter := FFields[ComboBox1.ItemIndex, 0] + '''' + Edit2.Text + ''''; end วิธีนี้จะเพิ่มความยืดหยุ่นของโค้ดและเพิ่มความสามารถในการนำโค้ดกลับมาใช้ใหม่ได้อย่างไม่ต้องสงสัย เนื่องจากโค้ดถูกแยกออกจากการเปลี่ยนแปลงข้อมูลอย่างดี ดังนั้นจึงอาจกล่าวได้ว่าสะดวกตราบใดที่คุณเพิ่มฟิลด์ส่วนตัว FFields: array[0..20, 0..2] ของสตริงใน FORM อื่นที่ใช้ฟังก์ชันนี้เช่นกัน และใช้กระบวนการข้างต้นของการโหลดข้อมูลแบบไดนามิก ตั้งค่าฟิลด์ได้ แต่การนำกลับมาใช้ใหม่นี้ไม่ค่อยดีนักเพราะเรายังไม่ได้รับการห่อหุ้มที่ดี สิ่งนี้นำไปสู่การทำซ้ำโค้ดที่กระจัดกระจายทุกที่ในโปรแกรมของคุณ (คุณมักจะใช้ COPY เพื่อขอรับฟังก์ชันนี้ซ้ำ เนื่องจากโค้ดด้านบนไม่มีการห่อหุ้มที่ดี) หากวันหนึ่งคุณต้องการแก้ไขฟังก์ชันการโหลดข้อมูล คุณจะต้องหาที่ไหนสักแห่งเพื่อคัดลอกฟังก์ชัน และคุณจะต้องแก้ไขโค้ดที่กระจัดกระจายอยู่ในที่อื่น ดังนั้นฉันจึงปรับโครงสร้างใหม่อีกครั้งและห่อหุ้มโค้ดเพิ่มเติม รหัสมีดังนี้: หน่วย uDataSetFieldsInfo; // คำอธิบาย: หน่วยนี้ประกอบด้วยคลาส TDataSetFieldsInfo ซึ่งสรุปการได้มาของข้อมูลส่วนย่อยของชุดข้อมูล // และจัดเตรียมอินเทอร์เฟซสำหรับการแสดงข้อมูลในช่องแสดงรายการคอมโบบ็อกซ์และรับชื่อส่วนย่อยที่เกี่ยวข้อง // สร้างแล้ว: wuchhao // วันที่: 2003.5interfaceuses Classes, DBClient, StdCtrls; type TDataSetFieldsInfo = class private FFieldsList: TStrings; สร้าง ; destructor แทนที่; ขั้นตอน GetDataSetFields (ที่มา: TClientDataSet); ขั้นตอน ShowFieldsInfo (เป้าหมาย: TComboBox); ฟังก์ชั่น GetFieldsNameByDisplayLabel (DisplayLabel: string): string; end; การนำไปใช้งาน { TDataSetFieldsInfo } ตัวสร้าง TDataSetFieldsInfo.Create; begin FFieldsList := TStringList.Create; end; destructor TDataSetFieldsInfo.Destroy;begin FFieldsList.Free; inherited;end;procedure TDataSetFieldsInfo.GetDataSetFields(Source: TClientDataSet);var i: Integer;begin FFieldsList.Clear; with Source do beginning for i := 0 to Fields.Count - 1 ทำถ้า ฟิลด์[i]มองเห็นได้ จากนั้นจึงเริ่มต้น FFieldsList.Add(Fields[i].DisplayLabel); FFieldsList.Add(Fields[i].FieldName); end; end;end;function TDataSetFieldsInfo.GetFieldsNameByDisplayLabel( DisplayLabel: string): สตริง; ดัชนี var: จำนวนเต็ม; เริ่มต้น ผลลัพธ์: = ''; ดัชนี := FFieldsList.IndexOf(DisplayLabel); ถ้าดัชนี <> -1 จากนั้น ผลลัพธ์ := FFieldsList.Strings[index+1] ;end;procedure TDataSetFieldsInfo.ShowFieldsInfo(Target: TComboBox);var i: Integer;begin Target.Items.Clear; .นับเริ่มต้น Target.Items.Add(FFieldsList.Strings[i]); i:= i+ 2; end;end;end หน่วย uDataSetFieldsInfo จะสรุปข้อมูลและวิธีการที่เกี่ยวข้องกับการใช้งานฟังก์ชันที่อธิบายไว้ในบทความนี้ คลาสจะกลายเป็นกล่องดำ ดังนั้นจึงสามารถนำกลับมาใช้ใหม่ได้อย่างง่ายดาย (การใช้กล่องดำซ้ำ) โดยไม่ต้องกังวลกับการทำสำเนาโค้ด ในเวลาเดียวกัน เนื่องจากมีการสรุปข้อมูลที่เกี่ยวข้องกับฟังก์ชัน ความรับผิดชอบของชั้นเรียนจึงมีการกำหนดไว้อย่างชัดเจน (ความรับผิดชอบเดี่ยว) และมีรายละเอียดที่เพียงพอและการห่อหุ้มที่ดี TdataSetFieldsInfo แยกกล่องคำสั่งผสมออกจากการเปลี่ยนแปลงข้อมูลได้อย่างมีประสิทธิภาพ ซึ่งท้ายที่สุดจะปรับปรุงระดับการใช้โค้ดซ้ำ ในขณะเดียวกันก็ลดความรับผิดชอบของคลาส FORM และจำนวนตัวเลขมหัศจรรย์ในการเข้ารหัสยาก นี่คือรหัสใหม่: ขั้นแรกให้ประกาศการอ้างอิงถึงคลาส TdataSetFieldsInfo ในแบบฟอร์ม ...โทรเมื่อมีการสร้าง FORM: FFieldsInfo := TDataSetFieldsInfo.Create;FFieldsInfo.GetDataSetFields(cdMaster);FFieldsInfo.ShowFieldsInfo(ComboBox1); ในขณะนี้ การตั้งค่าตัวกรองของฉันกลายเป็น: if ComboBox1.Text <> '' thenbeginClientDataSet.Filtered := เท็จ; ClientDataSet.Filter := FFieldsInfo.GetFieldsNameByDisplayLabel(ComboBox1.Text) + '''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;end; รับส่วนย่อยที่เกี่ยวข้องโดยการเรียกขั้นตอนอินเทอร์เฟซของวัตถุ FfieldsInfo ชื่อ. บทความนี้เป็นตัวอย่างง่ายๆ ของโค้ดการปรับโครงสร้างใหม่ ฉันคิดว่าคลาสที่ฉันนำไปใช้ข้างต้นสามารถเขียนได้หลายวิธีและมีอัลกอริธึมที่ดีกว่า นี่เป็นเพียงการให้แนวคิดเกี่ยวกับการปรับโครงสร้างโค้ดใหม่ เพื่อปรับปรุงคุณภาพของโค้ด ตลอดจนการบำรุงรักษาและความสามารถในการปรับขนาด เราจะสำรวจแนวคิดเกี่ยวกับการเขียนโปรแกรม OOD