Was macht man am besten nicht in einem Konstruktor?

7

Ich begann damit, eine Frage zu formulieren: "Was ist der beste Weg, Komponententests an einem Konstruktor durchzuführen (z. B. __construct () in PHP5)? Aber beim Lesen der zugehörigen Fragen sah ich mehrere Kommentare Ich schlage vor, dass das Setzen von Member-Variablen oder die Ausführung komplizierter Operationen im Konstruktor keine Nos sind.

Der Konstruktor für die fragliche Klasse nimmt hier einen Parameter, führt einige Operationen für ihn durch (stellt sicher, dass er einen Sniff-Test besteht und wandelt ihn bei Bedarf um) und speichert ihn dann in einer Member-Variable.

Ich dachte, die Vorteile wären:

1) dieser Client-Code wäre immer     sicher, einen Wert dafür zu haben     Elementvariable jedesmal wenn ein Objekt     dieser Klasse wird instanziiert und

2) speichert einen Schritt im Client-Code     (Eine davon könnte denkbar sein     verpasst), z. B.

%Vor%

wenn wir das einfach machen könnten

%Vor%

und damit fertig sein.

Ist das ein Nein? Wenn ja warum?

    
PartialOrder 07.02.2009, 21:48
quelle

10 Antworten

8

Das kommt in C ++ - Diskussionen ziemlich oft vor, und die allgemeine Schlussfolgerung, zu der ich gekommen bin, war folgende:

Wenn ein Objekt keine externen Ressourcen erhält, müssen die Member im Konstruktor in initialisiert werden. Dazu müssen alle Arbeiten im Konstruktor ausgeführt werden.

  • (x, y) Koordinate (oder wirklich jede andere Struktur, die nur ein verklärtes Tupel ist)
  • Nachschlagetabelle für US-Bundesstaatskürzel

Wenn ein Objekt Ressourcen erwirbt, die es steuern kann, können in dem Konstruktor zugewiesen werden:

  • Dateideskriptor öffnen
  • reservierter Speicher
  • handle / pointer in eine externe Bibliothek

Wenn das Objekt Ressourcen erwirbt, die nicht vollständig kontrolliert werden können, müssen außerhalb des Konstruktors zugewiesen werden:

  • TCP-Verbindung
  • DB-Verbindung
  • schwache Referenz

Es gibt immer Ausnahmen, aber dies deckt die meisten Fälle ab.

    
Tom 07.02.2009, 23:11
quelle
16

Als Faustregel gilt, dass ein Objekt nach Abschluss des Konstruktors einsatzbereit sein sollte. Aber es gibt oft eine Reihe von Optionen, die anschließend optimiert werden können.

Meine Liste von Do's und Donts:

  • Konstruktoren sollten grundlegende Optionen für das Objekt einrichten.
  • Sie sollten vielleicht Instanzen von Hilfsobjekten erstellen.
  • Sie sollten nicht Ressourcen (Dateien, Sockets, ...) anfordern, es sei denn, das Objekt ist eindeutig ein Wrapper um eine Ressource.

Natürlich keine Regeln ohne Ausnahmen. Wichtig ist, dass Sie über Ihr Design und Ihre Wahl nachdenken. Machen Sie die Verwendung von Objekten natürlich - und dazu gehört die Fehlerberichterstattung.

    
gnud 07.02.2009 21:58
quelle
6

Konstruktoren sind für die Initialisierung des Objekts, also

%Vor%

ist vollkommen akzeptabel.

    
Gary Willoughby 07.02.2009 21:57
quelle
4

Der Job eines Konstruktors besteht darin, die Invarianten einer Instanz festzulegen.

Alles was dazu nicht beiträgt, wird am besten außerhalb des Konstruktors gehalten.

    
Morendil 08.02.2009 12:39
quelle
2

Um die Testbarkeit einer Klasse zu verbessern, ist es im Allgemeinen eine gute Sache, den Konstruktor so einfach wie möglich zu halten und nur nach Dingen fragen zu lassen, die er absolut benötigt. Es gibt eine hervorragende Präsentation , die im Rahmen der "Clean Code Talks" -Serie von Google auf YouTube verfügbar ist. p>     

cg. 07.02.2009 22:47
quelle
1

Sie sollten es auf jeden Fall vermeiden, dass der Client anrufen muss

%Vor%

Solche Sachen gehören absolut in den Konstruktor. Es ist einfach unfreundlich gegenüber dem Client-Programmierer, um sie dazu zu bringen, dies anzurufen. Es gibt eine (etwas umstrittene) Denkweise, die besagt, dass Sie Klassen schreiben sollten, so dass Objekte nie in einem ungültigen Zustand sind - und "nicht initialisiert" ist ein ungültiger Zustand.

Aus Gründen der Testbarkeit und der Leistung ist es jedoch manchmal sinnvoll, bestimmte Initialisierungen auf später im Objekt zu verschieben. In Fällen wie diesen ist faule Bewertung die Lösung.

Entschuldigung dafür, dass Java-Syntax in eine Python-Antwort geschrieben wurde, aber:

%Vor%

Sie können Ihre träge Initialisierung segmentieren, so dass nur die Teile initialisiert werden, die sie benötigen. Es ist zum Beispiel üblich, dies in Gettern zu tun, nur für das, was den Wert beeinflusst, der erhalten wird.

    
slim 08.02.2009 12:33
quelle
0

Hängt davon ab, welche Art von System Sie zu entwerfen versuchen, aber im Allgemeinen glaube ich, dass Konstruktoren am besten dazu verwendet werden, nur den "Zustand" des Objekts zu initialisieren, aber selbst keine Zustandsübergänge auszuführen. Am besten lassen Sie einfach die Standardeinstellungen festlegen.

Ich schreibe dann eine "handle" -Methode in meine Objekte, um Dinge wie Benutzereingaben, Datenbankaufrufe, Ausnahmen, Sortierungen usw. zu behandeln. Der Grundgedanke ist, dass dies jeden Zustand, in dem sich das Objekt befindet, basierend auf externen Kräften (Benutzereingaben, Zeit usw.) handhabt. Grundsätzlich werden alle Dinge, die den Zustand des Objekts ändern und zusätzliche Aktionen erfordern, in den Objekt.

Schließlich habe ich eine Rendermethode in die Klasse eingefügt, um dem Benutzer etwas Sinnvolles zu zeigen. Dies stellt nur den Zustand des Objekts für den Benutzer dar (was auch immer das sein mag.)

__ Konstrukt ($ Argumente)
handhaben ()
render (Ausnahme $ ex = null)

    
thesmart 07.02.2009 23:20
quelle
0

Die __construct magic-Methode ist in Ordnung. Der Grund für die Initialisierung in vielen Frameworks und Anwendungen liegt darin, dass das Objekt auf eine Schnittstelle programmiert wird oder versucht, ein Singleton / getInstance-Muster zu erstellen.

Diese Objekte werden im Allgemeinen in einen Kontext oder einen Controller gezogen, und dann werden sie von anderen übergeordneten Objekten mit der allgemeinen Schnittstellenfunktionalität aufgerufen.

    
Syntax 08.02.2009 11:28
quelle
0

Wenn $ var absolut notwendig ist, damit $ Thing funktioniert, dann ist es DO

    
Chepech 23.02.2009 17:50
quelle
-1

Sie sollten Dinge nicht in einen Konstruktor einfügen, der nur einmal ausgeführt werden soll, wenn die Klasse erstellt wird.

Um es zu erklären.

Wenn ich eine Datenbankklasse hätte. Der Konstruktor ist die Verbindung zur Datenbank Also

%Vor%

Und jetzt bin ich mit der Datenbank verbunden.

Dann haben wir eine Klasse, die einige Methoden innerhalb der Datenbankklasse verwendet.

%Vor%     
Ólafur Waage 07.02.2009 21:57
quelle

Tags und Links