責任が共有されているときに単一の責任を管理するにはどうすればよいですか?


10

私には2つの基本クラスがOperationありTriggerます。それぞれに、特定のタイプの操作またはトリガーに特化したいくつかのサブクラスがあります。Aは、Trigger特定のトリガすることができますOperation。一方、Operation特定のによってトリガーできますTrigger

特定のものOperationを特定のものにTrigger(またはその逆に)マップするコードを記述する必要がありますが、どこに配置するかわかりません。

この場合、コードは1つのクラスまたは他のクラスに明確に属していません。したがって、単一責任の原則に関しては、コードがどこに属すべきかわかりません。

私はすべてうまくいく3つのオプションを見ることができます。1と2は単なるセマンティクスの選択であるように見えますが、3は完全に異なるアプローチを表しています。

  1. トリガー時、例えばbool Triggers(Operation o)
  2. 操作について、例えばbool TriggeredBy(Trigger t)
  3. マッピングを管理するまったく新しいクラス、たとえばbool MappingExists(Trigger t, Operation o)

単一の責任の原則に関して、共有マッピングコードを配置する場所をどのように決定すればよいですか?

責任が共有されているときに単一の責任を管理するにはどうすればよいですか?


編集1。

したがって、実際のコードは次のようになります。すべてのプロパティは、どちらかであるstringGuidcollection<string>、またはenum。それらは基本的に小さなデータの一部を表すだけです。

ここに画像の説明を入力してください

編集2。

ブール型の戻り値の理由。別のクラスがのコレクションTriggerとのコレクションを使用しOperationます。との間のマッピングがどこにあるかを知る必要がTriggerありOperationます。その情報を使用してレポートを作成します。


なぜブール型なのか?
TulainsCórdova2016

@ user61852呼び出しコードに結果を返す
James Wood

1
呼び出しコードはブール値で何をしますか?この質問への回答によっては、解決策があるかもしれません。
TulainsCórdova2016

@ user61852、私の編集を参照してください。
James Wood

1
それで、実際に操作のトリガーを実行することとは何の関係もありませんか?
トゥレインコルドバ

回答:


4

私はそれをこのように考えます:どの操作がどのトリガーをトリガーするかをどのように決定するのですか?それは、時間の経過とともに変化する、または複数のアルゴリズムに進化するアルゴリズムでなければなりません。TriggerクラスまたはOperationクラスのいずれかに配置することは、それらのクラスが将来このようなシナリオを処理できるようになることを意味します。まだまだあるかもしれないので、マッピングほど単純ではないことに注意してください。

私の選択は、GetOperationForTrigger(Trigger t)などの適切なメソッドでクラスを作成することです。これにより、コードをそのようなクラスのセットに進化させることができ、その選択は実行時または他の変数(たとえば、戦略パターン)に依存する可能性があります。

この考え方の主な前提は、最小限のコード(つまり、今日の3つのクラス)を書くことですが、将来的に機能を拡張する必要がある場合、常に正確に1つの方法があると想定しないことにより、大きなリファクタリングを回避することに注意してください。どのトリガーがどの操作を引き起こすかを特定します。

お役に立てれば。応答はuser61852に似ていますが、理由は異なります。その結果、実装は異なります(つまり、equalsをオーバーライドするのではなく、明示的なメソッドがあるため、メソッドの数はニーズに基づいて時間の経過とともに進化する可能性があります)。


5

そこに行って、それをやった。

オプション#3。

使用する言語はわかりませんが、Javaによく似た擬似コードを使用します。言語がC#の場合、おそらく同様のインターフェイスと構造を持っています。

マッピングクラスまたはマッピングを用意します。

public interface Mapping {
    public void setObject1(Object o);
    public void setObject2(Object o);
    public Object getObjecto1();
    public Object getObjecto2();
}
  • equals()メソッドをオーバーライドして、MappingコレクションにMapping特定のマッピングが含まれているかどうかを照会できるようにします。
  • 専門equals()化されたオブジェクトには、明確なメソッドも必要です。
  • また、インターフェースを実装して、Comparableレポートをソートできるようにします。

マッピングをコレクションに入れるだけです

List<Mapping> list = new ArrayList<Mapping>();
Hat hat = new Hat();
Bag bag = new Bag();
list.add(new Mapping(hat,bag));

後であなたは尋ねることができます:

// let's say you have a variable named x which is of type Mapping

if ( list.contains(x) ){
    // do some thing
}

0
  1. コードをより小さなビットに分解します。

現在、クラスAはクラスBを、クラスBはクラスAを知っています。

定義により、Aは少なくとも、自身の動作を行っている Bを実行する必要があるかどうかをチェックします。Bの場合は逆になります。最初に呼び出されたクラスは、結果を確認して、さらに実行する必要があるかどうかを確認できます。

クラスをより小さなコンポーネントに分割することで、この結合を試してみてください。私は各クラスの一番上にコメントを付けて、それが何をするのかを分かりやすい英語で説明したいと思います。ANDのような単語を使用する必要がある場合、または1つまたは2つの文を超える場合は、それを分解することを検討する必要があります。原則として、「and」の後のすべては独自のクラスにある必要があります

また、トリガーと操作の機能をカバーするインターフェースを定義できるかどうかも確認してください。それができない場合は、クラスが大きくなりすぎていることを示しています。また、クラス間の結合も解除されます。


1
正直なところ、コードをさらに分解できるかどうかはわかりません。確認できるようにクラスシグネチャを使用して質問を更新しましたが、基本的にはそれぞれがいくつかのプロパティを格納するかなり軽量のデータオブジェクトです。カップリングに関しては、はい、それはわずかに問題TriggerがありOperationます。しかし、これは実際のデータがどのようなものかを示しています。マッピングがあるため、それらは結合されます。たとえば、意味を持つためにはお互いについて知る必要があります。
James Wood
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.