Global state

tuedel

Aktives Mitglied
Grüße euch!!

Heute hätte ich mal eine Designfrage. Ein recht interessanter Thread, der die Diskussion in eine ähnliche Richtung führt findet sich hier:

java - Why are static variables considered evil? - Stack Overflow

Es geht mir darum, dass ich bisher einen relativ großen Teil meiner Variablen die ich als "statisch" verstanden auch als solches definiert habe. Unter dem Aspekt das sie entweder zur Laufzeit gesetzt und nicht mehr geändert werden oder das sie sich zur Laufzeit ändern können und einen momentanen Zustand ausdrücken, der Einfluss auf mehrere Abläufe nimmt.

Nun stelle ich mir die Frage, wie ich das Ganze straightforward konstruieren könnte, um Lesbarkeit, Threadsavety und ähnliches zu erhalten, bzw. Fehler durch global state zu vermeiden. Einen Schritt den ich getan hatte, war es einen Großteil in Enums abzulegen, um in diesen die Werte zu schreiben.

Bsp. Code:

Java:
public enum Fonts {

        FOOTER_MARK, FOOTER_DEFAULT, FOOTER_DATE,
        FOOTER_MATCH_RACE_BTN, FOOTER_MATCH_RACE_TEXT;

        private Font localFont;

        public Font getValue() {
            return localFont;
        }

        private void setValue(Font newFont) {
            localFont = newFont;
        }
    }

private void initFonts(){

font_raceTimer = Font.createFont(Font.TRUETYPE_FONT, givenpath);

Fonts.FOOTER_MARK.setValue(font_raceTimer.deriveFont(Font.BOLD, 15));
Fonts.FOOTER_DATE.setValue(font_raceTimer.deriveFont(Font.BOLD, 15));
}

Durch

Java:
Fonts.COLOR_CHOOSER.getValue();

kann ich mich auf diese Weise über die Enum Bezeichner zum gewünschten Wert hangeln. Jetzt könnte man natürlich auch die Werte direkt als final static bspw. setzen oder als static, falls sie sich ändern könnten. Zudem habe ich auch Werte, die ich gern ohne neuen build anpassen würde. Für diesen Fall würde ich eine properties file setzen.

Nun kann ich aber bspw. nicht in der properties file Instanzen einer BufferedImage vorhalten. Letztlich also nur den Pfad und die Objektinstanz vorhalten. Statisch oder an ein anderes Objekt gebunden.

Meine Frage ist nun eigl. recht simpel. Wie würdet ihr den Aufbau solch zum Teil finaler Werte vornehmen und jener, die sich zur Laufzeit ändern können. Ich wäre geneigt für die sich ändernden Werte eine Objektinstanz zu veranschlagen, bspw. eine Config Instanz. Abgesehen davon müsste der Zugriff aber dennoch easy to read sein. So wie mir das bisher eigl. mit den Enums ganz gut gefällt, die aber prinzipiell nicht an ein Objekt gebunden sind.

Abgesehen davon missfällt mir bei der properties file die Verwendung von Strings um die Werte abzugreifen - ich wäre versucht den Inhalt (Integer, Strings, usw.) wieder in Enum Instanzen zu schreiben, um den Pfad zu der entsprechenden Information leicht lesbar zu halten.

Ich freue mich auf eure Antworten.
LG
tuedel
 

Marco13

Top Contributor
Ja, sooo viel werde ich da nicht dazu sagen, aber das mit den enums ist ja nur eine Ausprägung von statics - statt der Enum könnte man auch eine Klasse wie
Java:
class FontHolder 
{
    void setFont(Font font) { ... }
    Font getFont() {...}
}
erstellen. Und wenn man sich klarmacht, dass man das auch als
Java:
class Holder<T>
{
    void set(T t) { ... }
    T get() { ... }
}
schreiben könnte, merkt man vielleicht, dass das irgendwie ganz anders ist, als das, was sonst überall gemacht wird ;) Grundsätzlich gibt's ja schon sowas wie den UIManager, mit lauter static-Methoden zum setten/getten von Properties. Es GIBT sicher Fälle, wo sowas angebracht ist. Aber eine pauschale Aussage dazu, wann static OK ist und wann nicht, überlasse ich gerade mal anderen...
 

Volvagia

Top Contributor
Was spricht denn gegen die Kapselung in Instanzen? Du schreibst, dass sie einfach gelesen werden können sollen. Aber ist es denn wichtig, dass ein anderer Teil des Programms weiß, in welcher Schriftart der Fooder z. B. das Datum darstellt?
 

tuedel

Aktives Mitglied
Das Argument, dass ein anderer Programmteil nicht die Schriftart des Footers kennen muss, ist richtig. Allerdings mag ich die Vorstellung an einer zentralen Position die teilweise finalen oder sich nur geringfügig ändernden Werte zu pflegen. Ich möchte nicht bei dem Bedarf einer Änderung mich in die gewünschte Instanz hangeln und "auf Suche gehen". Wenn ich an der zentralen Stelle dann der Namenskonvention folge - bspw. FOOTER_DATE - kann ich den Wert schnell und unkompliziert editieren.
 
M

maki

Gast
Allerdings mag ich die Vorstellung an einer zentralen Position die teilweise finalen oder sich nur geringfügig ändernden Werte zu pflegen.
Mag ja sein, aber wenn du globale Variablen nutzt, verstösst du da schon gegen die Regeln der OO und der Rest wird dann auch nicht mehr besser...

Gewöhne dir globale Variablen ab, einen wichtigeren Rat gibt es IMHO an dieser Stelle nicht.

Globale "Konstanten" dagegen sind unproblematisch.

FOOTER_DATE zB. kann ich mir unmöglich als Konstante vorstellen, wenn da ein aktuelles Datum drinnstehen soll.
 

tuedel

Aktives Mitglied
Der Wert für FOOTER_DATE bezog sich auf die Enums - war schlecht ausgedrückt. Die Anweisung via Enum hätte dann so ausgesehen:

Java:
Fonts.FOOTER_DATE.getValue();
 
T

tröööt

Gast
hmm ... es gibt unterschiede zwischen dem SO-thread und diesem hier ... denn auf SO wurde grundsätzlich über static diskutiert ... hier wird aber eingeschränkt nur über static-variablen geredet ...

ich bin da persönlich folgender meinung : es sollte im code grundsätzlich nur ein static geben ... und zwar das von main ...
zusätzlich kann man es noch für konstanten, factories und utility-klassen/-methoden nutzen

es ist schon eine persönliche designentscheidung wo man wie static nutzt ... aber bis auf main dürfte es immer einen anderen weg geben
 

Marco13

Top Contributor
Ich hatte es schon gelegentlich so zusammengefasst: Methoden sollte man IMMER static machen, wenn man sie (ohne Umwege) static machen kann. Fields sollte man NIE static machen, außer wenn man sehr, sehr genau weiß, was man da tut.
Eigentlich ist das noch etwas unpräzise, da es hier ja sowohl dem Titel als auch dem Inhalt nach um den statischen Zustand geht (und da ist es in mancher Hinsicht egal, ob er direkt oder über Methoden verändert wird). Aber gerade bei solchen GUI-Settings ist das ein Spezialfall, wo man auch einen statischen Zustand in betracht ziehen kann. Wenn man überall und immer eine Instanz einer Klasse "MyVerySpecialGuiSettings" an jede noch so kleine Hilfsmethode, die nur einen Button erstellt, weiterreichen muss, ist das ein Krampf. Wie schon angedeutet ist z.B. der UIManager (Java Platform SE 6) komplett statisch, und da der Fall eher unwahrscheinlich ist, dass man zwei Buttons (auf Basis dieses globalen Zustandes) unterschiedlich gestalten will, oder dort irgendwo Polymorphie o.ä. reinkommen soll, ist das IMHO auch OK.
 

tuedel

Aktives Mitglied
Man könnte ja auch argumentieren, dass wenn ich OO arbeiten möchte, dass die Verwaltung der Zustände von einem dafür vorgesehenen Objekt vorgenommen wird. Nehmen wir bspw. an, dass sich der Footer aus 5 UI Komponenten zusammensetzt. Sollte sich ein Zustand vor der Initialisierung dieser Komponenten ändern, stehen die 4 verbleibenden ja in Abhängigkeit zu dieser Änderung. In diesem Fall würde ich annehmen, dass die Anpassung der anderen Zustände bei dem jeweiligen Objekt schwierig lesbar wird. Wohingegen der Manager das zentral für einen Pool an möglichen Zuständen vornimmt.

Wenn man das bpsw. in dieser Form umsetzen würde, wäre mir dennoch wichtig eine Hierarchy zu finden, bei der der Zugriff über das Managerobjekt auch bei der Entwicklung plausibel ist, aber möglichst abstrakt bleibt. Unter diesem Gesichtspunkt hatte ich mich für die Enums entschieden, weil der Enumklassen Name den Typ signalisiert und der value die Zuordnung.

Ich hätte daher überlegt, in die Manager Klasse die Enums als Keys für entsprechende Hashmaps zu führen. Allerdings wäre das wieder nicht allzu stark abstrakt. Wie würdet ihr sowas umsetzen? Sagen wir eine Manager Klasse die Cached Images, Fonts, Colors, Strings, usw. verwaltet und einen plausiblen und easy to read Zugriff ermöglicht. Oder haltet ihr dieses Vorgehen für eher ungünstig?!
 

Ähnliche Java Themen

Neue Themen


Oben