# Verwaltung von Objekten in statischen Listen



## oetzi (19. Jul 2011)

Hallo zusammen,

bei meiner Webanwendung habe ich bis jetzt beim Serverstart Objekte (die sehr häufig gebraucht werden) aus einer Tabelle komplett geladen und in einer ArrayList<Objekt1> der Klasse K1 gespeichert. Diese Klasse K1 habe ich bis jetzt umständlich in den Application Context geschoben, um von überall Zugriff drauf zu haben.

Jetzt habe ich einen anderen, zugegebenermaßen viel einfacheren, Ansatz ausprobiert.
Ich speichere jetzt die Objekt1-Objekte einfach in einer statischen ArrayList<Objekt1> (weiterhin in der Klasse K1) und greife über statische Methoden drauf zu. (z.B. K1.getById(1); )

Erste Tests verliefen erfolgreich.

Was ich mich jetzt frage ist, ob dieser 2. Ansatz grundsätzlich so okay ist, oder ob es irgendwelche Nachteile hat solch eine Objektverwaltung über den statischen Ansatz zu erledigen? 

Wenn das so okay ist, würde ich auch noch den Rest der Anwendung umstellen. Da dies aber ein recht großer Aufwand wäre, möchte ich kurz eure professionelle Meinung hören 

Schönen Gruß,
oetzi


----------



## Marco13 (19. Jul 2011)

Von Spezifika bei Webanwendungen habe ich keine Ahnung, deswegen alles unter Vorbehalt, bis sich ein Experte dazu äußert:

Irgendwas statisch zu machen weil "das so praktisch ist", und ganz allgemein Objekt auf die man "von überall Zugriff haben" muss klingen nach einem Designfehler (und bei "normalen" Anwendungen i.a. ein so schwerer, dass ich mir kaum vorstellen kann, dass das bei Webanwendungen anders ist, aber nochmal: Vielleicht ist das in dem Zusammenhang OK... :bahnhof: ). Vielleicht wäre es interessant, zu wissen, was das für Objekte sind. Die vordergründigen Probleme bei "static" (auch in der häufig anzureffenden Form von "mißbrauchten Singletons") ist, dass es keine zwei Objekte der gleichen Art geben kann, und dass es schwer sein kann, den Zustand so zu verwalten, dass er "global richtig" ist. Die pragmatische Frage bei sowas wie

```
class SomeClass {
    static List<Something> list = ...
}
```
ist: Ist die _Liste_ eine _Eigenschaft_ der _Klasse_? Meistens eher nicht...

Aber mal schauen, was andere dazu sagen...


----------



## oetzi (19. Jul 2011)

Hi Marco,

danke schon mal für deine Meinung.
Als Hintergrundinfo hier mal ein Beispiel:
Es handelt sich um ein Rollenspiel und in so einem Rollenspiel dürfen natürlich jede Menge Items nicht fehlen. Auf diese Items muss halt von verschiedensten Stellen drauf zugegriffen werden. 
Items werden 
- getragen
- verkauft
- gefunden
- von Monstern getragen und fallen gelassen
- etc.

Daher ist es halt genau der Punkte, dass ich von überall bzw. halt an sehr vielen Stellen drauf zugreifen können muss. 

Das Problem, dass es keine 2 Objekte geben kann, habe ich ja auch, wenn ich diese globale Item Liste anderweitig speichere (z. B. im application context wie eingangs beschrieben). Hier behelfe ich mir mit tiefen Kopien von Objekten, wenn es nötig ist.


----------



## Marco13 (19. Jul 2011)

Vielleicht erbarmt sich ja doch noch ein Webanwendungs-Experte...?

(Bis dahin: Gibt es tatsächlich sowas wie ein "Globales ItemRepository", das ALLE (im ganzen Universum verfügbaren) Items speichern soll? Oder hat nicht z.B. jeder Spieler seine eigene Liste von Items, und die "Welt" eine Liste von Items, die von Monstern fallen gelassen wurden und so...? Nochmal: Ich kenne die für diese Fälle "üblichen" Archtitekuren nicht, deswegen alles unter Vorbehalt)


----------



## SlaterB (19. Jul 2011)

es gibt keinen Grund die Welt ernster zu sehen als sie ist,
in Spezialfällen wie z.B. Testframeworks kann es mit static Schwierigkeiten geben (muss selbst dann nicht),
in vielen einfachen Programmen reicht es vollkommen, wozu auch einfache Webanwendungen zählen

und das beste: man lernt den Nachteil am deutlichsten, wenn man erstmal static hat und dann irgendwann tatsächlich von selber auf Probleme trifft die zum Umstellen zwingen,
nicht nur im Voraus irgendwelche Buch-Gespenster verfolgt,

großer Aufwand ist ein Gegenargument, aber das ist schon ein recht zentrales Thema, da darf man auch bisschen investieren,
zumal strukturiertes Umschreiben von Methodenaufrufen usw. eigentlich schnell von der Hand geht

-------

wenn es unbedingt gleich besser sein muss, kann eine mögliche Strategie Basisklassen sein,
wer immer allgemein verfügbare Dinge braucht ruft nicht
Klasse.getXy() statisch auf,
und auch nicht manuell
getApplicationContext().getAttribute() mit Cast usw.
sondern einfach nur getXy(),
diese Methode stellt eine Basisklasse einmalig bereit (ob aus ApplicationContext oder statisch oder sonstwoher),
alle wichtigen Klassen erben davon, schon haben alle die Methode und die Daten wenn es grundsätzlich funktioniert

bestes Beispiel ist der ApplicationContext selber, wo kommt der denn her? ist nicht statisch, denn bei sowas großen macht man es natürlich gleich besser,
und es ist wie vorgeschlagen: der ApplicationContext kommt aus einer Methode der Basisklasse, 
wie er dorthin kommt, dass muss in der API einmal korrekt umgesetzt werden, 
aber alle Millionen Einzelanwendungen muss das nicht kratzen, sie haben den Context und fertig,

genauso dein Programm: eine Basisklasse die die Arbeit schafft, der Rest profitiert davon auf die kürzestmögliche Art


----------



## oetzi (19. Jul 2011)

SlaterB hat gesagt.:


> selber auf Probleme trifft die zum Umstellen zwingen, nicht nur im Voraus irgendwelche Buch-Gespenster verfolgt


genau, blind irgendwas nach Schema F machen möchte ich nicht. Darum diskutiere ich es ja hier mit den Experten ;-)
Und die Umstrukturierung würde auch noch einiges mehr als nur die Items betreffen, so dass der Aufwand schon erheblich wäre.

okay, die Idee mit der Vererbung kann ich vom Grundprinzip nachvollziehen. 
Ich sehe nur hier nicht genau den Vorteil. 
Ob ich in der Basisklasse mir eine Itemliste aus einer statischen Liste besorge und hierfür getter und setter anbiete, oder ob ich einfach diese statische Liste direkt in meiner "erbenden" Klasse verwende macht doch eigentlich technisch gesehen keinen Unterschied. Ich habe nur mehr Overhead durch die Vererbung. 
Und in meinem Fall habe ich auch immer nur eine Klasse, die Zugriff auf diese statischen Listen braucht (jeweils eine andere). So dass von einer Basisklasse immer nur eine Klasse erben würde.


Verstehe ich das aber richtig:
Es gibt grundsätzlich keine konkreten Nachteile durch diese statische Verwendung? Also abgesehen von der einmaligen statischen Natur der Objekte, mit der man dann leben muss bzw. darf


----------



## SlaterB (19. Jul 2011)

der Unterschied ist, dass du gegebenenfalls die Implementierung in der Basisklasse austauschen kannst,
das ist dann nur 1x statt an 100 Stellen, die anderen Klassen brauchst du gar nicht anfassen

wie gesagt braucht man im einfachen Fall darüber kaum nachdenken, ein prominentes Beispiel ist System.out, welches statisch super funktioniert,
aber wenn man irgendwann irgendwas komplizierter braucht, z.B. unterschiedliche Programmausgaben (Debug, Error) usw. dann greift man zum Logger,
für dein Programm möchte ich mir jetzt gar nicht erst was ausdenken, siehe Marco13, siehe Threads zu Singleton

> Es gibt grundsätzlich keine konkreten Nachteile durch diese statische Verwendung? 

der Nachteil ist feste Verknüpfung, die eigenten wann immer möglich vermieden wird,
ein Etagenplan spricht nur von Raum 1, 2, 3, es muss nicht jeweils
Erde, Deutschland, Hamburg, Mustermannstraße 7, Etage 4, Raum 1,
Erde, Deutschland, Hamburg, Mustermannstraße 7, Etage 4, Raum 2
...
heißen, auch wenn das jetzt ein blödes Beispiel ist,
statisch zementiert, ist nicht mehr zu ändern


----------



## oetzi (20. Jul 2011)

Morgen



SlaterB hat gesagt.:


> für dein Programm möchte ich mir jetzt gar nicht erst was ausdenken, siehe Marco13, siehe Threads zu Singleton



Habe mir jetzt einige Seiten rund um Singletons, statische Klassen und Threads durchgelesen.
Wenn ich das korrekt verstanden habe ist sowohl der Singleton als auch eine statische Klasse nicht von Natur aus Threadsicher, so dass ich mich auf jeden Fall drum kümmern muss, wenn ich denn Threads einsetzen würde.
mhh, und wenn ich so drüber nach denke... Bei meinem Beispiel handelt es sich ja um Art Itemverwaltung, die größtenteils dafür da sein soll, bestehende Items anzubieten. Geändert wird keines dieser Items zu Laufzeit. Müsste ich das ganze dann überhaupt threadsicher machen? Meiner Meinung nach nicht. 




SlaterB hat gesagt.:


> statisch zementiert, ist nicht mehr zu ändern


Hier verstehe ich glaube ich nicht genau wie du das meinst. Ich kann doch auch meine statische Klasse/Methoden ändern wenn ich das möchte. 


Der Knackpunkt ist bei mir folgender: Ich habe mich jetzt lange genug mit meiner bisherigen Lösung rumgeärgert und suche jetzt halt nach einer besseren Lösung 
Das ganze über den ApplicationContext zu lösen funktioniert zwar in 90% der Fälle mehr oder weniger reibungslos, aber z. B. beim Serverstart exisitert der applicationContext noch nicht, so dass ich hier teilweise über zig Klassen und Methoden hinweg Objekte durchreichen muss. Das macht die Fehlersuche nicht gerade einfach 
Ich wäre also natürlich auch offen für andere gute Lösungen für solch ein Problem. Ich formuliere es mal so: "Zugriff auf eine zentrale Ressourcenverwaltungskomponente aus einer Webanwendung heraus"


----------



## maki (20. Jul 2011)

> Ich formuliere es mal so: "Zugriff auf eine zentrale Ressourcenverwaltungskomponente aus einer Webanwendung heraus"


Was ein absolutes Standardproblem in der  Java WebApp Entwicklung ist, und nicht nur dort.

Wenn du ein DI Framework nutzt, ist die Lösung offensichtlich, falls nicht, kannst du auch den AppContext nutzten (verstehe dein Problem damit nicht), oder du nutzt ein GoF Singleton (XXX.getInstance()), oder nur eine statische Liste.

Die Tatsache dass sich diese Daten zur Laufzeit nicht ändern erspart dir Ärger mit der Synchronisation und dadurch entstehende Flaschenhälse.

Nutzt du denn irgendein Web Framework?


----------



## SlaterB (20. Jul 2011)

oetzi hat gesagt.:


> Hier verstehe ich glaube ich nicht genau wie du das meinst. Ich kann doch auch meine statische Klasse/Methoden ändern wenn ich das möchte.



eine statische Methode hat keinen Bezug zu irgendetwas, ist nicht gut unsichtbar zu modifizieren,
eine normale Methode kann je nach Rest, nach aktuellen User, nach Programmbereich usw. anders reagieren,

wird ohne konkrete Beispiele nicht sehr überzeugend, ich weiß, 
aber ich bin ja auch eigentlich eher auf der Seite 'static ist schon ok' 

es wäre übrigens noch vorstellbar, der statischen Methode weitere Parameter zum Zustand zu übergeben, z.B. den ApplicationContext,
da kann man sich etwas im Kreis drehen


----------



## oetzi (20. Jul 2011)

@maki: 
Ich nutzte struts2 als Webframework. Kein Spring, falls du das mit DI Framework meintest 
Wobei mir jetzt gerade der Einsatz von Spring in diesem Bereich als sehr nützlich erscheint. Habe allerdings nur sehr rudimentäre Erfahrungen damit. 

Zu dem Problem mit dem AppContext: 
Ich habe ein Servlet welches beim Start des Servers ausgeführt wird und hier meine "Ressourcenverwalter" (RV) z. B. mit den Items füllt. Diese RV werden dann in den AppContext gepackt. 
Führt ein User später eine Aktion durch, welche diesen Item-RV benötigt, hole ich ihn einfach aus dem AppContext und alles ist gut.
Probleme habe ich eigentlich nur in dem erwähnten Start-Servlet. Wenn ich, nach dem Item-RV in den AppContext gepackt worden ist, an einer anderen Stelle Zugriff auf diesen brauche. Z. B. um Geschäften die Items zuzuweisen, die dort verkauft werden. Während des Serverstarts funktioniert der Zugriff über den AppContext nicht, so dass ich dann z. B. den Item-RV immer mit übergeben muss (teiweise halt über mehrere Methodenaufrufe hinweg), damit er genutzt werden kann. Und das ist halt eine Sonderlocke nur für den Serverstart, also irgendwie sehr unschön. 




> Die Tatsache dass sich diese Daten zur Laufzeit nicht ändern erspart dir Ärger mit der Synchronisation und dadurch entstehende Flaschenhälse.


mhh, was hat das Ärger ersparen mit der Synchronisation mit der Entstehung von Flaschenhälsen zu tun? Wodurch sollen hier genau Flaschenhälse entstehen?


@SlaterB: 
Zumindest grob verstehe ich was du damit meinst 


Ich tendiere mittlerweile schwer dazu das re-engineering Richtung statische RessVerwalter durch zu führen. Sollte das irgendwann zu schwerwiegenden Problemen führen lerne ich wenigstens etwas daraus ;-)


----------



## maki (20. Jul 2011)

> Zu dem Problem mit dem AppContext:
> Ich habe ein Servlet welches beim Start des Servers ausgeführt wird und hier meine "Ressourcenverwalter" (RV) z. B. mit den Items füllt. Diese RV werden dann in den AppContext gepackt.
> Führt ein User später eine Aktion durch, welche diesen Item-RV benötigt, hole ich ihn einfach aus dem AppContext und alles ist gut.
> Probleme habe ich eigentlich nur in dem erwähnten Start-Servlet. Wenn ich, nach dem Item-RV in den AppContext gepackt worden ist, an einer anderen Stelle Zugriff auf diesen brauche. Z. B. um Geschäften die Items zuzuweisen, die dort verkauft werden. Während des Serverstarts funktioniert der Zugriff über den AppContext nicht, so dass ich dann z. B. den Item-RV immer mit übergeben muss (teiweise halt über mehrere Methodenaufrufe hinweg), damit er genutzt werden kann. Und das ist halt eine Sonderlocke nur für den Serverstart, also irgendwie sehr unschön.


Naja, wenn du sowas in den AppContext packst, dann hast du eben Abhängigkeiten zur Servlet Spec, wenn deine "Businessklassen" nix vom AppContext wissen sollen, musst du ihnen das eben anderweitig zur Verfügung stellen.
Denke du solltest das Design nochmals überdenken und deine Abhängigkeiten besser organisieren.
Wer braucht denn während des "Serverstarts" Zugriff auf die Daten und ist kein Servlet?



> mhh, was hat das Ärger ersparen mit der Synchronisation mit der Entstehung von Flaschenhälsen zu tun? Wodurch sollen hier genau Flaschenhälse entstehen?


Wenn sich die Daten ändern würden, müsstest du synchronisieren beim Zugriff auf die Daten, d.h. dass nur ein User gleichzeitig auf die Daten zugreifen könnte -> flaschenhals
Eine WebApp hat eben grundsätzlich Threadsicher zu sein.


----------



## oetzi (20. Jul 2011)

maki hat gesagt.:


> Naja, wenn du sowas in den AppContext packst, dann hast du eben Abhängigkeiten zur Servlet Spec, wenn deine "Businessklassen" nix vom AppContext wissen sollen, musst du ihnen das eben anderweitig zur Verfügung stellen.
> Denke du solltest das Design nochmals überdenken und deine Abhängigkeiten besser organisieren.
> Wer braucht denn während des "Serverstarts" Zugriff auf die Daten und ist kein Servlet?



Aktuell sieht mein Konstruktor eines solchen RessVerwalters so aus:

```
//get the ActionContext
ActionContext context = ActionContext.getContext();
Map<String,Object> appCon = context.getApplication();
//appCon == null at server start
if (appCon != null){
...
```
Und diese appCon != null Überprüfung habe ich überall drin, weil halt beim Start des Servers dieser noch null ist. Warum auch immer?!



maki hat gesagt.:


> Wenn sich die Daten ändern würden, müsstest du synchronisieren beim Zugriff auf die Daten, d.h. dass nur ein User gleichzeitig auf die Daten zugreifen könnte -> flaschenhals
> Eine WebApp hat eben grundsätzlich Threadsicher zu sein.


Ach, sorry. Hatte den Satz beim ersten Mal anders gelesen bzw. missverstanden.


----------

