3

GRASP コントローラー パターンを SOLID のまま、より具体的には単一の責任で維持しながら適用することについて質問があります。

ウィキペディアのコントローラー パターンの定義には次のように書かれています。

コントローラー パターンは、システム イベントを処理する責任を、システム全体またはユース ケース シナリオを表す非 UI クラスに割り当てます。Controller オブジェクトは、システム イベントの受信または処理を担当する非ユーザー インターフェイス オブジェクトです。

そしてSOLIDの単一責任原則について:

オブジェクト指向プログラミングでは、単一責任の原則は、すべてのクラスが単一の責任を持つべきであり、その責任はクラスによって完全にカプセル化されるべきであると述べています。そのすべてのサービスは、その責任と密接に連携する必要があります。

いくつかのサンプルコードに行きましょう。次の Java クラスがあるとします。

public class foo {
    public foo(){}
    public int foo1(){/*Some code*/}
    public String foo2(){/*Some code*/}
    public String foo3(int foo31){/*Some code*/}
}

public class bar {
    public bar(){}
    public int bar1(){/*Some code*/}
    public String bar2(){/*Some code*/}
    public String bar3(int bar31){/*Some code*/}
}

単一の責任を維持しながら、適切なコントローラーの実装は何ですか? ユースケースを通過するだけですか、それとも何ですか? 例えば:

public class bazController {

    private foo fooInstance;
    private bar barInstance;

    public bazController(){
        this.fooInstance = new foo();
        this.barInstance = new bar();
    }

    public void fooAction1(int arg){
        this.foo.foo3(arg);
    }

    public void barAction1(int arg){
        this.bar.bar3(arg);
    }

    public void fooAction2(){
        this.foo.foo1();
    }

    public void barAction2(){
        this.bar.bar1();
    }

}

ここで私は 1 つの責任を負っていますか? 私はこれを正しく行っていますか、またはこれを正しく理解していますか? よろしくお願いします。

編集:bazControllerこのメソッドがあり、両方のクラスが関連しているとどうなりますか?

public int bazAction(){
    return this.foo.fooAction1() + this.bar.barAction1();
}
4

2 に答える 2

2

私は経験豊富な開発者ではありませんが、概念の理解に基づいて、これに関する私のアイデアを探ってみます。

単一の責任:「あなたのクラスは何に対して責任を負っていますか?」という質問に対する答えだと思います。この質問に答えるときは、責任を 1 つだけ教えてください。あなたの場合、答えは次のとおりです。「私のクラスはbazを制御する責任があります」(もちろん、実装はそれを行う必要があります)。

あなたの答えは1つの責任しか指定していないので、適切に実装しました。

Dしかし、あなたのコードはのを満たしていないと思いますSOLID。つまり、依存性注入です。fooコンストラクターをbar介して、または他の手段で注入することができます。

更新:あなたのクラスの責任はcontrol the baz.

foobarは のコンポーネントでbazあり、 を介してそれらのアクションを制御していますbazCntroller

Single Responsibilityバズの制御以外の仕事をしているメソッドを追加すると、違反したと言えます。元:

public void LogBazExecution() {}
public int GetBazExecutionCount() {}

ご覧のとおりbaz controller、 baz アクションが何回起動されたかを追跡するのは の責任ではありません。

原則の背後にある理由は次のとおりですease of maintenance。各クラスが 1 つの責任のみを持つように設計されている場合、システム内の障害の場所を簡単に見つけることができ、新しいバグをあまり導入することなく、必要に応じていつでも簡単に拡張できます。

于 2013-02-01T04:54:06.683 に答える
1

それは実際には、クラスfoobarの背後にあるコンテキストと、それらがコントローラーのビジネスコンテキストとビジネス上どの程度密接に連携しているかに依存します。

あなたの例では、で動作するfooメソッドとで動作するメソッドbarがありますが、との両方で動作するfooメソッドはありませんbar。私にとって、これはそれを示してfooおり、barおそらく多くの共通点はありません。

これが私があなたの例を変える方法です:(仮定しfoobar、共通点が何もない):

public class fooController
{
    private foo fooInstance;

    public fooController() {
        fooInstance = new foo
    }

    public void fooAction1(int arg){
        this.foo.foo3(arg);
    }

    public void fooAction2(){
        this.foo.foo1();
    }
}

public class barController 
{

    private bar barInstance;

    public bazController(){
        this.barInstance = new bar();
    }

    public void barAction1(int arg){
         this.bar.bar3(arg);
    }

    public void barAction2(){
         this.bar.bar1();
    }
}

編集
複数のビジネスロジックインスタンスに委任するコントローラーがある場合の例は、次のようになります。

public class UserSettingsController
{
    private UserAddressLogic addressLogic;
    private UserPersonalInfoLogic personalInfoLogic;

    public UserSettingsController() {
        addressLogic = new UserAddressLogic();
        personalInfoLogic = new UserPersonalInfoLogic();
    }

    public User GetUser() {
        User user = new User();
        user.Address = addressLogic.GetUserAddress();
        user.PersonalInfo = personalInfoLogic.GetPersonalInfo();

        return user;
    }
}
于 2013-02-01T04:45:58.700 に答える