コードのリファクタリング - カプセル化の取得 DELPHI コーディング例 コードのリファクタリングは、リファクタリングを通じて、機能を変更せずにコードの品質を向上させ、コードの再利用の度合いを高めることができます。コードの品質を向上させ、カプセル化を実現する方法の具体的な例を次に示します。 (例では DELPHI を使用しています) コード関数: データ セット (TClientDataSet) のフィルターを設定します。ユーザーは、TComboBox でフィルターするフィールドを選択し、Tedit ボックスにフィルターする値を入力できます。図 1 に示すように: 最も一般的な方法は、TComboBox の Items 属性にあるデータ セットのフィールド名をハードコーディングし、コードに case ステートメントまたは if ステートメントを多数追加して、ユーザーが選択したフィールドを決定することです。データセットのフィルターを設定します。 ... 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; または使用します... ComboBox1.Text = 'マテリアル コード' の場合、 ClientDataSet.Filtered := False := ' 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... このコードは、ハードコーディングを通じてデータセットのフィルター設定も実装します。ニーズは満たしていますが、上記のコードは柔軟性がありません。データセットに多くのフィールドがある場合、コード作成者は項目にフィールドを 1 つずつ入力する必要があり、ケースを記述するときに順序を確認する必要があります。そうしないと、設定されたフィルターが間違ってしまい、開発者が導入しやすくなります。バグ。また、if ステートメントを使用するときに多数の if ステートメントを維持するのは面倒であり、ユーザーがデータ セット フィールドの中国語表示名の変更を要求した場合は、ハードウェア名も変更する必要があります。 TComboBox項目にコード化されたデータを忘れるとバグが発生します。そこで、最初の再構築では、TComboBox Items にデータを動的にロードすると同時に、ロード後にユーザーが選択したときに比較を実現しようとしました。プライベート FFields: array[0..20, 0..2] of string; フィールドをこのクエリ FORM に追加して、フィールド情報データをデータ セットに保存しました。同時に、データをロードするプロセスが実装されます: PRocedure TFrmSPARealStorageQuery.GetQueryFields;var i, iFieldsCount: Integer;begin iFieldsCount := 0; with DBGride1.DataSource.DataSet do begin for i := 0 to Fields.Count - 1 if Fields[ i].Visible を実行してから FFields[iFieldsCount, 0] を開始します :=フィールド[i].フィールド名; FFields[iFieldsCount, 1] := フィールド[i].DisplayLabel; i := 0 から iFieldsCount - 1 を実行します。 (FFields[i, 1]); end;end; これにより、実行時にフィールド情報を動的にロードできます。したがって、私のフィルター設定は次のようになります。 if ComboBox1.Text <> '' thenbeginClientDataSet.Filtered := False; ClientDataSet.Filter := FFields[ComboBox1.ItemIndex, 0] + '''' + Edit2.Text + '''';この方法では、コードがデータの変更から適切に分離されるため、間違いなくコードの柔軟性が向上し、コードの再利用性が向上します。したがって、同じくこの関数を実装した別のFORMに文字列のプライベートフィールドFFields:array[0..20, 0..2]を追加し、上記の動的にデータをロードする処理を利用すれば便利であると言えます。設定されたフィールドの再利用が実現されます。しかし、適切なカプセル化が達成されていないため、この再利用はあまり良くありません。これにより、プログラム内のあらゆる場所に重複コードが散在することになります (上記のコードは適切にカプセル化されていないため、この関数を再利用するには COPY を使用することがよくあります)。ある日、データ読み込み関数を変更したい場合は、その関数をコピーする場所を探す必要があり、他の場所に点在するコードも変更する必要があります。そこで、再度リファクタリングして、コードをさらにカプセル化しました。コードは次のとおりです:unit uDataSetFieldsInfo; // 説明: ユニットには、データ セットのサブセグメント情報の取得をカプセル化する TDataSetFieldsInfo クラスが含まれています。 // コンボボックス リスト表示フィールドに情報を表示し、対応するサブセクション名を取得するためのメソッド インターフェイスを提供します。 // Created : wuchhao // Date : 2003.5interfaceuses Classes, DBClient, StdCtrls; type TDataSetFieldsInfo = class private FFieldsList: TStrings;作成; デストラクター オーバーライド; GetDataSetFields(ソース: TClientDataSet); プロシージャ ShowFieldsInfo(ターゲット: TComboBox); 関数 GetFieldsNameByDisplayLabel(DisplayLabel: string): string; end;implementation{ TDataSetFieldsInfo }constructor TDataSetFieldsInfo.Create;begin FFieldsList := TStringList.Create;end;destructor TDataSetFieldsInfo.Destroy;begin FFieldsList.Free;継承;end;プロシージャ 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 から開始FFieldsList.Add(Fields[i].DisplayLabel); FFieldsList.Add(Fields[i].FieldName); end; end;function TDataSetFieldsInfo.GetFieldsNameByDisplayLabel( DisplayLabel: string): string;var インデックス: Integer;begin = ''; インデックス := FFieldsList.IndexOf(DisplayLabel); <> -1 then Result := FFieldsList.Strings[index+1] ;end;procedure TDataSetFieldsInfo.ShowFieldsInfo(Target:TComboBox);var i: Integer;begin Target.Items.Clear; i < FFieldsList; .Count do begin Target.Items.Add(FFieldsList.Strings[i]); i:= i+ 2; end;end;end. uDataSetFieldsInfo ユニットは、この記事で説明する機能の実現に関連するデータとメソッドをクラスにカプセル化し、オブジェクト指向設計における Open - Close 原則を実現します。クラスはブラックボックスになるため、コードの重複を気にすることなく簡単に再利用(ブラックボックス再利用)できます。同時に、関数関連の情報をカプセル化するため、クラスの責任が明確に定義され (単一責任)、十分な粒度と良好なカプセル化が実現されます。 TdataSetFieldsInfo は、データの変更からコンボ ボックスを効果的に分離し、最終的にコードの再利用の度合いを向上させながら、FORM クラスの責任とハードコーディングされたマジック ナンバーの量を削減します。新しいコードは次のとおりです。 まず、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 プログラミングのアイデアを検討します。