Frage

Im Abschnitt zur "guten Kapselung" in Code Complete wird empfohlen, private Implementierungsdetails auszublenden. Ein Beispiel ist in C ++ angegeben. Die Idee besteht im Grunde genommen darin, die Schnittstelle von der Implementierung selbst in Klassenebene vollständig zu trennen.

class Employee {
public:
    ...
    Employee( ... );
    ...

    FullName GetName() const;
    String GetAddress() const;

private:
    EmployeeImplementation *m_implementation;
};

Ist das wirklich eine gute Zeit? Dies scheint nicht nur ineffizient zu sein (welche Art von Leistungsstrafen würde das geben?), Sondern das gesamte Motto des Code vollständig ("Komplexität verwalten") scheint umgekehrt zu sein- dies nicht hinzufügen Komplexität?

War es hilfreich?

Lösung

Ein weiterer Vorteil der Pimpl -Idiom kann darin bestehen, die aufrechtzuerhalten Abi. Sehen Die Pimpl -Idiom in der Praxis.

Das Größe der Klasse bleibt konstant. Dies bedeutet, dass Sie die interne Implementierung ändern können, während Sie die Schnittstelle intakt halten.

Wenn die Implementierung in kompilierter Form (LIB, DLL usw. usw.) verteilt ist, können Sie unter bestimmten Bedingungen möglicherweise die Bibliothek nur ersetzen, ohne den Code neu kompilieren zu müssen, der die Klasse verwendet. Daher entkoppeln Sie den Code als vollständig eigenständiges Modul, solange sich die öffentliche Schnittstelle nicht ändert.

Wie andere erwähnt haben, verkürzt es auch die Zusammenstellungszeit, was in einigen Fällen Grund genug sein kann.

Andere Tipps

Nun, es erhöht die Kapselung, da Ihre Header -Datei jetzt nur öffentliche Mitglieder und einen einzelnen Zeiger auf eine private Implementierung enthält.

Es senkt auch (leicht?) Aufgrund des zusätzlichen Niveaus der Indirektion.

Der "Reduzierung der Kompilierungszeit" ist hier das Schlüsselproblem.

Wenn Sie (Ihr Unternehmen) die einzigen Benutzer der Klasse sind, dann glaube ich keinen Grund, diese Idiom zu verwenden. Sie erhalten eine geringere Leistung und sollten ohnehin täglich (oder periodische) Wiederaufbau Ihres Quellcodes (was sich der Abhängigkeiten zwischen den Klassen bewusst sein sollte).

Dies bedeutet, dass die Kompilierungszeit weitgehend irrelevant sein sollte, wenn Sie der einzige Verbraucher der Klasse sind.

Wenn Sie die Bibliothek verteilen, ist die Geschichte völlig anders. Änderungen der Header bedeuten, dass Kunden, die Sie haben, ihre Anwendungen wieder aufbauen müssen, um Ihre neue Version zu verwenden, auch wenn Sie die privaten Teile der Klasse ändern. Die Verwendung der PimPL -Idiom hier bedeutet, dass die Änderung für die Benutzer Ihrer dynamischen Bibliothek unsichtbar ist.

Ein zusätzliches Maß an Indirektion durch Zeiger kann zu zusätzlichen Cache -Fehlern führen und Ihr Programm verlangsamen. Afaik, dieses Idiom (PIMPL) wird am häufigsten vorgeschlagen, um die Kompilierungszeit zu verkürzen. Sagen Sie, Sie haben eine employee.h Header mit allen Feldern in der Klasse anstelle von nur einem Zeiger. Wenn Sie nun die Mitarbeiterdetails ändern (z. B. Feld hinzufügen oder entfernen), jede Datei einschließlich employee.h muss neu kompiliert werden. Wenn Sie nur einen einzelnen Zeiger auf eine Implementierungsklasse haben, die in definiert ist, employee.cpp, Nur dann employee.cpp muss neu kompiliert werden, wenn Sie sich ändern EmployeeImplementation.

Liegt die reduzierte Kompilierungszeit nun die zusätzlichen Kosten? Nur Sie können das entscheiden.

Ich denke lose Kopplung, dh brechen Abhängigkeiten, zwischen Komponenten.

Angenommen, Sie bieten eine Infrastrukturbibliothek an, die viele andere Komponenten verwenden. Wie @ZVRBA angab, müssen alle Ihre Kunden jedes Mal, wenn Sie Ihre privaten Implementierungsdetails ändern, neu kompilieren. Es könnte keine große Sache sein, aber bei großen und komplexen Projekten kann eine Integration zwischen Komponenten eine komplexe Aufgabe sein. Wenn Ihre Bibliothek dynamisch ist (dll, .so), wird von Ihren Kunden keine Aktion erforderlich.

Diese Redewendung wird zur Abstraßen über schlechte Header und nicht viel anderes verwendet. Verwenden Sie es nur, wenn die zum Definieren der Klasse erforderlichen Typen mit den Headern einbezogen werden, die Makros auslaufen, sich lange zusammenstellen usw. Abgesehen davon gilt dies im Allgemeinen nicht als richtig. Da Ihre Implementierung ohnehin eine dynamische Zuweisung und Referenzsemantik erfordert, können Sie sie auch einfach zu einer Schnittstelle machen und a anbieten CreateForMyPlatform() Methode, die eine Definition in einer CPP -Datei hat. Zumindest können Sie intelligente Zeiger für dieses Szenario verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top