class ProjectConfig {
String owner = "unknown";
Managers managers = new Managers();
}class Managers {
String classLoaderManager = "ds.managers.ClassLoaderManager";
String classManager = "ds.managers.ClassManager";
String instanceManager = "ds.managers.InstanceManager";
}
> > >
> > > Bist du sicher, dass die Klasse "Managers" statt "Manager" heißen soll? Ich bin leider nicht so sehr in diesem Thema drin, aber so wie du diese Strings speicherst, klingeln bei mir die Alarmglocken.
> > So wie oben zusehen, sind die zugewiesenen Strings eigentlich nur die Standard-Einstellungen, quasi würde das Programm erst ProjectConfig instantiieren, dann die eigentliche Projektkonfiguration aus einer Datei lesen und entsprechende Veränderungen in der ProjectConfig-Instanz überschreiben.
> Ich denke du solltest das "new Managers()" in den Konstruktor der ProjectConfig Klasse packen. Dann kannst du nämlich beim erzeugen der Projekt-Konfiguration die entsprechenden direkt mitgeben. Damit machst du dir auch Unittests viel einfacher.
> > (Und zu dem Managers/Manager-Namen: Ich hab 3 verschiedene Manager-Typen
> Warum hast du dann nicht 3 Klassen für die unterschiedlichen Manager-Typen?
> Wenn ich dich richtig verstehe, dann willst du wie gesagt 3 verschiedene Manager Klassen haben, wobei du von jeder Klasse eine Instanz beim Initialisieren der Projektkonfiguration übergibst. Später kann man dann in der Projektkonfiguration einfach ein "set"
> Für mich leider noch nicht so richtig. Könntest du vielleicht ein Code-Beispiel geben?
Ich merke, ich muss noch viel weiter ausholen als gedacht.
Es gibt für die Manager 3 Schnittstellen
IClassLoaderManager, IClassManager und IInstanceManager.
Nachdem die Konfiguration geladen ist. Wird das eigentliche System initialisiert.
Da habe ich eine Singleton-Klasse namens Registry, welche die unteranderem die die Manager-Instanzen erzeugt und dann griffbereit hält.
Grundlegend sieht die Initialisierung der Manager dann so aus:
~~~java
try {
classLoaderManager = createClassLoaderManager(projectCfg.getManagers().getClassLoaderManager());
} catch (Throwable e) {
// loggen dass konfigurierter Manager nicht geht
classLoaderManager = new ClassLoaderManager(/* daten */);
}
Für die anderen Manager sieht das ganze vom Prinzip her genauso aus.
Aber das ganze ist eigentlich schon viel zu weit im dahinter stehendem System und hat mit dem eigentlichen Problem nicht mehr viel zu tun.
Hier meinte ich die Autovervollständigung der IDEs. Bei
(new ProjectConfig()).getManagers().getInstanceManager()
kann man halt die Autovervollständigung der IDEs verwenden. Bei einer Liste aber(new CfgListe()).get("managers.instancemanager");
würde das nicht mehr funktionieren.
Woher kommt jetzt CfgListe?
CfgListe sollte hier irgendeine Klasse sein die das List-Interface implementiert (dabei wäre ich dann auch schon bei dem Problem dass ich List<Entry<String, Object>> benutzen müsste, oder Zahlen/Boolean auch als String im Speicher halten müsste)
Ah, ich glaube langsam verstehe ich etwas besser.
Wenn du es mit den Interfaces machst wie beschrieben, dann hast du den großen großen Vorteil, dass du in deinem Codebeispiel schon zur Compilezeit eine Fehlermeldung kriegen würdest, weil der Compiler erkennen würde, dass die Instanz "cfg" das Interface "ReadableConfiguration" implementiert und daher gar keine "setInstanceManager()" Methode hat. Es würde also keine UnsupportedOperationException werfen, sondern schon in der IDE würde man sofort sehen, dass die setInstanceManager() Methode gar nicht aufgerufen werden kann, die getInstanceManager() Methode hingegen schon. Gleiches gilt natürlich für setOwner().
Das mit der Autovervollständigung bezug sich nur auf das List.get("cfg.managers.instancemanager")
vs. ProjectConfig.getManagers().getInstanceManager();
da man sich das "cfg.managers.instancemanager" merken müsste.
CfgListe meineconfig = new CfgListe(new InstanceManager(), new SonstwasManager(), ...);
meineconfig.getInstantManager();
Mach ein Interface "ReadableProjectConfiguration", welches NUR die getXXX Methoden vorschreibt.
Mach danach ein Interface "WritableProjectConfiguration", welches ReadableProjectConfiguration implementiert und dann zusätzlich alle setXXX Methoden vorschreibt.
Hier steckt wieder eine "flache" Struktur wie bei einer Liste dahinter, ich würde gerne eine geschachtelte Struktur beibehalten wollen.
Für die Konfiguration der eigentlichen Instanzen der Plugins muss ich auf Listen zurückgreifen, das will ich übersogenannte Profile erreichen, diese sollen von einander erben können, angenommen die Projekt-Konfiguration ist als XML-Datei gespeichert, so hab ich folgende Struktur (Profile haben 1 bzw. 2 Eigenschaften, einen Dateinamen und optional noch ein Parent-Profil)
<profile name="default.ini">
<profile name="general_1.ini">
<profile name="specificA.ini" />
<profile name="specificB.ini" />
</profile>
<profile name="specificC.ini" />
</profile>
Quasi würde in der ProjectConfig-Klasse noch ein weiterer Member stecken:
class ProjectConfig {
String owner = "unknown";
Managers managers = new Managers();
Profile profile = new Profile();
}
class Profile {
String name = "default.ini";
Profile parent = null;
Profile getParent() {
return parent;
}
}
Durch die Verschachtelung hab ich dann nicht einfach nur IConfigReadable, IConfigWriteable und dessen Implementation, sprich 4 Dateien, sondern Gruppierungsklassen (Also Profile, ProjectConfig, Managers, usw) mal 4 Dateien.
Ich würde das ganze lieber so machen, dass ich eine Klasse schreibe, die beides Implementiert und dann eine allgemeine Wrapper-Klasse die das eigentliche Objekt readonly macht.
So, dass ich nur noch Grupperungsklassen*3 + 1 (der Readonly-Wrapper) Dateien habe.
MfG
bubble
If "god" had intended us to drink beer, he would have given us stomachs. - David Daye