2016-09-30 6 views
4

私は、時折Single Responsibility Principleを破ることが許容されるのか、まったく避けるべきかを理解するのが難しいです。SRPは常に尊重されるべきですか?

次のコードは、関連する部分のみを保持するために簡略化されています。

私は文字を表すHeroクラスを持っていますが、それは異なるItemsの倍数を持つことができます。
私はItemsを継承する倍数クラスを持っています。例えば、QuestItemsBackpackItemsです。
私はにItemを追加したいときは、種類によってはItemと違うはずです。
私は最初のものは、SRPを尊重することを行うには2つの異なる方法を試してみた:

public abstract class Item 
{ 
    private string _Name{get;set;} 

    public string Name 
    { 
     get 
     { 
      return _Name; 
     } 
     protected set 
     { 
      if (_Name != value) 
      { 
       _Name = value; 
      } 
     } 
    } 
} 

public class QuestItem: Item 
{ 
    public QuestItem(String name) 
    { 
     Name = name; 
    } 
} 

public class BackpackItem: Item 
{ 
    public BackpackItem(String name) 
    { 
     Name = name; 
    } 
} 
public class Hero 
{ 
    public void AddItem(Item item){ 
     if(item is QuestItem){ 
     //Do stuff to add QuestItem 
     return; 
     } 
     if(item is BackpackItem){ 
     //Do stuff to add BackpackItem 
     return; 
     } 
    } 
} 

利点:SRPが
デメリットを尊重している:私は一種Itemから継承する新しいアイテムを作成し、私を変更することを忘れた場合をAddItemの機能はHeroです。

SRPを尊重していない私の第二の溶液:

public abstract class Item 
{ 
    private string _Name{get;set;} 

    public string Name 
    { 
     get 
     { 
      return _Name; 
     } 
     protected set 
     { 
      if (_Name != value) 
      { 
       _Name = value; 
      } 
     } 
    } 
    public abstract void AddToHero(Hero hero); 
} 

public class QuestItem: Item 
{ 
    public QuestItem(String name) 
    { 
     Name = name; 
    } 
    public override void AddToHero(Hero hero) 
    { 
     //Do my stuff to add my QuestItem to Hero 
    } 
} 

public class BackpackItem: Item 
{ 
    public BackpackItem(String name) 
    { 
     Name = name; 
    } 
    public override void AddToHero(Hero hero) 
    { 
     //Do my stuff to add my BackpackItem to Hero 
    } 
} 

利点::私はからのaddメソッドを忘れることができない
私のAddItemメソッドの機能は、私のアイテムクラスになる

public void AddItem(Item item){ 
      item.AddToHero(this); 
     } 

になりますコンパイル時にエラーが発生するので、新しいItemの種類。 短所:私はSRPを尊重していませんが、今は私が本当になぜそれが悪いのか分かりません。

どのような実装を使いたいですか? (別のもの?)

+1

あなたはSRPだけ、またはすべてのSOLIDに興味がありますか?最初の例では、Hero.AddItemメソッドがOpen/Closeの原則を破るためです。 –

+0

私はコードの品質を向上させるためのベストプラクティスを学び、適用する方法に興味があります。 私は本当に変えるべきことは何でもあります。 – Belterius

答えて

2

まあ、Herosはリポジトリにアイテムを持っていますか?場所や、主人公以外のキャラクター(おそらくモンスター)なども所有していますか?

これは単純化されていることに言及しているので、適切なアプローチが何であるかについて明確な答えを出すことは困難です。多分どちらもありません。

私にとって、このような質問はSRPに関するものではなく、一般的なものがどのようにすべきか、そしてKISSとのバランスをとることです。例えば、であり、アイテムとHerosを完全に分離するより良い解決策となり、その代わりにどのようなオブジェクトがどのような方法で主人公かキャラクターであるかを決定する相互作用のルールがあります。あなたが直面する可能性のある次の問題は、同じアイテムを使って同じことをすることができないHeros、おそらくウィザードとWarriorの種類が異なることです。

また、OOP(単一)継承は実際の状況とよく一致しないことに注意してください。代わりにより構成的なモデルを使用することを検討してください。

+0

ありがとうございます。 今のところ私の 'Heros'は' Items'と対話できる唯一のものです。 コード全体はhttps://github.com/Belterius/LDVELH/tree/ViewModel/LDVELH_WPFから入手できますが、すぐに役立つとは思えません。 「より多くの構成モデル」のサンプル/チュートリアルへのリンクがありますか?これまでのところ、私はOOPタイプのプロジェクトに晒されてきました。 – Belterius

+1

@Belterius始めにhttps://en.wikipedia.org/wiki/Composition_over_inheritanceを見てください。また読む価値があります:https://ericlippert.com/2015/04/27/wizards-and-warriors-part-one/(そしてブログの投稿に続く) – Lucero

1

まず、SRPは簡単に言及して引用しますが、実際にはハードに従うことが非常に多いです。 「が1つで、が必要です」と考えてみると、1つのクラスに入る必要があります。

あなたのケースでは、アイテムをHero(またはMonsterまたはWhatever!)に追加する責任を自分のクラスに移すこともできます。意味:サービスクラスを作成して、他のクラスA、B、C、...に影響を与える特定の動作を実装するが、本当にA、B、C、...のいずれにも当てはまらない場合があります。 ..

すべてのクラスが「オブジェクト」を反映する必要はありません。彼らはまた、 "行動"を表すことができます!だからいくつかの場合ItemAdderServiceあなたを助けるだろうと考えて!

+0

「追加する"部分? – Belterius

+0

異なる実装を可能にする理想的なインターフェースです! – GhostCat

関連する問題