Hallo,
Auf eine Klasseninstanz / Objekt soll in verschiedenen Klassen in
verschiedenen Files zugegriffen werden können.
Ich sehe jetzt nur die Möglichkeiten.....
Verwenden von extern oder durchreichen von Pointern auf das Objekt oder
die Klasse als Sinleton anzulegen.
Am saubersten aber aufwendigsten wäre wohl das Durchreichen von nem
Pointer auf das Objekt, auf das ich in der jeweiligen Klasse zugreifen
will.
Singleton ginge wäre aber wohl zweckentfremdet.
Extern ginge auch.... aber ... unsauberer?
Gibt es Alternativen oder was wäre die gute Lösung?
Wie immer ist die Antwort auf die Frage "welcher Pattern passt" halt
"kommt drauf an".
Singleton ist ok, wenn du dir absolut, 100% sicher bist, dass es nie
Sinn macht dass es mehrere dieser Objekte gibt. Plausibler Kandidat
wären z.B. die globalen Konfigurationsoptionen des Programms. In allen
anderen Fällen macht durchreichen erfahrungsgemäß mittelfristig weniger
Ärger.
Janosch schrieb:> Am saubersten aber aufwendigsten wäre wohl das Durchreichen von nem> Pointer auf das Objekt, auf das ich in der jeweiligen Klasse zugreifen> will.
Genau.
> Singleton ginge wäre aber wohl zweckentfremdet.
Singleton ist das Pattern um ein Objekt einmalig zu initialisieren und
wird praktisch nur im Kontext globaler Variablen benutzt.
> Extern ginge auch.... aber ... unsauberer?
Das wäre lediglich die zugehörige globale Variable (deren
Initialisierung iwie sichergestellt werden muss).
Ob Singleton/Global oder Durchreichen hängt vom Kontext ab. Häufig ist
beides gleichermaßen schlecht. ;-)
Dann formulier mal die Lehrbuchlösung.
Eine weitere mir eingefallene Lösung wäre entsprechende Membervariable
der Klasse mit static zu declarieren.
Jede Instanz dieser Klasse kann dann auf die statische Membervariable
zugreifen.
Ich würde keinen Singleton verwenden. Das Pattern
hat zu viele Nachteile und ist auch aus der Mode
gekommen. Auch keine sonstigen technischen Spielereien.
Die sauberste Lösung meiner Meinung nach wäre das
injecten des "globalen" Objektes in die Objekte
hinein, die das verwenden wollen. Und das nur unter
Verwendung eines Interfaces. So werden Abhängigkeiten
minimiert.
Allerdings solltest du deine Klassenstruktur überdenken.
Wenn es viele Klassen gibt, die auf das Objekt zugreifen
wollen/müssen, stimmt was nicht.
merciless
Die Klasse soll einen 1ms Timer counter bereitstellen.
Jedes andere Klassenobjekt, das nur alle x Zeiteinheiten was machen
soll, soll auf diese Timer Klasse zugreifen können.
Die Timer Klasse wird mittels Observer Pattern jede 1ms im Isr kontext
upgedatet und zählt in einer TimerCount Klasse eine statische
Membervariable hoch.
Jedes andere Objekt, das eine Zeitinformation braucht, instanziiert die
TimerCount Klasse und hat Zeitinformationen.
Da war meine Überlegung eben, wie diese Zeitinformation anderen Objekten
zugänglich machen.
Fragen die einzelnen Klassen die "Uhrzeit" ab
und entscheiden, ob sie was machen sollen weil
z.B. 100ms vergangen sind? Wenn dem so ist, dann
würde ich da eher eine Scheduler-Klasse schreiben,
die diese Aufgabe übernimmt.
Und ein Objekt instantiieren, um an eine statische
Info zu kommen klingt mir overdosed: dafür gibt
es public static Methoden.
merciless
Janosch schrieb:> Dann formulier mal die Lehrbuchlösung.
Du hattest das Für und Wider bereits geschrieben. :-) Wenn du ein
bisschen im Netz schaust, wirst du zum Thema einiges an Diskussion
finden.
Das Durchreichen ist die "bessere" Lösung. Man kann an den
Funktionsköpfen bereits sehen, welche Parameter verwendet werden. Die
Kunst besteht darin, lange Parameterlisten zu vermeiden. Ansonsten wird
der Code schnell unverständlich.
Hast du bereits ein Projekt, wo das Durchreichen quasi ein
Refactoring/Redesign erfordert, dann greifst du eher zum globalen
Zugriff. Das macht den Code schwerer durchschaubar, da es "versteckte"
Parameter gibt. Dokumentation ist angesagt. (Ich habe hier so ein
historisch gewachsenes Projekt, wo es so viele Singletons und globale
Kontexte gibt, dass man absolut im Wald steht.)
Ist es dein eigenes Projekt, mach' es wie es für dich am "einfachsten"
ist. Die Lehrbuchlösung gibt es leider nicht.
Mikro 7. schrieb:> Das Durchreichen ist die "bessere" Lösung.
Bei der Aufgabenstellung scheint es sich um ein Art Hardwarezugriff zu
handeln (für den Timer gilt „es darf nur einen geben“). Da ist eine dann
globale und/oder statische Instanz doch eine sinnvolle Lösung.
Oliver
Oliver S. schrieb:> Mikro 7. schrieb:>> Das Durchreichen ist die "bessere" Lösung.>> Bei der Aufgabenstellung scheint es sich um ein Art Hardwarezugriff zu> handeln (für den Timer gilt „es darf nur einen geben“). Da ist eine dann> globale und/oder statische Instanz doch eine sinnvolle Lösung.>> Oliver
Für die Abstraktion des Hardwaretimers schon, aber nicht für den 1ms
Observerpattern Timer, der ist nicht einzigartig. Was passiert z.B. wenn
man einige der Funktionalitäten, die aktuell den 1ms Timer nutzen, auf
0.24ms umstellen muss?
mh schrieb:> Für die Abstraktion des Hardwaretimers schon, aber nicht für den 1ms> Observerpattern Timer, der ist nicht einzigartig. Was passiert z.B. wenn> man einige der Funktionalitäten, die aktuell den 1ms Timer nutzen, auf> 0.24ms umstellen muss?
Das seh ich auch so. Meine Vorschlag wäre daher sowas:
Dirk K. schrieb:> Allerdings solltest du deine Klassenstruktur überdenken.> Wenn es viele Klassen gibt, die auf das Objekt zugreifen> wollen/müssen, stimmt was nicht.
Huh? Bestes Beispiel: ein Logger. Wird überall im Programm benötigt, es
soll aber natürlich nur eine Instanz geben.
Ist doch das Normalste der Welt :-)
Ein guter Ansatz ist, shared Pointer auf die Instanz herumzureichen. Nur
so kann jede Klasse mit UnitTests versehen werden. Falls das zu viel
Aufwand ist: dafür gibt es Dependancy Injection Frameworks. Die nehmen
einem die Arbeit ab ;-)
Quixy schrieb:> Dirk K. schrieb:>> Allerdings solltest du deine Klassenstruktur überdenken.>> Wenn es viele Klassen gibt, die auf das Objekt zugreifen>> wollen/müssen, stimmt was nicht.>> Huh? Bestes Beispiel: ein Logger. Wird überall im Programm benötigt, es> soll aber natürlich nur eine Instanz geben.> Ist doch das Normalste der Welt :-)>>> Ein guter Ansatz ist, shared Pointer auf die Instanz herumzureichen. Nur> so kann jede Klasse mit UnitTests versehen werden. Falls das zu viel> Aufwand ist: dafür gibt es Dependancy Injection Frameworks. Die nehmen> einem die Arbeit ab ;-)
Ja, das ist dann genau die Ausnahme, die die Regel bestätigt ;)
Ich hatte eher einen Timer im Sinn, den Zugriff auf Hardware
oder ähnliches.
Und man braucht nicht gleich ein DI-Framework. In meinen
Applikationen mache ich das von Hand. Die Objekte werden
in einer Klasse erzeugt und Abhängigkeiten injiziert.
So kann ich das an zentraler Stelle ändern (für Tests etc).
merciless
Injiziert heißt in dem Fall schlicht, die Objektinstanz per Konstruktor
oder Methode zu übergeben oder nicht? Damit wäre es doch das "einfache"
Durchreichen per Zeiger?
Jan schrieb:> Injiziert heißt in dem Fall schlicht, die Objektinstanz per Konstruktor> oder Methode zu übergeben oder nicht? Damit wäre es doch das "einfache"> Durchreichen per Zeiger?
Ja, technisch nichts anderes, als einen Pointer
in das Objekt reinzureichen.
merciless
Quixy schrieb:> ein Logger. Wird überall im Programm benötigt, es> soll aber natürlich nur eine Instanz geben.
Welche Instanz? Da hat man ne Log Funktion, fertig. Eventuell auch ein
Macro, um noch die Zeile, Spalte, Funktionsname, etc. mitzugeben.
DPA schrieb:> Quixy schrieb:>> ein Logger. Wird überall im Programm benötigt, es>> soll aber natürlich nur eine Instanz geben.>> Welche Instanz? Da hat man ne Log Funktion, fertig. Eventuell auch ein> Macro, um noch die Zeile, Spalte, Funktionsname, etc. mitzugeben.
In einer funktionalen Welt ja, in einer
objektorientierten hat man eine Instanz.
merciless
Dirk K. schrieb:> In einer funktionalen Welt ja, in einer> objektorientierten hat man eine Instanz.
Es gibt ja rein theoretisch auch die Möglichkeit, ein bisschen
pragmatisch nachzudenken und nicht blind einem Pattern nachzulaufen ...
Sven B. schrieb:> Dirk K. schrieb:>> In einer funktionalen Welt ja, in einer>> objektorientierten hat man eine Instanz.>> Es gibt ja rein theoretisch auch die Möglichkeit, ein bisschen> pragmatisch nachzudenken und nicht blind einem Pattern nachzulaufen ...
Jo, ich bin auch Pragmatiker. Der TO hatte
aber nach einer guten Lösung gefragt, nicht
nach einer pragmatischen. Overengineering
ist eh eines der größten Probleme beim Entwerfen
von Software-Architekturen.
merciless
Sven B. schrieb:> Es gibt ja rein theoretisch auch die Möglichkeit, ein bisschen> pragmatisch nachzudenken und nicht blind einem Pattern nachzulaufen ...
So ein Logger braucht nun mal eine ganze Menge an Daten:
- File Handles (wenn er in dateien Loggt)
- Netzwerkverbindungen (wenn er auf einem Server loggt)
- Thread-Handles (da das Logging vorzugsweise in einem abgekoppelten
Thread laufen soll)
- Queues für die Logbotschaften
- Timer für das Zeitstempeln der Botschaften
- Etc.
Das lässt sich wunderbar in einer Klasse kapseln. Warum sollte man sowas
nicht OOP lösen wollen?
Wenn man das braucht, kann man das natürlich machen. Die meisten
Menschen wollen einfach nur ein paar Zeilen Text nach stdout schreiben.
Dazu braucht man keine Klasse.
Quixy schrieb:> So ein Logger braucht nun mal eine ganze Menge an Daten:> - File Handles (wenn er in dateien Loggt)> - Netzwerkverbindungen (wenn er auf einem Server loggt)> - Thread-Handles (da das Logging vorzugsweise in einem abgekoppelten> Thread laufen soll)> - Queues für die Logbotschaften> - Timer für das Zeitstempeln der Botschaften> - Etc.
Nein, ein Logger muss nur 3 dinge können: /dev/log unix socket öffnen,
eine rfc5424 (wenn man structured data braucht) oder rfc3164 konforme
Logmeldung zusammensetzen, und dann mit send die Logmeldung
wegschreiben. Fertig. Filtern, übers Netzwerk, in Dateien schreiben,
etc. erledigt der Systemlogger. Für rfc3164 gibts sogar eine Standard
Funktion dafür: syslog(3). Ernsthaft, es gibt nichts nervigeres als sich
mit den Logs solcher abnormalen Programme Herumschlagen zu müssen und
aufzuräumen, die meinen, sie könnten das besser selbst und anders lösen.
Selbst nach stdout loggen und durch logger pipen ist besser als was man
sonst so für mist in den "professionellen" Programmen sieht.
DPA schrieb:> Nein, ein Logger muss nur 3 dinge können: /dev/log unix socket öffnen,
Das mag für deine 200-Zeilen-Pickel-Nerd-Linux-Progrämmchen gelten, aber
es gibt Bereiche im echten Leben, die haben höhere Anforderungen z. B.
Medizingeräte und deren Anwendungssoftware.
Quixy schrieb:> DPA schrieb:>> Nein, ein Logger muss nur 3 dinge können: /dev/log unix socket öffnen>> Sicher, dass das auch auf Windows, MacOS und Android funkioniert?
Auf MAX OS X ist es glaub ich /var/run/syslog, auf BSD und anderen
unixoiden wurde es teils nach /var/run/log verschoben. Muss man halt mit
stat die 3 Dateien testen, bis man eine gefunden hat. Und bei Windows
und Android macht man halt entweder ein ifdef und reicht die Daten der
Logfunktion an die Systemnative weiter, oder linkt einfach eine
alternative Implementation der Funktion für die Platform, genauso wie
man das bei allen anderen Systemspezifischen Sachen auch macht.
Vermutlich lassen sich auch dafür irgendwo schon fertige logging
libraries finden, wenn man das Rad nicht unbedingt neu erfinden will.
Professioneller schrieb:> DPA schrieb:>> Nein, ein Logger muss nur 3 dinge können: /dev/log unix socket öffnen,>> Das mag für deine 200-Zeilen-Pickel-Nerd-Linux-Progrämmchen gelten, aber> es gibt Bereiche im echten Leben, die haben höhere Anforderungen z. B.> Medizingeräte und deren Anwendungssoftware.
Wie gesagt, syslog ist ein standard, genau wie die syslog Funktion.
Gerade in diesen Umgebungen sollte man sie nutzen, statt selbst was über
kompliziertes zu stricken. Kliniken haben in der regel auch eine
IT-Infrastruktur mit Syslog Server, zumindest wird das in manchen PDFs
erwähnt, wenn man "Medizin Syslog" googelt. Wobei, spezialisierte
Medizingeräte haben vermutlich ein komplett anderes System als anderes
zeug, und wenn dort überhaupt was geloggt wird, dann in der regel keine
Daten um das Programm zu analysieren, sondern Patientendaten, wann es
sich einschalten und auf irgendwelches zeug reagieren musste, und
solches zeug, also keine Logmeldungen in dem sinne, und damit auch nicht
mit normalem logging in anderen bereichen vergleichbar. In diesen
Geräten wird man im Hauptprogramm wohl auch keine spezielle Logger
Klasse finden, vermutlich gar keine Klassen. Ironischerweise sind die
Systeme oft trotzdem, oder gerade deshalb, oft weniger sicher als
sonstige, normale Systeme. Dafür laufen keine dafür aber wohl keine
Logfiles voll.
DPA schrieb:> und wenn dort überhaupt was geloggt wird, dann in der regel keine> Daten um das Programm zu analysieren
Natürlich, unter anderem genau dafür loggt man, um nachzuvollziehen was
im Feld passiert ist.
Ich habe das Beispiel Medizin gebracht, weil ich selbst seit >20 Jahren
Software für Computertomographen schreibe. Früher C++/MFC, heute C#/.NET
(unter Windows 10 :P)
Professioneller schrieb:> Früher C++/MFC, heute C#/.NET> (unter Windows 10 :P)
OMG, Ich wünschte ich müsste nicht alle Krankenhäuser meiden, wenn ich
dem entkommen wollte.
DPA schrieb:> Professioneller schrieb:>> Früher C++/MFC, heute C#/.NET>> (unter Windows 10 :P)>> OMG, Ich wünschte ich müsste nicht alle Krankenhäuser meiden, wenn ich> dem entkommen wollte.
Ich sehe ein Weltbild einstürzen, ...
Professioneller schrieb:> DPA schrieb:>> und wenn dort überhaupt was geloggt wird, dann in der regel keine>> Daten um das Programm zu analysieren>> Natürlich, unter anderem genau dafür loggt man, um nachzuvollziehen was> im Feld passiert ist.> Ich habe das Beispiel Medizin gebracht, weil ich selbst seit >20 Jahren> Software für Computertomographen schreibe.
Nicht aus dem Kontext reissen:
DPA schrieb:> Wobei, spezialisierte> Medizingeräte haben vermutlich ein komplett anderes System als anderes> zeug, und wenn dort überhaupt was geloggt wird, dann in der regel keine> Daten um das Programm zu analysieren
Mit "spezialisierte Medizingeräte" meine ich Herzschrittmacher,
Blutreinigungsgeräte, und solche speziellen Geräte. Software für normale
PCs bei weniger direkt lebensgefährlichen Systemen würde ich eher wie
die restlichen PCs in dem Umfeld betrachten, ob das jetzt in einem
Computertomographen steckt oder nicht. Das sind komplett andere arten
von Systemen.
Professioneller schrieb:>> OMG, Ich wünschte ich müsste nicht alle Krankenhäuser meiden, wenn ich>> dem entkommen wollte.>> Ich sehe ein Weltbild einstürzen, ...
Keine angst, das da etwas zu viele Windowssysteme in Krankenhäusern
herumstehen war mir schon klar. man liest ja auch immer mal wieder, wenn
die IT dort mal wieder vergisst die Updates oder ein mit der
Spezialsoftware inkompatibles Antivirusprogramm auszuschalten, und ne OP
dann deshalb abgebrochen werden muss, usw. Und dann gabs ja auch mal
noch die durch WannaCry lahmgelegten Krankenhäuser...