アルゴリズムの過程で、互いに依存する、または互いに離れて意味をなさないいくつかの値を計算するか、単に保存する必要がある場合があります。
(非常に無意味ですが、重要なことは単純な)例と同じようint[]
に、 number に最も近いで 2 つの異なる値を見つけることができます3
。
int a = values[0];
int b = values[1];
for (int value : values) {
int distance = Math.abs(value-3);
if (value != b) {
if (distance < Math.abs(a-3) ) {
a = value;
}
}
if (value != a) {
if (distance < Math.abs(b-3) ) {
b = value;
}
}
}
takeSausageSliceBetween(a, b);
との計算は相互に依存するため、メソッドcomputeA()
とcomputeB()
を同じクラスで作成することはできません。だから、コンピューティングとは、別のクラスにリファクタリングされることを求めているだけです:a
b
a
b
class DistinctNumbersNearestTo3 {
final int a;
final int b;
DistinctNumbersNearestTo3(int[] values) {
// same algorithm
}
}
したがって、より高いレベルのコードは素晴らしく明確になります。
DistinctNumbersNearestTo3 nearest = new DistinctNumbersNearestTo3(values);
takeSausageSliceBetween(nearest.a, nearest.b);
// nearest never leaves the method it was declared in
ただし(間違っている場合は修正してください)、少なくともいくつかのレベルの最適化、インスタンス化、および新しいオブジェクトのガベージコレクション(edenからだけですが、とにかく)を導入します。コード。また、スタックで int を探すと、ヒープでオブジェクトを探すことになります。
ここでの質問は次のとおりです。JVM は、最終的にリファクタリングされたコードを最適化して、リファクタリングされていないコードと同じように動作するほど十分にスマートですか?
よりクリーンなコードのためにいくつかの変数を新しいオブジェクトにまとめたい別のケースは、の呼び出しに固有のデータを保持a()
する新しいクラスを導入することにより、長いメソッドをいくつかの新しいメソッドにリファクタリングしたい場合です。そのデータを操作するためのいくつかの新しいメソッド。新しいリンク (ノードのペア) を追加できる一連のチェーンを表すクラスを実装して、既存のチェーンを拡張したり、2 つのチェーンを 1 つに結合したり、2 つのノードの新しいチェーンを作成したりするときに、このようなケースに出くわしました。いくつかの観点から、その特定のクラスについて説明しましょう。C
a()
public class SetOfChains {
List<List<Node>> chains;
public void addLink(Node a, Node b) {
// Very long method that mutates field this.chains. Needs refactoring.
}
}
addLink
のいくつかのメソッドに適切に分割するにはSetOfChains
、これらの新しいメソッドのそれぞれに多くのパラメータが必要です。addLink()
これは、 のすべてのステップで必要な呼び出しに固有のデータがあるためですaddLink()
。そのデータを の専用フィールドに保存することSetOfChains
も可能ですが、臭くて表現力に欠けます (メソッドの呼び出し中にのみ意味があるため)。したがって、明らかに、そのデータをそのフィールドに保持する新しい内部クラスを作成し、すべてのアルゴリズム手順を実行します。 、chains
リファクタリングされてaddLink()
いないものと同じように外部フィールドを変更します。
class SetOfChains{
List<List<Node>> chains;
void addLink(Node a, Node b) {
new LinkAddition(a,b).compute();
}
class LinkAddiditon { // Instances never leave addLink()'s scope
private final Something bunch, of, common, fields;
compute() {
this.properly();
this.isolated();
this.steps();
this.of();
this.the();
this.refactored();
this.method();
}
// There be code for the properly isolated steps...
}
しかし、機能的には、古い長い unrefactored を持つことと同等であるためaddLink()
、JVM は結果の命令を、あたかもLinkAddition
オブジェクトが存在しないかのように、リファクタリングされていない場合と同じくらい最適にすることができますか?
では、そのテキストの壁の下に結論を下すと、データとメソッドをメソッドではなく新しいクラスに抽出することで、コードを理解しやすくしようとすると、必然的にパフォーマンスが低下するのでしょうか?
そして、記述されたケースがまさに逃亡分析の対象であるということを正しく理解していますか?