Anti-Patterns mehrere Punkte
-
hustbaer schrieb:
Globale Variablen = böse" gilt z.B. für quasi alle Sprachen.
Wird damit eigentlich vorhandener globaler Zustand kritisiert, oder dass der globale Zustand oft in primitiven Variablen ohne Zugriffsschutz implementiert wird?
Weil globaler State ist ja oft keine Erwägungssache, sondern lässt sich meistens gar nicht vermeiden, z.B. Einstellungen der Software. Eine angeschlossene Datenbank ist ja oft auch nur eine Art "globale Variable", nur dass sowas dann wieder nicht verpönt ist.
-
Mal nachgehakt schrieb:
Wird damit eigentlich vorhandener globaler Zustand kritisiert, oder dass der globale Zustand oft in primitiven Variablen ohne Zugriffsschutz implementiert wird?
Letzteres. Globale Variablen bringen viele Probleme mit sich (schlechte Überwachung der Zugriffe und damit schwieriges Debuggen, Threadsicherheit, grosse Abhängigkeiten der Programmkomponenten...).
Globaler Zustand ist eigentlich immer vorhanden und an sich nichts Schlechtes. Man muss ihn an der richtigen Stelle behandeln, genauer gesagt an möglichst wenig Orten. Bei guter Kapselung kann man trotz globalen Zuständen schön objektorientiert arbeiten. Zum Beispiel war OpenGL vor allem in den Anfängen eine einzige State-Machine mit globalem Status, trotzdem arbeiten darauf aufbauende Bibliotheken mit eigenständigen, lokalen Objekten (Meshes, Sprites, Texturen...).
-
@Mal nachgehakt:
Damit meine ich, dass zu oft angenommen wird dass es Dinge "eh nur ein mal gibt", und diese dann als globale Variable oder Singleton ausgelegt werden.
Wie darauf zugegriffen wird ist dabei erstmal nebensächlich.
Genau so ob das ganze threadsafe gemacht wird oder nicht. Wobei es natürlich doppelt schlimm ist wenn es nicht threadsafe ist.Guck dir beispielsweise die DevIL (aka. OpenIL) an. Der ganze state (aktuelles Bild, die States der Library etc.) ist global. So richtig global, also nichtmal "threadlocal". Das ist das KO für viele Projekte, wo entweder viele Threads die Image-Library gleichzeitig verwenden sollen (ohne sich gegenseitig durch das Locken einer globalen Mutex auszubremsen), bzw. wo Programm-Komponenten unabhängig voneinander entwickelt werden (wenn ich Komponente A entwickle, und die DevIL verwende, und ein anderer Komponente B entwickelt, und ebenso die DevIL verwendet, und irgendwann Komponenten A und B gleichzeitig genutzt werden, dann knallts.)
Nochmal konkret dazu
Weil globaler State ist ja oft keine Erwägungssache, sondern lässt sich meistens gar nicht vermeiden, z.B. Einstellungen der Software
Die Einstellungen einer Applikation müssen doch bitte nicht global sein. Es gibt ein Applikations-Objekt und ggf. ein User-Objekt, da kann man Einstellungen speichern (je nachdem welchen Scope sie haben).
Dann kann man auch mal die gleiche Applikation 2x im selben Prozess laufen lassen.
Bei vielen Applikationen wird das nie vorkommen, bei einigen aber schon.Ganz schlimm wird es dann, wenn jemand Library-Code unter solchen Annahmen schreibt. Also ne Library baut, die diverse User- oder Applikations-Einstellungen einfach in globale Variablen klatscht. Dann kann man seine Library nämlich u.U. für Serveranwendungen und dergleichen vergessen, weil die Annahme "gibts nur ein mal" nicht mehr zutrifft.
----
Mir ist schon klar dass es immer irgendwo einen Punkt gibt, wo vorausgesetzt wird dass es etwas nur 1x gibt. Nur diesen Punkt sollte man ganz weit zurückdrängen. Darum geht's.
-
Nexus schrieb:
Globale Variablen bringen viele Probleme mit sich (schlechte Überwachung der Zugriffe und damit schwieriges Debuggen
Wenn man einen halbwegs vernünftigen Debugger hat, ist das kein Problem.
-
also schrieb:
Nexus schrieb:
Globale Variablen bringen viele Probleme mit sich (schlechte Überwachung der Zugriffe und damit schwieriges Debuggen
Wenn man einen halbwegs vernünftigen Debugger hat, ist das kein Problem.
"Debuggen" kann viel mehr bedeuten als "etwas im Debugger laufen lassen".
Globale Variablen ohne Zugriffsschutz (bzw. allgemein Daten auf die man "einfach so" zugreifen kann) können ein Programm sehr unübersichtlich machen. Der Debugger hilft da oft gar nicht, da man unmöglich alle Pfade die ein Programm nehmen kann im Debugger durchspielen kann.
-
hustbaer schrieb:
also schrieb:
Nexus schrieb:
Globale Variablen bringen viele Probleme mit sich (schlechte Überwachung der Zugriffe und damit schwieriges Debuggen
Wenn man einen halbwegs vernünftigen Debugger hat, ist das kein Problem.
"Debuggen" kann viel mehr bedeuten als "etwas im Debugger laufen lassen".
Globale Variablen ohne Zugriffsschutz (bzw. allgemein Daten auf die man "einfach so" zugreifen kann) können ein Programm sehr unübersichtlich machen. Der Debugger hilft da oft gar nicht, da man unmöglich alle Pfade die ein Programm nehmen kann im Debugger durchspielen kann.
Die Begründung ergibt keinen Sinn. Man kann auch nicht bei allen möglichen anderen Variablen alle Pfade durchspielen, wenn man ein etwas komplexeres Programm hat. Ist einfach ein zeitliches Problem.
Wenn ich wissen will, wer eine globale Variable ändert, setze ich einfach einen Data Breakpoint. Das geht sogar viel einfacher, als festzustellen, wer ein Member einer bestimmten Instanz ändert. Die Adresse der globalen Variable hab ich einfach, die einer Membervariable nicht so schnell. Einen Breakpoint in einem Setter setzen bringt da oft nicht viel, wenn es tausende Instanzen gibt und mich nur eine interessiert. Soll jetzt nicht bedeuten, dass globale Variablen gut sind, aber debuggen wird deshalb auch nicht schwerer.
-
Schneiderei11 schrieb:
(3) Hat diese ganze Anti-Pattern Thematik nicht eigentlich einen ziemlich
'scherzhaften' Unterton, d.h. geht's dabei primär darum, dass man sich über
Quellcode lustig macht, den man selber nicht versteht (weil man ihn nicht
entwickelt hat + weil er schlecht dokumentiert ist),Einen scherzhaften Unterton - ja, sicherlich.
Das hat aber Methode. Die pragmatischen Projektleute in der Softwarewelt kommen in der Fachliteratur überwiegend aus den USA, und dort ist der knochentrockene Stil nicht so üblich. Außerdem ist es einfacher den Leuten ihre Fehler vorzuhalten, wenn man es "nett verpackt".
Schneiderei11 schrieb:
(4) Sind diese Anti-Patterns eigentlich nur für die objektorientierte
Programmierung von Belang, oder auch für andere Programmierparadigmen?
Weil ja eigentlich jeder prozedurale Quellcode laut diesen Kriterien
schon mal grundsätzlich ein Anti-Pattern wäre ...Du schreibst hier ständig "Quellcode" - das Konzept eines Antipattern geht durchaus über "Quellcode" oder "schlechten Quellcode" hinaus.
Der Quellcode kann im Rahmen eines Antipattern sogar sehr gut, qualitativ hochwertig sein - trotzdem kann das Projekt an "Death-March" oder "Scope-Creep" leiden.
Bei Antipatterns handelt es sich um fehlerhafte Verhaltensweisen beim Lösen von Problemen, die man aber immer wieder gerne anwendet weil sie sich gut und brauchbar anfühlen.
Insofern ist das nicht auf OOP beschränkt - man kann sogar sagen, daß viele der Antipattern als "globale Projektverhaltensfehler" nicht einmal auf die Softwarewelt beschränkt sind.
Als Beispiel, das Thema "Scope-Creep" ist auch häufig in der Bauindustrie anzutreffen.
-
erstmal bestes Danke für die instruktiven Antworten.
globale variablen sind oft unvermeidlich, wenn mehrere threads ihre jeweiligen
'neuesten Erkenntnisse' untereinander kommunizieren sollen. in einer einzel-
thread anwendung kann man die globalen variablen aber häufig vermeiden.bezüglich meines chameleon objekts ist auch das problem, dass es genau so
eine globale variable ist, wo bei einem parallelen listen()-thread kommandos
von einem server kommen, und dann soll der listen()-thread die update()-Schnitt-
stelle von dem chameleon austauschen dürfen, aber die update() Schnittstelle
muss auch immer genau so heißen, weil sie von einemm Framework regelmäßig
angesprungen wird. naja, ist halt eine schwierige angelegenheit und mir
ist erstmal nur die möglichkeit mit dem austauschen der funktionszeiger
(durch den listen() thread) eingefallen. Leider können die funktionszeiger
auch von anderen stellen im programm ausgetauscht werden (auch von dort, wo
eigentlich nur
'lesend' mit ->update() gearbeitet werden sollte.)
@hustbaer - werde mich dann mal genauer mit dem state-entwurfsmuster beschäftigen, vielleicht lässt sich mein programm damit ja auch 'sauberer'
lösen.
mfg
-
Schneiderei11 schrieb:
@hustbaer - werde mich dann mal genauer mit dem state-entwurfsmuster beschäftigen, vielleicht lässt sich mein programm damit ja auch 'sauberer'
lösen.
mfgSchau Dir auch das Strategy- und das Bridge-Muster an. Das sind zwei weitere Ausprägungen "deiner" Idee. Die wesentlichen Unterschiede bestehen darin, wer das Verhalten zur Laufzeit austauscht und zu welchem Zweck die drei Pattern verwendet werden. Der Aufbau ist fast identisch.
-
Schneiderei11 schrieb:
--- Meine aller freundlichste Einladung zum (gerne auch scherzhaften)
Smalltalk zu diesem Design-Anti-Patterns Thema, weil ich find's einfach nur
witzig, dass die überwältigende Mehrheit der RL-Software mit diesen scheinbar
ungeeigneten Patterns erstellt wurde und trotzdem oft tadellos funktioniert.Das ist eine (imho) fehlerhafte Wahrnehmung. Die überwältigende Mehrheit aller Software Projekte im RL SCHEITERT. Und irgendwann haben sich halt Leute hingesetzt und der Frage gestellt: Warum ist das so? Was haben diese Projekte gemeinsam? Daraus sind Anti-Patterns entstanden. Getreu dem Satz: Der kluge Mensch lernt aus seinen Fehlern, der weise Mensch aus den Fehlern der Anderen.