Warum sind globale Variablen schlecht?



  • wird dir von globalen Variablen abraten, denn diese haben nur Nachteile

    Stimmt, aber diese 100% Pauschalisierung kann nicht aus dem Artikel stammen und ist IMO wie jedes Dogma schädlich.



  • Irgendwie muss man halt differenzieren.

    Einerseits bringen globale Variablen Probleme mit sich. Daher sollte man Sie möglichst vermeiden. Aber nur weil etwas schlechter Stil ist, es generell abzulehnen ist auch Falsch.

    Im endeffekt zählt Kosten-Nutzen. Wenn ich mir 3 h eine Lösung ohne globale Variablen überlegen muss, aber ich nach 10 Minuten eine Lösung mit Globals habe, dann kann man auch mal ein Global verwenden anstatt auf KRampf zu versuchen sowas zu verwenden.

    Das gleiche gilt für andere Sachen die "Schlechter Stil" sind wie das verlassen von Schleifen mit break etc. Gerade für Anfänger ist es ratsam so zu Programmieren wie man gerade Lust hat und wie man weiterkommt, anstatt die sauberste und effizienteste Lösung sofort parat zu haben.


  • Mod

    Fedaykin schrieb:

    Im endeffekt zählt Kosten-Nutzen. Wenn ich mir 3 h eine Lösung ohne globale Variablen überlegen muss, aber ich nach 10 Minuten eine Lösung mit Globals habe, dann kann man auch mal ein Global verwenden anstatt auf KRampf zu versuchen sowas zu verwenden.

    Das Problem ist aber, dass die Erfahrung lehrt, dass die 10 Minuten Lösung später einmal zu sehr schwer diagnostizierbaren Fehlern führen werden, wenn irgendwann mal unerwartete Seiteneffekte auftreten. Das muss nicht morgen sein, vielleicht erst in ein paar Jahren, wenn andere Entwickler an dem Code arbeiten und der ursprüngliche Programmierer längst weg ist. Und die werden dann sehr viel länger als 3 h an dem Problem sitzen.

    Und deswegen ist guter Stil wichtig. Und guter Stil wird dadurch definiert, dass man damit erfahrungsgemäß später wenig Probleme hat. Und im Normalfall ist es auch nicht so schwer, sich daran zu halten: Ich möchte mal den Fall sehen, wo man durch Verwendung von globalen Variablen tatsächlich 2:50 h einspart und die Lösung wie eine Krampf aussieht.



  • Wenn aber heutzutage jede Sekunde bei der Entwicklung zählt und Termine so knapp bemessen werden das man lieber schnell, als sauber programmiert. Ist das ganze kein Wunder.

    Zusätzlich ist es auch noch ein unterschied ob ich sowas in einer "Multi-Programmer" umgebung programmiere oder in einen Projekt für mich, wo ich absehe das in 3 Jahren das ganze eh nicht mehr anschaue.

    Wie schon gesagt, es kommt auf Kosten-Nutzen an. Dort zählt auch die Zukunftsentwicklung rein.

    Meine Beispiele sind rein theoretischer Natur. Bei globalen Variablen sehe ich das ganze auch eher unkritisch. Aber es wird andere Fälle geben wo sowas eher zuschlägt.

    Ich möchte auch nicht sagen das man ohne Nachzudenken Globals verwenden sollte, sondern das man selber Abwägen soll, ob Sie jetzt Sinnvoll sind oder nicht. Nicht desto trotz ist es natürlich Sinnvoll zu wissen welche Risiken sie bergen. Wer mit dem Wissen immer noch Globals einsetzt, soll es halt tun.



  • Globale und lokale statische Variablen haben mir in der Vergangenheit die meisten Schmerzen bereitet. Mal keine eine lib nicht nebenläufig verwendet werden (aber es wurde eine Allokation gespart), mal ziehen eigentlich kleine Programmänderungen riesige Refaktorierungsmaßnahmen nach sich (don't - ever - call me, I'll call you!), oder man sucht sich den Wolf, um rauszufinden, welcher Schelm den globalen super pointer in undefinierten Zuständen hinterlässt.

    Globale Variablen sind mit ebensolcher Vorsicht zu genießen wie goto. Wenn möglich, vermeiden.



  • Lieber selber die Erfahrung machen und dann nach den eigenen Vorlieben entscheiden. Nur auf Leute hören, die einem etwas näherbringen wollen; alle Leute, die einem etwas vorschreiben wollen, ignorieren.

    Auch aus den Fehlern anderer kann gelernt werden. Man muss nicht jeden Fehler selbst machen, das kostet nur unnoetig Zeit und Nerven.

    Wenn aber heutzutage jede Sekunde bei der Entwicklung zählt und Termine so knapp bemessen werden das man lieber schnell, als sauber programmiert.

    Der groesste Kostenpunkt ist Wartung.



  • knivil schrieb:

    Auch aus den Fehlern anderer kann gelernt werden. Man muss nicht jeden Fehler selbst machen, das kostet nur unnoetig Zeit und Nerven.

    Man muss aber nicht alle Wasserkocher verbieten weil sich einer mal die Hand verbrüht hat.

    Ich wette die meisten "globale Variablen sind böse"-Prediger vertreten hier einfach eine Überzeugung die ihnen irgendwann mal eingeprügelt wurde. Hinterfragt (oder gar selbst Erfahrungen gemacht) wird heute ja eh selten etwas.



  • Aber wenn man anfaengt auf Trolle zu hoeren, die sich nur hinter pauschalen Aussagen verstecken ohne zu argumentieren, ist man eh verloren. Diese nutzen dann auch gleich die Gelegenheit, C++ und den Rest der Welt in den Dreck zu ziehen. Und untermauern ihre Position mit viel GROSSBUCHSTABEN und fett gedrucktem. "Es gibt nicht DIE OPTIMALE LÖSUNG" ist einfach nichts sagend.



  • So Pauschalaussagen wie "Auch aus den Fehlern anderer kann gelernt werden" oder "Der groesste Kostenpunkt ist Wartung"?



  • knivil schrieb:

    "Es gibt nicht DIE OPTIMALE LÖSUNG" ist einfach nichts sagend.

    Diese Aussage ist vielleicht nichtssagend aber diese Aussage ist mir persönlich lieber als "Meine Umsetzung ist besser als deine, mach es gefälligst wie ich!!!!!1elf".



  • knivil schrieb:

    Aber wenn man anfaengt auf Trolle zu hoeren, die sich nur hinter pauschalen Aussagen verstecken ohne zu argumentieren,

    Naja meine pauschale Aussage lag doch nur darin,dass man sich von pauschalen Aussagen & Befehlen anderer fernhalten soll, stattdessen lieber ganz unpauschal herumprobieren und seinen Weg herausfinden.



  • "Es gibt nicht die optimale Lösung" ist keine Pauschalaussage, sondern ein Allgemeinplatz.


  • Administrator

    Kenner der Tatsachen schrieb:

    Diese Aussage ist vielleicht nichtssagend aber diese Aussage ist mir persönlich lieber als "Meine Umsetzung ist besser als deine, mach es gefälligst wie ich!!!!!1elf".
    ...
    Naja meine pauschale Aussage lag doch nur darin,dass man sich von pauschalen Aussagen & Befehlen anderer fernhalten soll, stattdessen lieber ganz unpauschal herumprobieren und seinen Weg herausfinden.

    Zeig mir mal bitte auf, wo hier die Verwendung verboten wurde. Oder wo solche Aussagen gemacht wurden, welche du in diesem Thread anscheinend gesehen haben willst. Ich sehe überall nur, dass davon abgeraten wird oder Empfehlungen abgegeben werden. Du bist der Erste, welcher plötzlich etwas von Verbot gequasselt hat.

    Und übrigens: Man sollte auch in C die Verwendung von globalen Variablen gut bedenken, da die Problematik genau dieselbe ist. Mit C++ Programmierer oder der Sprache C++ hat das überhaupt nichts zu tun.

    Grüssli



  • Globale Variablen sind tötlich, wenn man Multithreading verwendet. Funktionen die in globale Variablen schreiben sind nicht reentrant. Konstanten als globale Variablen machen natürlich nichts.



  • *Man kann natürlich überall ein Mutex um die globalen Variablen machen.



  • Globalisierungsgegner schrieb:

    Globale Variablen sind tötlich, wenn man Multithreading verwendet. Funktionen die in globale Variablen schreiben sind nicht reentrant. Konstanten als globale Variablen machen natürlich nichts.

    Tötlich sind globale Variablen bestimmt nicht. Wenn schon, dann tödlich. Aber egal.

    Geteilte Resourcen sind das, was man beachten muss. Und das können durchaus statische lokale Variablen oder Singletons sein. Damit gelten sie normalerweise nicht als global. Das sind mehr oder weniger unabhängige Probleme.

    Wenn ich auf eine globale Variable nur lesend oder atomar zugreife, dann ist das kein Problem. Auch wenn ich sicher stelle, dass nur ein Thread gleichzeitig darauf zugreift, beispielsweise über einen Mutex, dann ist das auch kein Problem.

    Globale Variablen sind aus anderen Gründen schlecht. Es ist einfach schwer zu durchschauen, wer wann darauf zugreift. Eine Variable, die ich innerhalb einer Funktion definiere, kann ich leicht verifizieren, ob sie korrekt behandelt wird. Je weiter ich den Scope einer Variablen fasse, desto schwieriger wird es. Daher ist es in aller Regel schlechter Stil.



  • ich liebe ja bis heute die "errno" variable im linux kernel, ja das muß schon ein langsames fleckchen erde sein, wenn die auch noch in fast jeder function verwendet werden muß. und stimmt, die fehler suche wird dadurch natürlich schon erschwert. wieso haben sie dafür nur kein singleton verwendet 😉

    lg lolo



  • noobLolo schrieb:

    ...die "errno" variable...

    ...das "errno" symbol...

    lg lolo



  • tntnet schrieb:

    Globalisierungsgegner schrieb:

    Globale Variablen sind tötlich, wenn man Multithreading verwendet. Funktionen die in globale Variablen schreiben sind nicht reentrant. Konstanten als globale Variablen machen natürlich nichts.

    Tötlich sind globale Variablen bestimmt nicht. Wenn schon, dann tödlich. Aber egal.

    Geteilte Resourcen sind das, was man beachten muss. Und das können durchaus statische lokale Variablen oder Singletons sein. Damit gelten sie normalerweise nicht als global. Das sind mehr oder weniger unabhängige Probleme.

    Wenn ich auf eine globale Variable nur lesend oder atomar zugreife, dann ist das kein Problem. Auch wenn ich sicher stelle, dass nur ein Thread gleichzeitig darauf zugreift, beispielsweise über einen Mutex, dann ist das auch kein Problem.

    Globale Variablen sind aus anderen Gründen schlecht. Es ist einfach schwer zu durchschauen, wer wann darauf zugreift. Eine Variable, die ich innerhalb einer Funktion definiere, kann ich leicht verifizieren, ob sie korrekt behandelt wird. Je weiter ich den Scope einer Variablen fasse, desto schwieriger wird es. Daher ist es in aller Regel schlechter Stil.

    Schlechter Stil ist es natürlich auch, aber das Multithreading-Problem ist genauso schlimm. Solche pseudo Optimierungen, wie globale Variablen statt push und pop usw. machen Funktionen für Multithreading untauglich. Gilt natürlich auch für statische lokale Variablen. Sobald die Variable mehr als nur einmal in der Funktion verwendet wird, reicht es noch nicht mal aus nur die Variable mit nem Mutex zu sperren oder nur atomar Zugriffe zu haben, weil du dann plötzlich der eine Aufrufer die Daten des anderen in der Variable stehen hat. Da müsste man dann die ganze Funktion sperren und dann ist die anfängliche "Optimierung" total umgedreht.



  • Habe mich in letzter Zeit etwas genauer damit beschäftigt, was alles der Linker zu meinen Programmen ergänzen muss, damit ein ausführbares Programm daraus wird.
    Auch wenn ich in meinem Programm scheinbar gar keine globalen Variablen verwende (also 'sichtbar' in meinen Quelltexten), so ist es doch erstaunlich, wie viele globale Variablen in meinem Programm trotzdem vorkommen.
    Z.B. Umgebungsvariablen.
    Praktisch jeder Aufruf einer Funktion aus z.B. einer DLL setzt ja auch voraus, dass z.B. stdin / stdout für mein Programm global verfügbar sind (und auch änderbar zur Laufzeit ...). Auch stdin/stdout sind also globale Variablen.
    Wenn ich mich mit GetCommandLine() darüber informieren möchte, wie die Kommandozeile für mein Programm ausgesehen hat, so muss ja auch in einem (globalen) Buffer diese Kommandozeile gespeichert worden sein, immerhin funktioniert die Funktion ja an jeder Stelle meines Programms.
    Überhaupt: Jeder Funktionsname aus einem externen Modul, den mir der Linker 'aufgelöst' hat (egal ob jetzt printf oder GetSystemMetrics oder sonst etwas) ist doch im Grunde auch eine globale (global, weil aus jeder Funktion in meinem Programm aufrufbar!) Funktionszeigervariable! Jede DLL mit dem selben Namen, und den selben exportierten Funktionen, und die der PE-Loader zufällig als erste findet, könnte der Funktionszeigervariablen 'printf', die in meinem Programm vorkommt, einen gültigen (und somit zuhöchst variablen ..) Wert zuweisen. Dazu kommen noch die 'implizten' Resourcen, die ohnehin jedem Prozess zur Verfügung stehen, der eine entsprechende DLL geladen hat, und die somit global verfügbar sind (also egal innerhalb welcher Funktion meines Programms ich z.B. GetStockObject(WHITE_BRUSH) aufrufen würde, das zurückgegebene Handle war ohnehin schon immer im Global Scope meines Prozesses vorhanden ...).
    Es kommt natürlich auch darauf an, wie weit man den Begriff 'Global Scope' fasst. Wenn man all jene globalen Variablen dazuzählt, die vom PE-Loader oder der CRT initialisiert werden, die für den Programmierer zwar nicht sichtbar (aber dennoch global erreichbar und oft auch manipulierbar) sind, dann könnte man den Eindruck gewinnen, dass globale Variablen eher die (notwendige) Regel als die Ausname sind, ohne die praktisch gar kein Programm mehr lauffähig wäre.
    Zum Glück sind alle diese 'implizit initialisierten' globalen Variablen für den Programmierer nicht sichtbar, sodass er weiterhin in dem Glauben programmieren kann, keine globalen Variablen zu verwenden ...
    mfg


Anmelden zum Antworten