Ich lese PHP-Objekte, Muster und Übungen . Der Autor versucht, eine Lektion in einem College zu modellieren. Ziel ist es, den Unterrichtstyp (Vorlesung oder Seminar) und die Gebühren für den Unterricht auszugeben, je nachdem, ob es sich um einen Stunden- oder einen Festpreisunterricht handelt. So sollte die Ausgabe sein
Lesson charge 20. Charge type: hourly rate. Lesson type: seminar.
Lesson charge 30. Charge type: fixed rate. Lesson type: lecture.
wenn die Eingabe wie folgt ist:
$lessons[] = new Lesson('hourly rate', 4, 'seminar');
$lessons[] = new Lesson('fixed rate', null, 'lecture');
Ich habe das geschrieben:
class Lesson {
private $chargeType;
private $duration;
private $lessonType;
public function __construct($chargeType, $duration, $lessonType) {
$this->chargeType = $chargeType;
$this->duration = $duration;
$this->lessonType = $lessonType;
}
public function getChargeType() {
return $this->getChargeType;
}
public function getLessonType() {
return $this->getLessonType;
}
public function cost() {
if($this->chargeType == 'fixed rate') {
return "30";
} else {
return $this->duration * 5;
}
}
}
$lessons[] = new Lesson('hourly rate', 4, 'seminar');
$lessons[] = new Lesson('fixed rate', null, 'lecture');
foreach($lessons as $lesson) {
print "Lesson charge {$lesson->cost()}.";
print " Charge type: {$lesson->getChargeType()}.";
print " Lesson type: {$lesson->getLessonType()}.";
print "<br />";
}
Aber laut dem Buch irre ich mich (ich bin mir ziemlich sicher, dass ich es auch bin). Stattdessen gab der Autor eine große Hierarchie von Klassen als Lösung an. In einem früheren Kapitel hat der Autor die folgenden "vier Wegweiser" als den Zeitpunkt angegeben, zu dem ich eine Änderung meiner Klassenstruktur in Betracht ziehen sollte:
- Codeduplizierung
- Die Klasse, die zu viel über ihren Kontext wusste
- Der Alleskönner - Klassen, die versuchen, viele Dinge zu tun
- Bedingte Anweisungen
Das einzige Problem, das ich sehen kann, sind bedingte Aussagen, und das auch auf vage Weise - warum also umgestalten? Welche Probleme könnten Ihrer Meinung nach in Zukunft auftreten, die ich nicht vorausgesehen habe?
Update : Ich habe vergessen zu erwähnen - dies ist die Klassenstruktur, die der Autor als Lösung bereitgestellt hat - das Strategiemuster :
quelle
Antworten:
Es ist lustig, dass das Buch es nicht klar ausdrückt, aber der Grund, warum es eine Klassenhierarchie gegenüber bevorzugt, wenn Anweisungen innerhalb derselben Klasse wahrscheinlich das Open / Closed-Prinzip sind Diese allgemein bekannte Software-Design-Regel besagt, dass eine Klasse geschlossen werden sollte Änderung, aber offen für Erweiterung.
In Ihrem Beispiel würde das Hinzufügen eines neuen Unterrichtstyps bedeuten, dass der Quellcode der Unterrichtsklasse geändert wird, wodurch sie anfällig und anfällig für Regressionen wird. Wenn Sie eine Basisklasse und eine Ableitung für jeden Lektionstyp hätten, müssten Sie stattdessen nur eine weitere Unterklasse hinzufügen, die im Allgemeinen als sauberer angesehen wird.
Sie können diese Regel unter den Abschnitt "Bedingte Anweisungen" stellen, wenn Sie so wollen. Ich halte diesen "Wegweiser" jedoch für etwas vage. Wenn Aussagen im Allgemeinen nur Code-Gerüche sind, Symptome. Sie können aus einer Vielzahl von schlechten Entwurfsentscheidungen resultieren.
quelle
Ich denke, dass das Buch darauf abzielt, Dinge zu vermeiden wie:
Meine Interpretation des Buches ist, dass Sie drei Klassen haben sollten:
Sie sollten dann die
cost
Funktion in beiden Unterklassen erneut implementieren .Meine persönliche Meinung
für einfache Fälle wie diesen: nicht. Es ist seltsam, dass Ihr Buch eine tiefere Klassenhierarchie bevorzugt, um einfache bedingte Anweisungen zu vermeiden. Darüber hinaus muss es sich bei Ihrer Eingabespezifikation
Lesson
um eine Fabrik mit einem Versand handeln, bei dem es sich um eine bedingte Anweisung handelt. Mit der Buchlösung haben Sie also:Das ist mehr Komplexität ohne zusätzlichen Nutzen.
quelle
SemesterLesson
,MasterOneWeekLesson
etc. Eine abstrakte Wurzelklasse, oder besser noch eine Schnittstelle, ist definitiv der Weg dann zu gehen. Wenn Sie jedoch nur zwei Fälle haben, liegt es im Ermessen des Autors.Das Beispiel im Buch ist ziemlich seltsam. Aus Ihrer Frage ergibt sich die ursprüngliche Aussage:
Dies würde im Kontext eines Kapitels über OOP bedeuten, dass der Autor wahrscheinlich möchte, dass Sie folgende Struktur haben:
Aber dann kommt die Eingabe, die Sie zitiert haben:
dh etwas, das als streng typisierter Code bezeichnet wird und das ehrlich gesagt in diesem Zusammenhang, wenn der Leser OOP lernen soll, schrecklich ist.
Dies bedeutet auch, dass, wenn ich mit der Absicht des Buchautors Recht habe (dh die oben aufgeführten abstrakten und geerbten Klassen zu erstellen), dies zu doppeltem und ziemlich unlesbarem und hässlichem Code führt:
Wie für die "Wegweiser":
Codeduplizierung
Ihr Code ist nicht dupliziert. Der Code, den der Autor von Ihnen erwartet, funktioniert.
Die Klasse, die zu viel über seinen Kontext wusste
Ihre Klasse übergibt nur Zeichenfolgen von der Eingabe zur Ausgabe und weiß überhaupt nichts. Der erwartete Code hingegen kann dafür kritisiert werden, dass er zu viel weiß.
Der Alleskönner - Klassen, die versuchen, viele Dinge zu tun
Auch hier übergeben Sie nur Zeichenfolgen, nichts weiter.
Bedingte Anweisungen
Ihr Code enthält eine bedingte Anweisung. Es ist lesbar und leicht zu verstehen.
Vielleicht hat der Autor sogar erwartet, dass Sie einen viel überarbeiteten Code schreiben als den mit sechs Klassen oben. Zum Beispiel könnten Sie das Fabrikmuster für Unterricht und Gebühren usw. verwenden.
In diesem Fall erhalten Sie neun Klassen, was ein perfektes Beispiel für eine Überarchitektur ist .
Stattdessen haben Sie einen leicht verständlichen, sauberen Code erhalten, der zehnmal kürzer ist.
quelle
Zunächst können Sie "magische Zahlen" wie 30 und 5 in der Funktion cost () in aussagekräftigere Variablen ändern :)
Und um ehrlich zu sein, denke ich, dass Sie sich darüber keine Sorgen machen sollten. Wenn Sie die Klasse ändern müssen, ändern Sie sie. Versuchen Sie zuerst, Wert zu schaffen, und wechseln Sie dann zur Refactorisierung.
Und warum denkst du, dass du falsch liegst? Ist diese Klasse nicht "gut genug" für dich? Warum machst du dir Sorgen um ein Buch?
quelle
Es ist absolut nicht erforderlich, zusätzliche Klassen zu implementieren. Sie haben ein kleines
MAGIC_NUMBER
Problem in Ihrercost()
Funktion, aber das war's. Alles andere ist eine massive Überentwicklung. Leider ist es jedoch üblich, dass sehr schlechte Ratschläge erteilt werden. Circle erbt beispielsweise Shape. Es ist definitiv in keiner Weise effizient, eine Klasse für die einfache Vererbung einer Funktion abzuleiten. Sie können stattdessen einen funktionalen Ansatz verwenden, um ihn anzupassen.quelle