5

私は最近、ここ数か月で Java でのコーディングを開始しました。多くのメソッドで肥大化しすぎている Matrix クラスがあります。また、Matrix を拡張する SquareMatrix クラスも用意しており、肥大化の一部を軽減しています。

私が見つけたのは、Matrix クラスの多くのメソッドが一般的に行列に関連しているということです。addMatrix(Matrix)、multiplyMatrix(Matrix)、multiplyMatrix(float) などのすべての基本があり、getGaussian(Matrix) や getLUDecomposition(Matrix) などのより複雑なメソッドがあります。

クラス Matrix の行数を減らすには、どのようなオプションがありますか? クラスが非常に大きくなるのは普通ですか? 私はそうは思いません...これは私が早い段階で検討すべきことであり、リファクタリングは困難ですか?または、簡単な解決策はありますか?

ありがとうございました!


編集:いくつかの回答を読んだ後、次のことを検討しています:

ユーティリティ クラスMatrix には、マトリックスの一般的な/基本的なメソッドがすべて含まれています。

委任クラス (ヘルパー/サブ):

*ヘルパー クラス* getGaussian(..)、getLUFactorization(..)、...

サブクラス (Matrix を拡張) SquareMatrix、LowerTriMatrix、UpperTriMatrix、...

委任は、C++ でヘッダーを含む複数の .cpp ファイルを定義することに似ています。さらなるヒントは大歓迎です。


Edit2: また、クイックフィックスではなく、適切に設計してリファクタリングすることをお勧めします。今回だけでなく、将来のプロジェクトに役立つことを願っています。

4

5 に答える 5

3

インターフェースはcompleteminimalの両方である必要があります。つまり、型インターフェースには、その型で必要かつ意味のあるタスクを達成するために必要なすべてのメソッドが含まれている必要があります。

そのため、Matrix の API メソッドを分析し、コア API (タスクを実行するためにクラスの内部にアクセスする必要がある) に属するものと、「拡張」機能を提供するものを判断します。次に、クラス API をコア機能に縮小し、残りのメソッドを、パブリック コア API を使用して目的を達成できる個別のヘルパー / ユーティリティ / サブクラスに移行します。

リファクタリング/単体テストのヘルプについては、Michael Feathers によるLegacy Code を効果的に使用することを検討してください。

于 2012-04-18T08:49:05.207 に答える
2

肥大化したクラスをきれいに見せるための簡単で汚い方法 (混乱を他の場所に移動することによって)

メソッドの内容を外部ユーティリティ クラスの静的メソッドに入れることができます。

例:

マトリックス.java

import MatrixUtils;
//[...]
public class Matrix
{
    //[...]
    Matrix()
    {
        //[...]
    }
    //[...]
    public Gaussian getGaussian(Matrix m)
    {
        return MatrixUtils.computeGaussian(m);
    }
    public LUDecomposition getLUDecomposition(Matrix m)
    {
        return MatrixUtils.computeLUDecomposition(m);
    }
}

MatrixUtils.java

protected class MatrixUtils
{
    private MatrixUtils()//Utility class: prevent instantiation
    {//nothing
    }
    //[...]
    protected static Gaussian computeGaussian(Matrix m)
    {
        //do your superlong 100+lines Algorithm and return the result
    }
    public static LUDecomposition computeLUDecomposition(Matrix m)
    {
        //do your superlong 100+lines Algorithm and return the result
    }
}

このように (私が言ったように、すばやく汚い)、Matrix クラスをきれいにブラウズできます (特に、メソッドと javadoc がたくさんある場合)。

実際のコードにアクセスしたい場合は、MatrixUtils にアクセスします。

何らかの理由で各メソッドが非常に長い (200 行以上のコード!?) 場合、および他の理由で .java ファイルを短くしておく必要がある場合は、「静的クラス」を作成することもできます。 " (つまり、静的メソッドのみを持つユーティリティ クラス) すべての [uber-long] メソッドに対して。

...そしてもちろん、@oksaytで言及されているように、コードのいくつかのブロックを別々の(まだ一貫性のある)関数に入れることでメソッドを短縮する、ある程度「手続き型」のリファクタリングを行う必要があります。

于 2012-04-18T09:17:17.773 に答える
2

リファクタリングは確かに良いことですが、優れた単体テストがない限り、確実にリファクタリングすることは困難です。テスト駆動開発は、通常はリファクタリングが容易なコードベースを実現する方法を提供します。

単体テストのない既存のコードの場合、これは、最初にリファクタリングする領域を分離する必要がある前に、最初に単体テストを記述してからリファクタリングすることを意味します。ただし、これが単なる個人的なプロジェクトである場合は、リファクタリングを無傷で生き残るために必要な機能の最小限のセットだけのテストを作成することでおそらく回避できます。

手元にあるリファクタリングの方法については、他の回答が指摘しているように、いくつかの原則と方法があります。ほとんどの場合、私にとってうまくいったのは次のとおりです。

次のスタイル ルールを厳密に適用します。

  1. メソッドは 40 行を超えることはできません
  2. クラスのファンアウトは 20 を超えることはできません

他にもありますが、個人的には、これらが悪いデザインから自分を遠ざけるのに最も役立つことがわかりました. メソッドの長さを制限すると、メソッド シグネチャについて真剣に考え、簡潔で的を絞ったメソッドを書く必要があります。これにより、通常、重複を見つけて削除しやすくなります。クラスのファンアウトを制限すると、クラス レベルでも同様の効果があり、クラスの役割についてよく考え、簡潔にする必要があります。

などのツールcheckstyleは、これらの両方を他の多くのスタイル ルールと共に適用できます。

EclipseIDEA IntelliJはどちらも「抽出メソッド」リファクタリングを提供します。これにより、抽出するコードを強調表示してショートカット キーを押すだけで簡単に実行できます。IntelliJ は、クラス内のまったく同じコードの出現をチェックし、それらを新しいメソッドの呼び出しに置き換えます。実際、手動でコピー&ペーストして編集するよりも、このようなリファクタリング ツールを常に使用することをお勧めします。

于 2012-04-18T09:13:56.537 に答える
1

「非常に大きい」とはどういう意味ですか?

メソッドは 100 行以内、クラスは javadoc を含めて 1000 行以内にする必要があると思います。さらに必要な場合は、デザインを確認してください。委任を使用します。つまり、ロジックをモジュール/クラスに分離し、あるクラスを別のクラスから呼び出します。

于 2012-04-18T08:50:34.260 に答える
0

基本的な行列演算については、適切なライセンスでオープン ソースの実装を使用できます。あなたは考えることができます: -

http://math.nist.gov/javanumerics/jama/

http://code.google.com/p/effective-java-matrix-library/

http://commons.apache.org/math/

これにより、コード全体のサイズが間違いなく縮小され、より多くのテスト済みの使用済みコード ベースの利点が得られます。

お役に立てれば。

于 2012-04-18T09:19:13.447 に答える