7

私が取り組んでいるプロジェクトをリファクタリングする最善の方法を定義しようとしています。

優れた設計が不足しているため、ほとんどすべてのプロジェクトは次のもので構成されています。

1) ビジネスロジックを含むフォーム

2) 巨大なデータモジュール (フォームごとに 1 つ + 余分なもの)

3) 共通コード (ライブラリ) を含む一部のユニット

OOP はありません (いくつかの小さな領域を除いて)。コードの再利用は最小限のレベルです。

1 つの問題は、データベース対応コントロールが使用されていることです。そのため、データモジュールに多くのデータセットとデータソースをドロップし、高度に結合された方法で DB に直接リンクするのは非常に簡単でした。

理想的には、Tcustomer、Temployeeのようなクラスを抽出して、OSのカプセル化をアドバンテージし、すべてのコードを複製せずに将来新しいUIを作成できるようにしたいと思います。

とにかく私の質問は次のとおりです。どうすればデータベース対応コントロールを扱い続けることができますか? データセットを返す関数を実装し、dataawarecomponent.datasource を関数の結果にリンクする必要がありますか?

function TCustomer.LoadByID(aCustomerID: integer): TDataset

?

4

2 に答える 2

9

アプリケーションが設計されたアーキテクチャに拘束されます。それに対抗しようとしないでください。データ認識コントロールに得意なこと、つまりデータ同期を行わせます。コントロールが dfm を使用して既にデータ ソースにバインドされている場合、問題はありません。

リファクタリングに必要なのは、コントロールにアタッチしたイベント ハンドラーです。Supervising Controllerパターンをご覧になることをお勧めします。以下の実装例を見つけました。

Delphi には UI アーキテクチャ パターンの例がいくつかありますが、デスクトップ アプリケーション向けのものは、Supervising Controller ではなくPassive Viewに関するものである傾向があります。だからここに私の見解があります。

アプリケーションのフォームごとに少なくとも 1 つのインターフェイスを定義することから始めます。一部のフォームは複雑で、複数のインターフェイスに分割する必要がある場合があるため、少なくとも 1 つと言います。

IProductView = interface
end;

次に、フォームに実装させます。

TProductForm = class(TForm, IProductView)
...
end;

次に、プレゼンター/コントローラーが必要です。これにより、データ同期以外のすべてが処理されます。

TProductPresenter = class
private
  FView: IProductView;
public
  constructor Create(AView:IProductView);
end;

フォーム クラスにプライベート フィールドを作成し、フォームの作成/解放時にプレゼンターを作成/解放します。フォームのコンストラクタ/デストラクタを使用するか、onCreate/onDestroy イベントを使用するかはあまり重要ではありません。

TProductForm = class(TForm, IProductView)
private
  FPresenter: TProductPresenter;
public
  constructor Create;
...
end;

implementation
TProductForm.Create
begin
  FPresenter := TProductPresenter.Create(self);
end;

イベントに応答するためにフォームまたはそのコントロールの 1 つが必要な場合は、責任をプレゼンターに委任します。製品名に適切な大文字が使用されていることを確認する必要があると仮定しましょう。

TProductForm.NameDBEditChange(Sender: TObject);
begin
  FPresenter.ValidateName;
end;

コントロールまたはそのテキスト プロパティを引数として渡すのではなく、データをインターフェイスのプロパティとして公開します...

IProductView = interface
  function GetName:string;
  procedure SetName(Value: string);
  property Name: string read GetName write SetName;

...そしてフォームに実装GetNameSetNameます。

TProductForm.GetName: string;
begin
  Result := NameDBEdit.Text;
end;

TProductForm.SetName(Value: string);
begin
  NameDBEdit.Text := Value;
end;

可能な限り単純な形式でデータを公開することが重要です。TDBEdit に保存されている製品名によっては、プレゼンターは必要ありません。プレゼンターは、インターフェースを通して見ることを明示的に許可したものだけを見るべきです。これの主な利点は、フォームを好きなだけ変更 (または完全に置き換える) できることと、インターフェイスに準拠している限り、プレゼンターに変更を加える必要がないことです。

すべてのビジネス ロジックがプレゼンターに移動されたので、神のクラスのようになります。次のステップは、そのロジックを責任ごとに分割された適切なクラスにリファクタリングすることです。この時点に到達すると、アーキテクチャの再設計を試みるのに適した位置にいます (まだ検討している場合)。

「うわー!それは大変な作業のように見えます!」と言うかもしれません。その通りです (しかし、開始する前に、それが大変な作業になることはわかっていました)。一度にすべて行う必要はありません。これらの手順のいずれも、ロジックが実行される場所でロジックの動作を変更するものではありません。

利点

  • UI を簡単に変更できるようになりました
  • ビジネス ロジックを分離して簡単にテストできる
  • 段階的に実装可能

短所

  • 最初はより多くの作業が必要ですが、これは後でより保守しやすいコードによって相殺されます。
  • すべてのアプリケーションに適しているわけではありません。小規模なプロジェクトの場合、インフラストラクチャを追加する価値はありません。

その他の参考資料

于 2010-10-29T15:46:46.017 に答える
1

コードに優れたデザインや実際のOOPがない場合は、その複雑さを考慮して、まず、現在の機能を説明するデザインを作成する必要があります。はい、それはあなたが最初にたくさんのドキュメントを書くのに忙しいことを意味します。ただし、プロジェクト全体を論理的/機能的な部分に分割して、このドキュメントが完成したら焦点を当てることができます。次に、各部分を個別にリファクタリングしたり、場合によってはそれらの部分を書き直したりすることもできます。
この複雑なプロジェクトは、リファクタリングが常に実用的であるとは限りません。元のデザインに戻って(つまり、何も持っていないので作成します)、コードを見て、リファクタリングまたはリライトのどちらが速いかを検討する必要があります。

于 2010-10-29T13:11:23.510 に答える