Vererbung vs enum-Eigenschaften in der Domäne Modell
Hatte ich eine Diskussion auf der Arbeit über "die Vererbung im domain-Modell erschwert die Entwickler Leben". Ich bin ein OO-Programmierer, so dass ich begann zu suchen nach Argumenten, die mit Vererbung im domain-Modell erleichtert dem Entwickler das Leben wirklich statt-switches, die alle über den Ort.
Was ich sehen möchte, ist dies :
class Animal {
}
class Cat : Animal {
}
class Dog : Animal {
}
Was der andere Kollege sagt, ist :
public enum AnimalType {
Unknown,
Cat,
Dog
}
public class Animal {
public AnimalType Type { get; set; }
}
Wie kann ich ihn überzeugen (links sind WILLKOMMEN ), dass eine Klassen-Hierarchie wäre besser, als dass es eine enum-Eigenschaft für diese Art von Situationen?
Dank!
- Ist das für Sie eine in-memory-Objekt-Modell oder ein ORM? Ich finde nicht, die Tiere z.B. sehr nützlich, da es nicht ausüben, viele der häufigsten Probleme, die Sie Gesicht, wenn Sie echte OO-design.
- vereinbart. Speziell, was die Winkel Verhalten?
- Hunde bellen, Katzen miauen, mit Ihrer Kollegin, die Implementierung dieser Verhaltensweisen ist schwer zu implementieren in C# (zum Beispiel). Es ist immer noch sinnvoll in funktionale Sprachen wie F#, wobei diskriminiert Gewerkschaften sind ein sehr mächtiges Mittel zur Verfügung zu stellen Polymorphismus.
- und @sfinnie: es ist ein anemic domain model für ORM und business-Schicht. Aus meiner Sicht ist ein domain-model-Klasse kann Eigenschaften haben, die keine Bedeutung haben, für andere Klassen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist, wie ich Grund dazu:
Nur die Vererbung verwenden, wenn die Rolle/der Typ wird sich nie ändern.
z.B.
übernahmekonzept für Dinge wie:
Feuerwehrmann <- Mitarbeiter <- Person ist falsch.
sobald Freddy der Feuerwehrmann änderungen job oder wird arbeitslos, Sie haben ihn zu töten, und erstellen Sie ein neues Objekt des neuen Typs, die mit allen alten Beziehungen zu ihm befestigt wird.
So die naive Lösung der oben genannten problem würde geben einen JobTitle enum-Eigenschaft der person-Klasse.
Dies kann genug sein, in einigen Szenarien, z.B. wenn Sie nicht brauchen, sehr komplexe Verhaltensweisen im Zusammenhang mit der Rolle/Typ.
Der richtigere Weg wäre, zu geben, die Klasse person eine Liste von Rollen.
Jede Rolle repräsentiert e.g einen Arbeitsvertrag mit einer Zeit-Spanne.
z.B.
oder wenn das übertrieben ist:
Diese Weise , Freddy kann sich ein Entwickler w/o-wir haben ihn zuerst zu töten.
Jedoch alle mein Geschwafel immer noch nicht beantwortet, wenn Sie sollten eine enum-oder Typ-Hierarchie für die jobtitle.
In reinen In mem OO ich würde sagen, dass es mehr richtig zu verwenden-Vererbung für die jobtitles hier.
Aber wenn Sie das tun, O/R-mapping Sie könnten am Ende mit ein bisschen overcomplex Daten Modell hinter die kulissen, wenn der mapper versucht, die Zuordnung der einzelnen Unterkategorie, um eine neue Tabelle.
Also, in solchen Fällen, oft gehe ich für den enum-Ansatz, wenn es keine realen/komplexen Verhalten im Zusammenhang mit der Arten.
Damit kann ich Leben, mit ein ", wenn Typ == JobTitles.Feuerwehrmann ...", wenn die Nutzung eingeschränkt ist, und es macht die Dinge einfacher oder weniger Komplex.
z.B. das Entity Framework 4-designer für .NET kann nur die Zuordnung der einzelnen Unterkategorie, um eine neue Tabelle. und Sie erhalten möglicherweise eine hässliche Modell oder eine Menge von Verknüpfungen, wenn Sie Abfragen in Ihrer Datenbank w/o jeder wirklichen nutzen.
Aber ich die Vererbung verwenden, wenn der Typ/Rolle statisch ist.
z.B. für Produkte.
haben Sie vielleicht CD <- Produkt-und Buch - <- Produkt.
Vererbung gewinnt hier, weil in diesem Fall haben Sie wahrscheinlich auch anderen Staat im Zusammenhang mit dem Typen.
CD kann eine Reihe von Spuren-Eigenschaft bei einem Buch haben vielleicht die Anzahl der Seiten Eigenschaft.
Also kurz gesagt, es hängt davon ab 😉
Auch, am Ende des Tages werden Sie wahrscheinlich am Ende mit einer Menge von switch-Anweisungen oder so.
Lassen Sie uns sagen, das Sie Bearbeiten wollen, ein "Produkt" , auch wenn Sie die Vererbung verwenden, werden Sie wahrscheinlich haben Sie code wie diesen:
wenn (Produkt Buch)
Antwort.Redicted("~/EditBook.aspx?id" + Produkt.id);
Da die Codierung der Bearbeiten-Buch-url in die entity-Klasse wäre hässlich, da es zwingen würde, Ihre business-entites zu wissen, über Ihre Website-Struktur etc.
Enums sind gut, wenn:
Wenn Sie könnte lösen Ihr problem mit einer Zahl, eine enum ist wahrscheinlich eine gute Passform und mehr typsicher. Wenn Sie brauchen mehr Flexibilität als die oben genannten, dann enums sind wahrscheinlich nicht die richtige Antwort. Verwenden von polymorphen Klassen können Sie:
Statisch sichergestellt, dass alle Typ-spezifisches Verhalten behandelt wird. Zum Beispiel, wenn Sie müssen alle Tiere zu können
Bark()
machenAnimal
Klassen mit einer abstraktenBark()
Methode der compiler überprüfen Sie, dass jeder Unterklasse implementiert wird. Wenn Sie ein enum und einem großenswitch
es nicht, sicherzustellen, dass Sie haben behandelt jeden Fall.Können Sie neue Fälle (Arten von Tieren in deinem Beispiel). Diese kann getan werden, über source-Dateien, und auch über paketgrenzen. Mit einem enum, sobald Sie deklariert haben, ist es eingefroren. Open-ended-Erweiterung ist eine der primären stärken von OOP.
Es ist wichtig zu beachten, dass Ihre Kollegin Beispiel nicht in direktem Widerspruch zu Ihnen. Wenn er möchte, dass ein Tier der Typ zu sein, der eine exponierte Immobilie (was ist nützlich für einige Dinge), können Sie immer noch tun, ohne über ein enum, mit der Typ-Objekt-Muster:
Dies gibt Ihnen die Bequemlichkeit der eine enum: Sie können
AnimalType.Cat
und Sie können die Art des Tieres. Aber es gibt Ihnen auch die Flexibilität von Klassen: Sie können Felder hinzufügenAnimalType
zum speichern zusätzlicher Daten, die mit jedem Typ, der Sie virtuelle Methoden, etc. Noch wichtiger ist, können Sie neue Tier-Arten nur durch das erstellen neuer Instanzen vonAnimalType
.Würd ich fordere Sie auf zu überdenken: in einer anemic domain model (pro die Kommentare oben), Katzen nicht Verhalten anders als Hunde, so gibt es keine Polymorphie. Ein Tier-Typ ist wirklich nur ein Attribut. Es ist schwer zu sehen, was für ein Erbe kauft Sie es.
Dass ein enum ist wie das werfen eine party für alle, die
Open/Closed Principle is for suckers
Menschen.Es wirklich lädt Sie ein, um zu überprüfen, ob ein Tier einer bestimmten Art, und wenden Sie dann eine benutzerdefinierte Logik für jeden Typ. Und darstellen können, schreckliche code, das macht es wirklich schwer, weiterhin den Aufbau auf Ihrem system.
Allem OOPS bedeutet Modellierung der Realität. Vererbung gibt Ihnen die Möglichkeit zu sagen, die Katze ist ein Tier. Tier soll nicht wissen, wenn Ihr eine Katze, die jetzt Schreien, und dann entscheiden, dass es wohl zu Miauen und nicht Bellen, Kapselung wird besiegt es. Weniger code, als dass Sie jetzt nicht tun, Wenn sonst, wie du gesagt hast.
Beide Lösungen sind richtig.
Sie sollten schauen, welche Techniken wendet Sie besser aus problem.
Wenn Ihr Programm verwendet verschiedene Objekte, und nicht neue Klassen hinzufügen, es ist besser, Sie bleiben mit Aufzählungen.
Aber, wenn Sie das Programm verwendet eine Menge von verschiedenen Objekten (verschiedenen Klassen), und kann neue Klassen hinzufügen, in Zukunft besser versuchen, das Erbe Weg.