2016-09-30 2 views
4

Es fällt mir schwer zu verstehen, ob es manchmal akzeptabel ist, das Prinzip der einfachen Verantwortung zu brechen, oder ob es um jeden Preis vermieden werden sollte.Sollte SRP immer respektiert werden?

Bitte beachten Sie, dass der folgende Code vereinfacht wurde, um nur den relevanten Teil zu behalten.

Ich habe Hero Klasse, die ein Zeichen darstellen, kann es mehrere verschiedene Items besitzen.
Ich habe mehrere Klassen, die von Items erben, zum Beispiel QuestItems und BackpackItems.
Wenn ich eine Item auf meiner Hero hinzufügen möchte, je nach Art der Item sollte ich anders handeln.
Ich habe 2 verschiedene Art und Weise versucht, dass die erste zu tun, um die SRP zu respektieren:

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; 
     } 
    } 
} 

Vorteile: SRP
Nachteil respektiert wird: wenn ich ein neues Element erben Art von Item und vergessen eröffne mein zu ändern AddItem Funktion in Hero Ich riskiere eine Menge Ärger.

Meine zweite Lösung, die nicht SRP nicht respektiert:
meine AddItem Funktion

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

werden meine Artikel Klasse geworden:

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 
    } 
} 

Vorteil: Ich kann die Methode add vergessen aus eine neue Item Art, da ich zur Kompilierzeit einen Fehler habe. Nachteil: Ich respektiere SRP nicht, aber ich verstehe im Moment nicht wirklich, warum es so schlimm wäre.

Welche Implementierung sollte ich bevorzugen? (ein anderer?)

+1

Sind Sie nur interessiert an SRP oder alle von SOLID? Weil im ersten Beispiel die Hero.AddItem-Methode das Open/Close-Prinzip bricht. –

+0

Ich bin daran interessiert, wie ich die Best Practice lernen/anwenden kann, um meine Codequalität zu verbessern. Also alles was ich wirklich ändern sollte/könnte. – Belterius

Antwort

2

Nun, können nur Heros "Gegenstände" im Repository haben? Gibt es nicht Orte, Nicht-Helden (vielleicht Monster) usw., die auch Gegenstände besitzen können?

Da Sie erwähnen, dass dies vereinfacht ist, ist es schwierig, eine endgültige Antwort zu geben, was der richtige Ansatz ist. Vielleicht auch nicht.

Für mich ist diese Art von Fragen nicht so sehr über SRP, sondern eher darüber, wie generisch etwas sein sollte, und balancieren das gegen KISS. Zum Beispiel kann es Mai eine bessere Lösung sein, Items und Heros insgesamt zu entkoppeln und stattdessen Regeln der Interaktion haben, die bestimmen, welches Objekt in welcher Weise welcher Held oder Charakter verwendet werden kann. Denn das nächste Problem, dem du gegenüberstehst, ist, dass du verschiedene Arten von Helden hast, vielleicht einen Zauberer und einen Krieger, die nicht die gleichen Dinge mit den gleichen Gegenständen machen können.

Denken Sie auch daran, dass die (einmalige) OOP-Vererbung oft nicht gut auf reale Situationen abbildet; erwägen, stattdessen ein kompositorischeres Modell zu verwenden.

+0

Vielen Dank für Ihre Eingabe. Für jetzt sind meine 'Heros' die einzigen, die mit' Items' interagieren können. Der gesamte Code ist hier verfügbar: https://github.com/Belterius/LDVELH/tree/ViewModel/LDVELH_WPF, aber ich denke nicht, dass es von großem Nutzen sein wird, eine schnelle Hilfe zu geben. Haben Sie einen Link zu einem Beispiel/Tutorial eines "mehr kompositorischen Modells"? Bis jetzt war ich nur dem OOP-Projekttyp ausgesetzt. – Belterius

+1

@Belterius Werfen Sie einen Blick auf https://en.wikipedia.org/wiki/Composition_over_inheritance für einen Start. Lies auch einen lesenswert: https://ericlippert.com/2015/04/27/wizards-and-warrictors-part-one/ (und folgende Blog-Posts) – Lucero

1

Zunächst ist SRP leicht erwähnt und zitiert, aber sehr oft hart in der Realität zu folgen. Nur herauszufinden, "was ist eine Anforderung" (das sollte in eine Klasse gehen) kann schwer sein.

In Ihrem Fall könnte eine Alternative darin bestehen, die Verantwortung für das Hinzufügen eines Gegenstands zu einem Helden (oder Monster oder was auch immer!) In seine eigene Klasse zu verschieben. Bedeutung: Manchmal ist es sinnvoll, eine Klasse Service zu erstellen, die ein bestimmtes Verhalten implementiert, das sich auf andere Klassen A, B, C, ... auswirkt, aber nicht in A, B, C, ... passt. ..

Sie wissen, nicht alle Klassen müssen "Objekte" widerspiegeln. Sie können auch "Verhalten" darstellen! Überlegen Sie also, ob Ihnen ItemAdderService helfen könnte!

+0

Meinst du die Implementierung einer Schnittstelle, die sich um das "Hinzufügen" kümmern würde "Teil? – Belterius

+0

Idealerweise eine Schnittstelle, um verschiedene Implementierungen zu ermöglichen! – GhostCat

Verwandte Themen