web-dev-qa-db-ja.com

「Introduce Parameter Object」は実際に良いパターンですか?

いくつかのパラメーターを必要とする関数を呼び出したい状況があります。この関数は直接呼び出されず、間接的に呼び出され、パラメーターが数回委譲されます。いくつかの追加のパラメーターが異なるレイヤーの間に追加される場合がありますが、それらは簡単にするために例には含まれていません。

疑似コードでは、AC.abcで発生する機能を間接的に呼び出します。

class A {
    private B b;

    public int abc() {
        return b.abc(value1, value2, value3);
    }
}

class B {
    private C c;

    public int abc(int x, int y, int z) {
        return c.abc(x, y, z);
    }
}

class C {
    private int w = 100;

    public int abc(int x, int y, int z) {
        // Do something with parameters x, y, z, e.g.:
        return w + x + y + z;
    }
}

もちろん、パラメーターの数は3つとは異なる場合があります。パラメーターを一緒に使用する限り、パラメーターの数は少なくても大きくてもかまいません。このような状況では、Introduce Parameter Objectが推奨される場合があります( ここ および ここ )。

次のように適用されます。

class XYZParameterObject {

    private int x, y, z;

    public constructor(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public int abc(int w) {
        return w + x + y + z;
    }
}

class A {
    private B b;

    public int abc() {
        return b.abc(new XYZParameterObject(value1, value2, value3));
    }
}

class B {
    private C c;

    public int abc(XYZParameterObject xyz) {
        return c.abc(xyz);
    }
}

class C {
    private int w = 10;

    public int abc(XYZParameterObject xyz) {
        // Do something with parameters x, y, z, e.g.:
        return xyz.abc(this.w);
    }
}

私にはこれはクラスが1つのメソッドを中心に設計されているようですが、動作はありません。実際には、XYZParameterObjectインスタンスを作成するのではなく、クロージャーを渡すのと同じです。どちらの状況でも、x、y、zパラメータは1つのパラメータに削減されます。どちらも、同じ引数を何度も渡す必要がないために、クラスを悪用しているように見えます。一方、それはもちろんいくらか便利です!

では、そのような状況で推奨される方法は何ですか?

5
user2180613

パラメータオブジェクトは、パラメータのセットをユニットに収集するための単なる方法です。しかし、あなたの例ではあなたはもっと何かをしています-あなたはビジネスロジック(追加)をパラメータオブジェクト自体に追加しています(これはCクラスが不要になることを意味します)。しかし、それはもはや単なるパラメータオブジェクトではありません。

パラメータオブジェクトは、単一のメソッドを中心に構築されたクラスではなく、データ転送オブジェクトです。つまり、メソッドはまったくありません(または少なくともデータにアクセスするためのメソッドのみ)。しかし、それはビジネスメソッドを備えた実際のクラスの出発点になる可能性があります。

そもそもパラメーターオブジェクトが適切かどうかは、コードによって異なります。あなたの例は、あまりに抽象的すぎてわかりません。ただし、xy、およびzが3Dの点の座標を表すと言う場合、それらをパラメーターオブジェクトにグループ化すると便利ですが、さらに追加するとさらに便利です。スケーリング、追加など、ポイントの計算のためのいくつかのビジネスロジック.

6
JacquesB

「Introduce Parameter Object」は実際に良いパターンですか?

はい。あらゆる点で。

これにより、コードが読みやすくなり、結果としてより理解しやすくなります。解析する必要のある情報が少ないほど、理解しやすくなります。

この観点から、パラメーターのリストをobjectにリファクタリングすることは理にかなっています。このオブジェクトに意味のある名前を付けると、2倍になります。

編集後:

私にはこれはクラスが1つのメソッドを中心に設計されているようですが、動作はありません。

1つのメソッドをオブジェクトに入れても、(提供したコンテキストでは)意味がありません。

a.abc()への呼び出しは、b.abc()への呼び出しを委譲します。これ自体が、値オブジェクトに含まれている値を使用して何かを実行します。したがって、methodが属すべき場所は、例Cです。

このメソッドは、呼び出しが再利用可能である必要がある場合にのみ意味を持ちます。たとえば、Aは、それについてDに通知するための結果が必要だとします。

では、そのような状況で推奨される方法は何ですか?

値オブジェクトを使用しても問題ありません。単にパラメータリストを短くするためです。コードが読みやすくなります。

複数の場所でメリットがある場合にのみ、メソッドを追加します。

1
Thomas Junk