5

Struts 1.2.4 を使用して、この巨大なレガシー Java Web アプリを継承しました。アクションに関して具体的な質問があります。ほとんどのページにはアクションが 1 つだけあり、processExecute() メソッドは恐ろしい怪物です (非常に長く、要求パラメーターに基づいてネストされた多数の if ステートメント)。

アクションがコマンド パターンの実装であることを考えると、これらのアクションをユーザー ジェスチャごとに 1 つのアクションに分割することを考えています。ただし、これは大規模なリファクタリングになります。

  1. これは正しい方向ですか?
  2. モノリシックなアクション内の混乱を処理するパターンなど、私が取ることができる中間ステップはありますか? アクション内の別のコマンド パターンでしょうか。
4

7 に答える 7

9

これに対処する私の方法は次のようになります。

  • 「一度にすべて」をしないでください
  • 何かを変更するときはいつでも、見つけたよりも良いままにしておきます
    • 条件を個別の Action 実装に置き換えることは 1 つのステップです。
    • さらに良いことに、フレームワークを変更するときに使用できるように、実装を Action クラスから分離します。
    • 新しい Command 実装を Struts への参照なしで完全に保持し、新しい Action をこれらの実装のラッパーとして使用します。
    • すべてのデータをコピーせずに Struts ActionForm を渡すために、Struts ActionForm へのインターフェイスを提供する必要がある場合があります。一方、通常は一連の文字列である ActionForms 以外のオブジェクトを渡したい場合があります ( Struts 1.2 ActionFormsに関する他の質問を参照してください) 。
  • より新しく、より優れたテクノロジーへのパーツの移行を開始します。Struts 1.2 は出てきたときは素晴らしかったですが、永遠にサポートしたいものではありません。現在、いくつかの世代のより優れたフレームワークがあります。

間違いなくもっとあります - 申し訳ありませんが、ここで時間切れです...

于 2008-10-16T18:19:28.167 に答える
5

私の考えでは、Struts アクションにはあまり多くのコードを含めるべきではありません。リクエストとレスポンスを直接操作する必要があります。フォームまたはリクエスト パラメータから一部のデータを取得し、その情報をサービス レイヤーに渡してから、一部を Response オブジェクトに入れるか、ユーザーのセッションに一部のデータを保存します。

アクション クラスで継承を行わないようにすることをお勧めします。最初は良いアイデアのように思えますが、遅かれ早かれ、実際にコード ベースを堅牢にするよりも、靴べらを作っていることに気付くと思います。Struts にはそのままで十分なベース アクションがあります。新しいアクションを作成する場合は、Web レイヤーにあるはずのないコードが含まれている可能性があります。

それは私の個人的な経験です。

于 2008-10-17T02:57:43.253 に答える
2

私は以前にこの種のことを扱ったことがあります。最初の良いステップは、Actionと元の巨大なアクションクラスの1つ(ClassAと呼びましょう)の間の継承チェーンに別の基本クラスを挿入することです。特に、一度にすべてを行う時間がない場合。次に、機能の一部をより小さな並列アクションクラス(ClassB、ClassC)に引き出し始めることができます。元のClassAと新しいリファクタリングされたクラスに共通するものはすべて、新しい基本クラスにプルアップできます。したがって、階層は次のようになります。

Original Hierarchy:      New Hierarchy:

     Action                   Action
       |                        |
       |                      BaseA
  (old)ClassA                   |
                       +--------+----------+
                       |        |          |
                   ClassB (new)ClassA   ClassC
于 2008-10-17T01:59:26.693 に答える
2
  1. 一度に1つの方法を実行します
  2. 後で再生できるテストケースをいくつか記録します。 ここでの例(コード内のできるだけ多くのパス、つまり、このアクションを呼び出すページ上のすべてのユーザージェスチャをヒットするようにしてください)
  3. メソッドをリファクタリングして、より小さなことを行うより小さなメソッドを作成することにより、複雑さを軽減します。
  4. これを行うときにテストを再実行します

この時点で、非常に厄介なメソッドのバージョンをリファクタリングしました。 これで、実際に特定のアクションの作成を開始できます

新しくリファクタリングされたクラスを基本クラスとして使用し、それらのリファクタリングされた小さなメソッドを使用して、特定の各アクションをサブクラスとして実装できます。

これを実行すると、クラス間で共有されるロジックの全体像がわかり、必要に応じてこれらのメソッドをプルアップまたはプッシュダウンできます。

面白くはありませんが、コードベースでしばらく作業する場合は、時間と頭痛の種を節約できます。

于 2008-10-17T16:21:35.520 に答える
1

難しい問題ですが、初期の Web アプリ開発の典型です。

まず最初に、どのロジックがビジネス行動を構成し、どのロジックが「フロー」 (つまり、ユーザーに表示されるもの) を構成し、どのロジックがユーザーが表示するコンテンツを取得するかについて考え始める必要があります。

ファクトリやインターフェイスなどの経路をたどる必要はありません。遡及的な実装はあまり役に立ちません...しかし、ビジネスロジックとデータ取得ロジックをある種のデリゲートに統合し、Strutsアクションを残して、そのロジックの成功/失敗に基づいてページフローを決定します。

そこから、数週間かけて磨き上げるだけです

于 2008-10-16T18:26:49.900 に答える
1

ケースが非常に短い単一の switch ステートメント (トークンの解析など) でない限り、1 つの長いメソッドは決して適切ではありません。

少なくとも、長いメソッドをわかりやすい名前の小さなメソッドにリファクタリングできます。

可能であれば、フォームを調べてメソッドが何をすべきかを認識することからメソッドを開始し、さまざまなオプションへの道を if/else することができます。ただし、ネストされた if はありません。これらはコードを判読不能にする傾向があります。ただ

enum Operation {
  ADD, DELETE;
}

...

Operation operation = determineOperation(form);
if (operation == Operation.DELETE) { 
  doDelete(form); 
} else if (operation == Operation.ADD) {
  doAdd(form);
}

そこまで行くことができれば、あなたのロジックは素晴らしくきれいになり、好きなようにリファクタリングを行うことができます。

難しいのは、ロジックを明確にすることです。これは段階的に行うことができます。問題が何であるかを正確に理解するまで、パターンを選択しないでください。

于 2008-10-16T18:34:39.823 に答える
1

コードのリファクタリングを計画している場合は、最初に既存のコードのテストを作成して、リファクタリングを開始した後にその機能が変更されていないことを確認する必要があります。

于 2008-10-16T18:45:45.383 に答える