Was ist eine globale Variable und warum soll man sie nicht benützen?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Die Frage ist jetzt: Wie kompliziert wird es, wenn man keine globale Variable benützt?

Dazu ein Bespiel: die Anwendung besteht aus verschiedenen Modulen, die miteinander über eine gemeinsame Queue kommuinizieren. Die bisherige Lösung war: einfach das Kommunikationsmodul importieren und dort die als globale Variable bereitgestellte Queue benützen.

Die Lösung ohne globale Variable könnte jetzt so sein:

Das Mainscript erzeugt die als lokale Variable Queue und importiert alle Module, welche die Queue brauchen. Darin muß es dann eine init Funktion geben, die mit dieser Queue als Parameter aufgerufen wird, Anschließend sollte diese init Funktion durch eine Dummy init Funktion ersetzt werden, damit nicht noch jemand anderes die Initialisierung ein zweites Mal aufruft.

Wer es aber trotzdem tut, hat ein Problem, wenn er eine eigene Queue erzeugt, die dann den anderen Kommunikationspartnern unbekannt ist.

Problematisch könnte auch werden, daß man dann vom Kommunikationsinterface bereitgestellte Klassen nicht so einfach benutzen kann, weil man diesen dann die gemeinsame nicht global bekannte Queue als Paramater übergeben muß. Damit hat man dann Kassen mit eingeschränkter Benutzung.

Der Sinn wäre eigentlich, die Klassen zu benützen und die Queue nicht zu kennen, denn was geht dem Anwender die Qeue an?
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: bei Dir ist alles falsch herum.
Wie kompliziert wird es, wenn man globale Variablen benutzt?

Dazu ein Beispiel: die Anwendung besteht aus mehreren Klassen, die miteinander über Queues kommunizieren. Die korrekte Lösung ist, wenn man von einer zentralen Stelle die Klassen initialisiert, die miteinander kommunizieren sollen und ihnen das Queueexemplar übergibt.

Die Probleme kommen auf, wenn man jetzt globale Variablen benutzt:
Jedes Modul nimmt sich einfach von irgendwoher eine globale Queue. Da muß man jetzt irgendwelche Verrenkungen machen, dass man die Initfunktion nicht zum zweitenmal aufruft, weil die globale Queue gibt es ja nur einmal, was dann zu Chaos führen würde. Damit hat man dann Klassen mit eingeschränkter Benutzung.

Der Sinn wäre eigentlich, die Klassen flexibel zu benützen, und nicht auf eine globale Queue angewiesen zu sein.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:Dazu ein Beispiel: die Anwendung besteht aus mehreren Klassen, die miteinander über Queues kommunizieren. Die korrekte Lösung ist, wenn man von einer zentralen Stelle die Klassen initialisiert, die miteinander kommunizieren sollen und ihnen das Queueexemplar übergibt.
Nein, das ist nicht die richtige Lösung, denn die Queue geht keinen etwas an. Daher soll diese an niemand per Parameter übergeben werden!!!

Man macht ja auch nicht:

Code: Alles auswählen

import os

ossystem = Boot_PC_with('Windows 7.0')
os.init(ossystem)
python.init_os(ossystem) # damit man dann File lesen kann
open('myfile','r')
Aber die erste Zeile 'import os' haut dann schon mal nicht hin
BlackJack

@Alfons Mittelmeyer: Also die bisherige Lösung war ein Kommunikationsmodul mit einer globalen Queue auf die jeder zugegriffen hat. Aber übergeben darf man die Queue nicht weil die niemanden etwas angeht. Wenn die niemanden etwas anginge, dann dürfte man sie ja erst recht nicht einfach so global zur Verfügung stellen. Deine Argumentation macht keinen Sinn.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Wenn die niemanden etwas anginge, dann dürfte man sie ja erst recht nicht einfach so global zur Verfügung stellen. Deine Argumentation macht keinen Sinn.
Die macht, schon Sinn. Sie sollte dem Kommunikationsmodul selber natürlich zur Verfügung stehen. Wenn das Kommunikationsmodul in C geschrieben wäre, wäre es kein Problem, diese Queue nach außen hin zu verbergen, da gibt es etwa static. Wie verbirgt man sie aber in Python, damit keiner darauf zugreifen kann außer die Funktionen im Kommunikationsmodul.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: bei einer Kommunikation sind mindestens zwei beteiligt. Jetzt fängst Du an, etwas zu verstecken, so dass nur einer drauf zugreifen kann. Das ergibt wirklich keinen Sinn. Das einfachste, damit zwei kommunizieren können, ist, dass derjenige, der die Kommunikation initiiert, den Kanal als Argument übergibt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: bei einer Kommunikation sind mindestens zwei beteiligt. Jetzt fängst Du an, etwas zu verstecken, so dass nur einer drauf zugreifen kann. Das ergibt wirklich keinen Sinn. Das einfachste, damit zwei kommunizieren können, ist, dass derjenige, der die Kommunikation initiiert, den Kanal als Argument übergibt.
Also die Queue habe ich ja versteckt, nämlich in einem anderen Objekt. aber das verlagert ja nur das Problem, dafür gibt es eben dann dieses andere globale Objekt.

Normalerweise sendet man eine Message etwa mit:

Code: Alles auswählen

comm.send(message_id,parameter)
Wer aber dieses globale Objekt kennt, kann es auch tun mit :

Code: Alles auswählen

comm.proxy.send(message_id,parameter)
Die Frage ist, was ist das Problem mit dieser globalen Variablen, warum soll ich sie als Parameter übergeben? Es braucht sie ja keiner. Und wenn doch einer darauf zugreift und dann den längeren Ausdruck verwenden will, was schadet das?
BlackJack

@Alfons Mittelmeyer: Dann geht es nicht um die Queue, sondern dass das `comm`-Objekt jetzt globalen Zustand besitzt. Also müsste man den Kommunikationspartnern *dieses* Objekt als Argument übergeben, damit die nicht auch hart kodiert von diesem globalen Zustand abhängig sind. Beziehungsweise sollte es möglich sein so einem Objekt die Queue zu übergeben und mehrere davon zu erstellen, damit es nicht dieses eine globale Objekt mit globalen Zustand gibt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack: Es gibt ja auch kein globales Objekt auf das alle zugreifen. Jeder Kommunikationpartner bekommt eine eigene Instanz. Nur die GuiApp importiert die erweiterten Widgetklassen und dort wird dann auch das übergebene Proxy Objekt abgespeichert, damit man in der GuiApp bequem send ohne eine unötige Referenz auf ein Widget benützen kann. Was hätte auch Nachricht senden mit einem Widget zu tun

Bei nur zwei Kommunikationspartnern wird jeweils ein eigenes Proxyobjekt übergeben, wobei das eine das andere kennt. Bei mehr als zwei Kommunikationspartnern wird jeweils ein Proxyobjekt übergeben, welches ein zentrales Proxyobjekt kennt, und das ist auch nicht global. Die Kommunikationspartner wissen also überhaupt nichts über die anderen.

Für die GuiAppp ist es auch kein Problem, denn wer macht schon etwa:

gui_1 = tk.Tk(Proxy())
...

gui_2 = tk.Tk(Proxy())
....

gui_1.mainloop()

gui_2.mainloop()
Antworten