Frage

Ich bin ein langjähriger Entwickler (ich bin 49), aber eher neu in der objektorientierten Entwicklung. Ich habe seit Bertrand Meyers Eiffel über OO gelesen, habe aber wirklich wenig OO -Programme gemacht.

Der Punkt ist, dass jedes Buch über OO -Design mit einem Beispiel für ein Boot, ein Auto oder ein echtes gemeinsames Objekt, das wir sehr oft verwenden es.

Sie gehen also normalerweise so etwas wie "Je besser das Modell, desto besser repräsentiert es das Objekt in der Anwendung und desto besser kommt alles heraus".

So weit so gut, aber andererseits habe ich mehrere Autoren gefunden, die Rezepte wie „Eine Klasse sollte nur in eine einzelne Seite passen“ angeben (ich würde hinzufügen, welche Monitorgröße wir nicht versuchen, da wir es nicht versuchen, es nicht zu versuchen Code drucken!).

Nehmen Sie zum Beispiel a PurchaseOrder PurchaseOrderItem, eines der Argumente hier bei der Arbeit ist, dass wir a verwenden sollten PurchaseOrder Einfache Klasse mit einigen Methoden (kaum mehr als eine Datenklasse) und haben a PurchaseOrderFSM "Expertenklasse", die die endliche Zustandsmaschine für die abwickelt PurchaseOrder.

Code riecht Post über das Codierungsschrecken. Ich würde es einfach gesunden Menschenverstand nennen. Wenn ich meine richtige Bestellung ausgeben, genehmigen oder stornieren kann, dann die PurchaseOrder Klasse sollte haben issuePO, approvePO und cancelPO Methoden.

Außerdem hilft das nicht zur Wartbarkeit der Klasse?

War es hilfreich?

Lösung

Eine Klasse sollte das Prinzip der einzelnen Verantwortung verwenden. Die meisten sehr großen Klassen, die ich gesehen habe, tun viele Dinge, weshalb sie zu groß sind. Schauen Sie sich jede Methode und jede Code an, wenn sie in dieser Klasse oder separates, doppelter Code ein Hinweis ist. Möglicherweise haben Sie eine ISSUEPO -Methode, enthält sie jedoch 10 Zeilen Datenzugriffscode beispielsweise? Dieser Code sollte wahrscheinlich nicht da sein.

Andere Tipps

Meiner Meinung nach spielt die Klassengröße keine Rolle, solange die Variablen, Funktionen und Methoden für die betreffende Klasse relevant sind.

Das größte Problem bei großen Klassen ist, wenn es darum geht, diese Klassen zu testen, oder deren Interaktion mit anderen Klassen. Große Klassengröße an sich ist kein Problem, aber wie alle Gerüche zeigt es a Potenzial Problem. Wenn die Klasse groß ist, ist dies im Allgemeinen ein Hinweis darauf, dass die Klasse mehr als eine einzelne Klasse tut.

Für Ihre Autoanalogie, falls der Unterricht car ist zu groß, das ist wahrscheinlich ein Hinweis darauf, dass es in den Unterricht aufgeteilt werden muss engine, Klasse doors und Klasse windshields usw.

Ich glaube nicht, dass es eine bestimmte Definition einer zu großen Klasse gibt. Ich würde jedoch die folgenden Richtlinien verwenden, um festzustellen, ob ich meine Klasse neu gestalten oder den Umfang der Klasse neu definieren soll:

  1. Gibt es viele Variablen, die voneinander unabhängig sind? (Meine persönliche Toleranz liegt in den meisten Fällen bei 10 ~ 20)
  2. Gibt es viele Methoden für Eckfälle? (Meine persönliche Toleranz ist ... nun, es hängt sehr von meiner Stimmung ab, denke ich)

Stellen Sie sich vor, Sie definieren Ihre Windschutzscheibengröße, die Radgröße, das Schwanz -Glühbirnenmodell und 100 weitere Details in Ihrer Klasse car . Obwohl sie alle für das Auto "relevant" sind, ist es sehr schwierig, das Verhalten einer solchen Klasse zu verfolgen car. Und wenn Ihr Kollege eines Tages versehentlich (oder in einigen Fällen absichtlich) die Windschutzscheibengröße basierend auf dem Schwanz -Glühbirnenmodell ändert, braucht Sie ewig, um herauszufinden, warum die Windschutzscheibe nicht mehr in Ihr Auto passt.

Stellen Sie sich in 2 vor, Sie versuchen, alle Verhaltensweisen zu definieren, die ein Auto in der Klasse haben kann car, aber car::open_roof() wird nur für Cabrios verfügbar sein, und car::open_rear_door() Gilt nicht für diese 2-Türer-Autos. Obwohl Cabrios und zweitürige Autos per Definition "Autos" sind, implementieren Sie sie in der Klasse car kompliziert die Klasse. Die Klasse wird schwieriger zu bedienen und schwerer zu pflegen.

Abgesehen von diesen beiden Richtlinien würde ich eine klare Definition des Klassenbereichs vorschlagen. Sobald Sie den Umfang definiert haben, implementieren Sie die Klasse streng auf der Definition. Meistens erhalten die Menschen eine "zu große" Klasse aufgrund der schlechten Definition des Umfangs oder wegen der willkürlichen Merkmale, die der Klasse hinzugefügt wurden

Sagen Sie, was Sie in 300 Zeilen brauchen

Hinweis: Diese Faustregel sieht davon aus

Es ist keine absolute Regel, aber wenn ich in einer Klasse über 200 Codezeilen sehe, bin ich misstrauisch. 300 Zeilen und Warnglocken kommen auf. Wenn ich den Code eines anderen öffne und 2000 Zeilen finde, weiß ich, dass es die Zeit neu refactoring ist, ohne die erste Seite zu lesen.

Meistens kommt dies auf Wartbarkeit an. Wenn Sie ein Objekt so komplex sind, dass Sie sein Verhalten in 300 Zeilen nicht ausdrücken können, wird es für jemand anderen sehr schwierig sein, zu verstehen.

Ich stelle fest, dass ich diese Regel im Modell beile -> ViewModel -> Ansicht der Welt, in der ich ein 'Verhaltensobjekt' für eine UI -Seite erstelle eine Seite. Ich bin jedoch immer noch neu in diesem Programmiermodell und finde gute Möglichkeiten, Verhaltensweisen zwischen Seiten/ViewModels neu zu verhalten/wiederzuverwenden, was allmählich die Größe meiner ViewModels verringert.

Lassen Sie uns es rückwärts gehen:

Geht das nicht mit dem „Maximierenden Kohäsion“ und „minimieren Sie die Kopplung“ -Altinprinzipien, die ich als Eckpfeiler von OO verstehe?

Eigentlich ist es ein Eckpfeiler der Programmierung, von dem OO nur ein Paradigma ist.

Ich werde lassen Antoine de Saint-Exupéry Beantworten Sie Ihre Frage (weil ich faul bin;)):

Perfektion wird erreicht, nicht, wenn nichts mehr hinzugefügt zu werden gibt, sondern wenn nichts mehr zum Mitnehmen ist.

Je einfacher die Klasse ist, desto sicherer wird es richtig, desto einfacher wird es sein völlig Probier es aus.

Ich bin mit dem OP auf der Feature Envy -Klassifizierung. Nichts irritiert mich mehr, als ein paar Klassen mit einer Reihe von Methoden zu haben, die an den Interna einer anderen Klasse arbeiten. OO schlägt vor, dass Sie Daten und Operationen auf diesen Daten modellieren. Das bedeutet nicht, dass Sie die Operationen an einem anderen Ort als die Daten einsetzen! Es wird versucht, Sie dazu zu bringen, die Daten und diese Methoden zu setzen zusammen.

Mit dem car und person Modelle so weit verbreitet, wäre es so, als würde man den Code für die Erstellung der elektrischen Verbindung oder sogar den Starter in die einsetzen person Klasse. Ich würde hoffen, dass dies sein würde Offensichtlich falsch an jeden erfahrenen Programmierer.

Ich habe keine ideale Klasse oder Methodengröße, aber ich ziehe es vor, meine Methoden und Funktionen auf einem Bildschirm anzupassen, damit ich ihre Gesamtheit an einem Ort sehen kann. (Ich habe VIM konfiguriert, um ein 60-Zeilen-Fenster zu öffnen, das zufällig um die Anzahl der Zeilen auf einer gedruckten Seite liegt.) Es gibt Orte, an denen dies nicht viel Sinn ergibt, aber es funktioniert für mich. Ich möchte dieselbe Richtlinie für Klassendefinitionen befolgen und versuche, meine Dateien unter ein paar "Seiten" lang zu halten. Alles über 300, 400 Zeilen fühlen sich unhandlich an (vor allem, weil die Klasse zu viele direkte Verantwortlichkeiten übernommen hat).

Wenn eine Klassendefinition ein paar hundert Methoden hat, ist sie zu groß.

Ich stimme der Verwendung des Einzelverantwortungsprinzip Für Klassen, aber wenn das folgt und in großen Klassen führt, dann sei es so. Der eigentliche Fokus sollte sein, dass einzelne Methoden und Eigenschaften nicht zu groß sind. zyklomatische Komplexität Sollte der Leitfaden dort sein, und folgt, kann dies zu vielen privaten Methoden führen, die die Gesamtklassengröße erhöhen, sie jedoch auf ein detailliertes Niveau lesbar und überprüft werden können. Wenn der Code lesbar bleibt, ist die Größe irrelevant.

Die Ausgabe einer Bestellung ist häufig ein komplizierter Prozess, der mehr als nur die Bestellung beinhaltet. In diesem Fall ist es wahrscheinlich das Richtige, die Geschäftslogik in einer separaten Klasse zu halten und die Bestellung einfacher zu machen. Im Allgemeinen haben Sie jedoch Recht - Sie wollen keine "Datenstruktur" -Klassen. Zum Beispiel Ihre "Pomanager" Business Class " issue() Methode sollte wahrscheinlich die PO's aufrufen issue() Methode. Die PO kann dann ihren Status auf "ausgestellt" festlegen und das Ausgabedatum notieren, während der Pomanager dann eine Benachrichtigung an Konten senden kann das erwartete Datum.

Jeder, der "Regeln" für die Methode/Klassengröße drängt, hat offensichtlich nicht genug Zeit in der realen Welt verbracht. Wie andere erwähnt haben, ist es oft ein Refactoring-Indikator, aber manchmal müssen Sie (insbesondere in der Arbeit "Datenverarbeitung" wirklich eine Klasse mit einer einzigen Methode schreiben, die über 500 Zeilen umfasst. Lass dich nicht darauf aufhalten.

Ich habe mehrere Autoren gefunden, die Rezepte wie "Eine Klasse sollte nur in eine einzelne Seite passen" geben.

In Bezug auf die physische Größe einer Klasse ist das Sehen einer großen Klasse ein Hinweis auf einen Codegeruch, bedeutet aber nicht unbedingt, dass es immer Gerüche gibt. (Normalerweise sind sie es jedoch) Wie die Piraten in den Piraten der Karibik es ausdrücken würden, ist dies mehr das, was Sie als "Richtlinien" bezeichnen würden als die tatsächlichen Regeln. Ich hatte einmal versucht, dem "Nicht mehr als einhundert Loc in einer Klasse" zu folgen, und das Ergebnis war eine Menge unnötiger Überbindung.

Sie gehen also normalerweise so etwas wie "Je besser das Modell, desto besser repräsentiert es das Objekt in der Anwendung und desto besser kommt alles heraus".

Normalerweise beginne ich meine Designs damit. Was macht diese Klasse in der realen Welt? Wie sollte meine Klasse dieses Objekt reflektieren, wie in seinen Anforderungen angegeben? Wir fügen hier ein bisschen Zustand hinzu, ein Feld dort, eine Methode, um an diesen Feldern zu arbeiten, ein paar weitere und voila hinzuzufügen! Wir haben eine Arbeiterklasse. Füllen Sie nun die Signaturen mit den richtigen Implementierungen aus, und wir können loslegen, oder so denken Sie. Jetzt haben wir eine schöne große Klasse mit all den Funktionen, die wir brauchen. Aber das Problem dabei ist, dass es nicht so berücksichtigt, wie die reale Welt berücksichtigt wird. Und damit meine ich, dass es nicht berücksichtigt wird, "Veränderung".

Der Grund, warum Klassen vorzugsweise in kleinere Teile aufgeteilt werden, ist, dass es schwierig ist, große Klassen später zu ändern, ohne die vorhandene Logik zu beeinträchtigen oder ein oder zwei neue Fehler unbeabsichtigt zu erstellen oder einfach nur schwierig zuverwenden. Hier kommen Refactoring, Designmuster, solide usw. ins Spiel, und das Endergebnis ist normalerweise eine kleine Klasse, die an anderen kleineren, detaillierteren Unterschichten arbeitet.

In Ihrem Beispiel erscheint das Hinzufügen von Issuepo, Genehmigungen und Abbrechen von PO in die CORTORDS -Klasse unlogisch. Bestellungen geben sich nicht selbst aus, genehmigen oder stornieren sich nicht. Wenn PO Methoden haben sollte, sollten die Methoden an ihrem Zustand nicht in der gesamten Klasse arbeiten. Sie sind wirklich nur Daten-/Datensatzklassen, an denen andere Klassen arbeiten.

Groß genug, um die erforderliche Logik zu enthalten, um seinen Job auszuführen.

Klein genug, um zu warten und dem zu folgen Einzelverantwortungsprinzip.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top