class oder namespace
-
Gehören nicht-sichtbare Daten in den privaten Bereich einer Klasse (Implementierung B) oder doch eher in eine Unnamed Namespace der Quelldatei (Implementierung A), damit die Klassendeklaration nach aussen "schlank" bleibt?
Implementierung A
//--------------------------- // a.h #ifndef A_H_ #define A_H_ class A { public: void DoSomething(); }; #endif //--------------------------- // a.cc #include "a.h" namespace { const int SIZE = 123; const int array[SIZE] = { // some data }; } // Unnamed void A::DoSomething() { // work with array[]... }Implementierung B
//--------------------------- // a.h #ifndef A_H_ #define A_H_ class A { public: void DoSomething(); private: static const int SIZE = 123; static const int array[A::SIZE]; }; #endif //--------------------------- // a.cc #include "a.h" const int A::array[A::SIZE] = { // some data }; void A::DoSomething() { // work with A::array[]... }
-
Kommt drauf an. Wenn jede Klasse so etwas benötigt, dann in jede Klasse. Aber etwas wie
shared_ptrwürde ich im anonymen Namespace machen.
-
Hängt davon ab, was ich dem Leser der Klasse mitteilen will.
Sowas wie eine SIZE ist normalerweise interessant, damit er das Wesen der Klasse genau begreifen kann. Sowas wie eine CACHESIZE hingegen ist normalerweise uninteressant, weil sie nur vom verwendeten Prozessor abhängt.
-
EOutOfResources schrieb:
Kommt drauf an. Wenn jede Klasse so etwas benötigt, dann in jede Klasse. Aber etwas wie
shared_ptrwürde ich im anonymen Namespace machen.Nein, <shared_ptr> sind hier Unfug, da nichts von dem nach aussen sichtbar sein wird. Es dient lediglich für interne Berechnungen innerhalb nur genau der jeweiligen Klasse und wird nirgendwo sonst verwendet.
-
volkard schrieb:
Hängt davon ab, was ich dem Leser der Klasse mitteilen will.
Sowas wie eine SIZE ist normalerweise interessant, damit er das Wesen der Klasse genau begreifen kann. Sowas wie eine CACHESIZE hingegen ist normalerweise uninteressant, weil sie nur vom verwendeten Prozessor abhängt.Eben, und daher ziehe ich Implementierung A mit Unnamed Namespaces vor, da den Nutzer der Klasse interne Tabellen (und überhaupt deren Existenz und Grösse) nicht interessieren sollten.
-
Tomahawk schrieb:
volkard schrieb:
Hängt davon ab, was ich dem Leser der Klasse mitteilen will.
Sowas wie eine SIZE ist normalerweise interessant, damit er das Wesen der Klasse genau begreifen kann. Sowas wie eine CACHESIZE hingegen ist normalerweise uninteressant, weil sie nur vom verwendeten Prozessor abhängt.Eben, und daher ziehe ich Implementierung A mit Unnamed Namespaces vor,
Tomahawk schrieb:
da den Nutzer der Klasse interne Tabellen (und überhaupt deren Existenz und Grösse) nicht interessieren sollten.
Eben doch! Der Benutzer hat ein berechtigtes Interesse, umfassend informiert zu werden. Er soll immerhin die Klasse möglichs sachgemäß benutzen. Programmieren ist kein Krieg. Außerdem würde ich mich selber bekriegen. Zum Beispiel der globale Instanzenzähler muß member sein.
Ich ziehe die offene Variante stark vor. Die geschlossene mache ich nur, wenn es fürchterlich uninteressant ist, wenn ich das nicht erwähnen würde, wenn ich die Funktionsweise der Klasse (nicht nur die Schnittstelle) einem Kollegen gegenüber skizzieren würde. Und gaanz selten, um Header-Abhängigkeiten zu reduzieren.
-
Tomahawk schrieb:
Nein, <shared_ptr> sind hier Unfug, da nichts von dem nach aussen sichtbar sein wird. Es dient lediglich für interne Berechnungen innerhalb nur genau der jeweiligen Klasse und wird nirgendwo sonst verwendet.
Ich meinte, ich würde den Referenzzähler von
shared_ptrim anonymen Namespace machen (wenn ichshared_ptrreimplementieren würde).
-
volkard schrieb:
Eben doch! Der Benutzer hat ein berechtigtes Interesse, umfassend informiert zu werden. Er soll immerhin die Klasse möglichs sachgemäß benutzen. Programmieren ist kein Krieg. Außerdem würde ich mich selber bekriegen. Zum Beispiel der globale Instanzenzähler muß member sein.
Ich ziehe die offene Variante stark vor. Die geschlossene mache ich nur, wenn es fürchterlich uninteressant ist, wenn ich das nicht erwähnen würde, wenn ich die Funktionsweise der Klasse (nicht nur die Schnittstelle) einem Kollegen gegenüber skizzieren würde. Und gaanz selten, um Header-Abhängigkeiten zu reduzieren.Das ist vor allem dann ganz toll, wenn der Benutzer sein so gewonnenes internes Wissen benutzt, und seinen Code daran anpasst. Wenn man dann was an seiner Klasse ändert, hat der Benutzer richtig Spaß. Die offene Variante verleitet zur unsachgemäßen Benutzung.
Der Benutzer hat ein berchtigtes Interesse daran, dass sich etwas wie spezifiziert verhält. Wie das Verhalten erzeugt wird, kann Ihm ziemlich wurst sein.
-
Tachyon schrieb:
Das ist vor allem dann ganz toll, wenn der Benutzer sein so gewonnenes internes Wissen benutzt, und seinen Code daran anpasst. Wenn man dann was an seiner Klasse ändert, hat der Benutzer richtig Spaß. Die offene Variante verleitet zur unsachgemäßen Benutzung.
Der Benutzer hat ein berchtigtes Interesse daran, dass sich etwas wie spezifiziert verhält. Wie das Verhalten erzeugt wird, kann Ihm ziemlich wurst sein.
Anpassung im Rahmen der Spezifikation natürlich. Was sollte denn daran schlecht sein?
Nur, weil Du weißt, wie das Auto funktioniert, benutzt Du es doch nicht unsachgemäß, sondern im Gegenteil, Du benutzt es sachgemäßer.
-
volkard schrieb:
[...]Nur, weil Du weißt, wie das Auto funktioniert, benutzt Du es doch nicht unsachgemäß, sondern im Gegenteil, Du benutzt es sachgemäßer.
Ganz schlechtes Beispiel. Ich kenne einen Haufen Leute, die frickeln unsachemäß herum, weil sie glauben, sie wissen, wie Ihr Auto funktioniert.
-
Tachyon schrieb:
Ganz schlechtes Beispiel. Ich kenne einen Haufen Leute, die frickeln unsachemäß herum, weil sie glauben, sie wissen, wie Ihr Auto funktioniert.
Ok, also merken wir uns:
Deppen sollten anders pr0ggern als Vollprovis, und Deppen haben andere Bedürfnisse an die Bibliotheken und Arbeitskollegen.
Die Frage "class oder namespace" kann also nur im soziokulturellen Kontext betrachtet werden. Aber nicht ohne Einberufung einer Ethikkommission unter Beteiligung aller gesellschaftlich relevanten Gruppen, insbesondere der Kirchen und Gewerkschaften.
-
Also eigentlich denke ich eher an sowas:
Ich schreibe 'ne Klasse, welche von einem anderen Entwickler benutzt werden soll. Weil meine Firma 200000 Mitarbeiter hat und weltweit tätig ist, sitzt dieser Entwickler zufällig in Neuseeland, und ich habe keine Chance, persönlich mit diesem in Kontakt zu treten. Damit alles reibungslos läuft, beschreibe ich alles so gut wie möglich, und bastel das Interface so, dass es gar nicht erst zur Falschbenutzung verleitet.
Das nennt man defensives Programmieren (ein Aspekt), und es soll, so hört man munkeln, durchaus Fälle gegeben haben, in denen dies viel Ärger und unnötige Kosten verhindert hat.
-
Tachyon schrieb:
Ganz schlechtes Beispiel. Ich kenne einen Haufen Leute, die frickeln unsachemäß herum, weil sie glauben, sie wissen, wie Ihr Auto funktioniert.
Frickeln? Du meinst,
privateumgehen.
Ich meine, daß sie Kupplung und Lager schonen, indem sie schalten, wenn die Drehzal paßt, also selbst bei plötzlichem einkuppeln kein riesiger Ruck durchs Auto gehen würde, daß sie die Stahlgürtel schonen, indem sie nicht halbbordsteinparken (auch wenn moderne Reifen das kaum noch brauchen), daß sie es nicht notorisch anschieben oder anrollen lassen, weil das die Lamdasonde verarscht, daß sie wenn der Scheibenwischer nicht durchkommt, weil am Glas festgeeist, sie sofort die Zündung ausmachen (Scheibenwischer abschalten reicht nicht, denn der läuft selbstätig in Ruhestellung zurück, kann er aber nicht -> Motor kaputt), daß sie bei längerem Gefälle die Bremsen schonen und lauter so Sachen. Und das zieht sich weiter bin in die höheren Fahrkünste.
-
Tachyon schrieb:
Also eigentlich denke ich eher an sowas:
Ich schreibe 'ne Klasse, welche von einem anderen Entwickler benutzt werden soll. Weil meine Firma 200000 Mitarbeiter hat und weltweit tätig ist, sitzt dieser Entwickler zufällig in Neuseeland, und ich habe keine Chance, persönlich mit diesem in Kontakt zu treten. Damit alles reibungslos läuft, beschreibe ich alles so gut wie möglich, und bastel das Interface so, dass es gar nicht erst zur Falschbenutzung verleitet.
Das nennt man defensives Programmieren (ein Aspekt), und es soll, so hört man munkeln, durchaus Fälle gegeben haben, in denen dies viel Ärger und unnötige Kosten verhindert hat.ES KANN NICHTS SCHIEF LAUFEN, WENN ICH MICH AN DIE SPEZIFIKATION HALTE.
Natürlich bohre ich die Klasse nicht auf, indem ich mit reinterpret_cast das private umgehe, sondern benutze nur das erlaubte Interface.
Damit ist der defensiven Programmierung doch genüge getan.Wozu zusätzliche Geheimniskrämerei? Doch nur, weil es möglich ist und aus esoterischen Gründen, jedoch nicht, weil es sich mal ausgezahlt hätte in dem Unternehmen mit 200000 Mitarbeitern.
-
volkard schrieb:
[...]
Wohl dem, der 'ne Automatik hat...