Code-Refactoring – Erzielen einer Kapselung DELPHI-Codierungsbeispiel Code-Refactoring ist eine Möglichkeit, eine gute Struktur zu erhalten. Durch Refactoring können wir die Qualität des Codes verbessern und den Grad der Code-Wiederverwendung erhöhen, während die Funktionen unverändert bleiben. Hier ist ein konkretes Beispiel dafür, wie Sie die Codequalität verbessern und die Kapselung erreichen können. (Das Beispiel verwendet DELPHI) Codefunktion: Legen Sie einen Filter für den Datensatz fest (TClientDataSet). Der Benutzer kann das zu filternde Feld in einer TComboBox auswählen und dann den zu filternden Wert in ein Tedit-Feld eingeben. Wie in Abbildung 1 dargestellt: Die gebräuchlichste Methode besteht darin, die Feldnamen in unserem Datensatz im Items-Attribut von TComboBox fest zu codieren und dann viele Groß-/Kleinschreibungs- oder If-Anweisungen zum Code hinzuzufügen, um die vom Benutzer ausgewählten Felder zu bestimmen um Filter für das Datensatzgerät festzulegen. ...... case ComboBox1.ItemIndex of0: ClientDataSet.Filtered := False; ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + '''';1: ClientDataSet .Filtered := False; ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;... end; Oder verwenden Sie... if ComboBox1.Text = 'Material Code' then begin ClientDataSet.Filtered := False; ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;endelse if ComboBox1.Text = 'name' thenbegin ClientDataSet.Filtered := False; ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;end... Dieser Code implementiert auch das Festlegen von Filtern für den Datensatz durch harte Codierung erfüllt die Anforderungen, aber der obige Code ist unflexibel. Wenn der Datensatz viele Felder enthält, muss der Codierer die Felder einzeln in „Elemente“ eingeben und die Reihenfolge beim Schreiben des Falls überprüfen. Andernfalls ist der festgelegte Filter falsch und für Entwickler einfach einzuführen INSEKT. Es ist außerdem mühsam, bei der Verwendung von if eine große Anzahl von if-Anweisungen beizubehalten, und es werden keine Bedarfsänderungen unterstützt. Wenn der Benutzer eine Änderung des chinesischen Anzeigenamens des Datensatzfelds anfordert, muss er auch daran denken, die fest codierten Daten zu ändern in TComboBox. Wenn Sie es vergessen, wird ein Fehler auftreten. Daher habe ich bei der ersten Rekonstruktion versucht, die Daten in TComboBox Items dynamisch zu laden und gleichzeitig einen Vergleich zu erreichen, wenn der Benutzer nach dem Laden auswählt. Ich habe diesem Abfrageformular ein privates FFields: array[0..20, 0..2] of string; hinzugefügt, um die Feldinformationsdaten im Datensatz zu speichern. Gleichzeitig wird ein Prozess zum Laden von Daten implementiert: PROcedure TFrmSPARealStorageQuery.GetQueryFields;var i, iFieldsCount: Integer;begin iFieldsCount := 0; with DBGride1.DataSource.DataSet do begin for i := 0 to Fields.Count - 1 do if Fields[ i].Visible then begin FFields[iFieldsCount, 0] := Fields[i].FieldName; FFields[iFieldsCount, 1] := Fields[i].DisplayLabel; for i := 0 to iFieldsCount - 1 (FFields[i, 1]); end;end; Dies ermöglicht das dynamische Laden von Feldinformationen zur Laufzeit. Meine Filtereinstellungen sehen also so aus. if ComboBox1.Text <> '' thenbeginClientDataSet.Filtered := False; ClientDataSet.Filter := FFields[ComboBox1.ItemIndex, 0] + '''' + Edit2.Text + ''''; Ende; Diese Methode erhöht zweifellos die Flexibilität des Codes und erhöht die Wiederverwendbarkeit des Codes, da der Code gut von sich ändernden Daten isoliert ist. Daher kann man sagen, dass es praktisch ist, solange Sie das private Feld FFields: array[0..20, 0..2] von string in einem anderen FORM hinzufügen, das diese Funktion ebenfalls implementieren und den obigen Prozess dynamisch verwenden möchte Das Laden von Datensatzfeldern wird erreicht. Diese Wiederverwendung ist jedoch nicht sehr gut, da wir keine gute Kapselung erreicht haben. Dies führt zu doppeltem Code, der überall in Ihrem Programm verstreut ist (Sie verwenden häufig COPY, um die Wiederverwendung dieser Funktion zu erreichen, da der obige Code keine gute Kapselung aufweist). Wenn Sie eines Tages die Datenladefunktion ändern möchten, müssen Sie einen Ort finden, an dem Sie die Funktion kopieren können – und Sie müssen den an anderen Stellen verstreuten Code ändern. Also habe ich es noch einmal umgestaltet und den Code weiter gekapselt. Der Code lautet wie folgt: Unit uDataSetFieldsInfo; // Beschreibung: Die Unit enthält die TDataSetFieldsInfo-Klasse, die die Erfassung von Datensatz-Untersegmentinformationen kapselt. // Und stellt eine Methodenschnittstelle zum Anzeigen von Informationen im Anzeigefeld der Combobox-Liste und zum Abrufen des entsprechenden Unterabschnittsnamens bereit. // Erstellt: wuchhao // Datum: 2003.5interfaceuses Classes, DBClient, StdCtrls;type TDataSetFieldsInfo = class private FFieldsList: TStrings; Create ; destructor Destroy; procedure GetDataSetFields(Quelle: TClientDataSet); procedure ShowFieldsInfo(Target: TComboBox); function GetFieldsNameByDisplayLabel(DisplayLabel: string): string; end;implementation{ TDataSetFieldsInfo }constructor 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 begin for i := 0 to Fields.Count - 1 do if Fields[i].Visible dann beginnen FFieldsList.Add(Fields[i].DisplayLabel); FFieldsList.Add(Fields[i].FieldName); end;end;function TDataSetFieldsInfo.GetFieldsNameByDisplayLabel( DisplayLabel: string): string;var index: Integer;begin Ergebnis: = ''; index := FFieldsList.IndexOf(DisplayLabel); <> -1 then Result := FFieldsList.Strings[index+1] ;end;procedure TDataSetFieldsInfo.ShowFieldsInfo(Target: TComboBox);var i: Integer;begin Target.Items.Clear; i:=0; .Count do begin Target.Items.Add(FFieldsList.Strings[i]); i:= i+ 2; end;end;end. Die Einheit uDataSetFieldsInfo kapselt die Daten und Methoden im Zusammenhang mit der Realisierung der in diesem Artikel beschriebenen Funktionen und kapselt sie in einer Klasse, wodurch das Open-Close-Prinzip im objektorientierten Design realisiert wird. Die Klasse wird zu einer Blackbox, sodass sie problemlos wiederverwendet werden kann (Blackbox-Wiederverwendung), ohne sich Gedanken über Codeduplizierung machen zu müssen. Da funktionsbezogene Informationen gekapselt werden, sind gleichzeitig die Verantwortlichkeiten der Klasse klar definiert (einzelne Verantwortung) und sie weist eine ausreichende Granularität und eine gute Kapselung auf. TdataSetFieldsInfo isoliert das Kombinationsfeld effektiv von sich ändernden Daten und verbessert so letztendlich den Grad der Code-Wiederverwendung, während gleichzeitig die Verantwortlichkeiten der FORM-Klasse und die Menge der fest codierten magischen Zahlen reduziert werden. Hier ist der neue Code: Deklarieren Sie zunächst einen Verweis auf die TdataSetFieldsInfo-Klasse im FORM. ...Aufruf beim Erstellen von FORM: FFieldsInfo := TDataSetFieldsInfo.Create;FFieldsInfo.GetDataSetFields(cdMaster);FFieldsInfo.ShowFieldsInfo(ComboBox1); Zu diesem Zeitpunkt lauten meine Filtereinstellungen: if ComboBox1.Text <> '' thenbeginClientDataSet.Filtered := Falsch; ClientDataSet.Filter := FFieldsInfo.GetFieldsNameByDisplayLabel(ComboBox1.Text) + '''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;end; Rufen Sie die Schnittstellenprozedur des FfieldsInfo-Objekts auf Name. Dieser Artikel ist ein einfaches Beispiel für die Umgestaltung von Code. Ich denke, dass die Klasse, die ich oben implementiert habe, auf viele Arten geschrieben werden kann und über bessere Algorithmen verfügt. Dies dient lediglich dazu, eine Idee zur Umgestaltung des Codes zu vermitteln. Um die Qualität unseres Codes sowie seine Wartbarkeit und Skalierbarkeit zu verbessern, werden wir Ideen zur OOD-Programmiermethode untersuchen.