Interface Laden der Konfiguration über Interfaces sinnvoll?

Gromit

Mitglied
Hallo,

ich bin mir unsicher, was die Umsetzung einer Lösung angeht. Mein Java-Projekt lädt Konfigurationsdaten aus externen Dateien ein. Die Konfigurationen sollen zentral durch einen ConfigManager verwaltet werden. Nun dachte ich, dass ich das Laden und Verarbeiten in andere Klassen auslagere, die das Interface IConfigLoader implementieren.

1. Wenn ich jetzt beispielsweise die Konfiguration zur Farbpalette im ConfigManager abspeichern möchte, wäre diese Art und Weise dann sinnvoll?

Java:
public class ConfigManager {

    private ColorPalette colorPalette = null;

    public void setColorPalette(IConfigLoader loader) {
        colorPalette = (ColorPalette) loader.getConfig();
    }

}

Die Klasse ColorPaletteLoader implementiert IConfigLoader und übernimmt das Laden der Farbpalette. Das Interface schreibt eine Methode getConfig() vor, die ein Objekt vom Typ IConfig zurückgibt. ColorPalette implementiert IConfig.

Java:
public interface IConfigLoader {

    public IConfig getConfig();
    public void load(String fileName);
    
}

2. Was würdet ihr anders machen? Kennt ihr (bessere) Beispiele?
 
Füg dann aber bitte Generics hinzu, so dass du den konkreten Typen der Configs bereits kennst, also [c]ConfigLoader<ColorPalette>[/c] o.ä. 🙂
 
1) lass das >I< weg ... das ist nicht java ... sondern C ...
2) warum so umständlich ... reichen properties nicht ?

1: Ist es irrelevant was man an einen Namen dranhängt oder nicht, es hilft aber zu erkennen, was was ist (wir haben in den Guidelines, dass hinten ein If drankommt wenn es ein Interface ist und noch einiges mehr, das in den Guidelines anders steht, aber wir leben schon länger sehr gut damit)
Ausserdem ist C++ in bestimmten Belangen Java überlegen, warum also darauf herumhacken.

2: Weil es möglicherweise einfach so sein muss.

Arbeitest du bei Microsoft? Die neigen auch dazu Antworten zu geben die nicht falsch sind, aber auch kein bisschen weiter helfen.

Zur Sache:
Wir hier (unsere Firma) neigen eher dazu überall Interfaces einzusetzen, wo nicht zwingend die ganze Klasse bekannt sein muss und es gibt durchaus auch mehrere Interfaces, hinter denen aber dieselbe Klasse steckt.

Nach dem Motto "so wenig bekannt geben wie unbedingt nötig" wird immer das kleinstmögliche Interface eingesetzt.

Ich behaupte nicht das sei die allein seligmachende Weisheit und es ist an manchen Orten übertrieben, aber es schadet auch nichts. Der Vorteil ist, dass Klassen aufgesplittet oder gemerged werden können, ohne dass das grosse Änderungen nach sich zieht. (Nein, das machen wir nicht jeden Tag)
 
1: Ist es irrelevant was man an einen Namen dranhängt oder nicht, es hilft aber zu erkennen, was was ist (wir haben in den Guidelines, dass hinten ein If drankommt wenn es ein Interface ist und noch einiges mehr, das in den Guidelines anders steht, aber wir leben schon länger sehr gut damit)

Jede vernuenftige IDE zeigt an, ob man eine Klasse oder ein Interface hat. Anders gefragt: Ist es ueberhaupt von Interesse, ob man grad mit einer Klasse oder einem Interface arbeitet?

Ich halte nix von saemtlichen Pre- oder Postfixen (I oder If bei Interfaces, m_ fuer Instanzvariablen, ...).

Ausserdem ist C++ in bestimmten Belangen Java überlegen, warum also darauf herumhacken.

Niemand hackt irgendworauf rum ;-) Aber es gibt Guidelines, die sind fuer C/C++ aeussert sinnvoll, was aber nicht bedeuten muss, dass die gleichen Guidelines auch fuer Javaprojekte sinnvoll sind.

2: Weil es möglicherweise einfach so sein muss.

DAS ist das Problem der Softwareentwicklung heutzutage. "Macht das so-und-so und fragt bloss nicht, warum. Es ist einfach so!!" Wie oft musste ich mir diese (imho bloedsinnige) Antwort schon anhoeren.

Man sollte IMMER und staendig hinterfragen, warum man gerade etwas so macht und ob es nicht auch einfacher oder besser gehen wuerde. Nicht immer kann man dann sofort alles umstellen oder anders machen.

Aber wer sich von "Weil es so ist" ueberzeugen laesst, der hat doch schon verloren, oder?

Hier im konkreten erscheint mir spontan mit den maessigen Informationen auch erstmal ein grosses Fragezeichen. Interfaces, Loader, Generics, .... zum Laden einer Konfigdatei?? Ja, es gibt bestimmt Faelle wo das so sein muss, weil es zig Tausende Configfiles gibt (*grusel*). Dann kann man das so machen wie der TO vorgeschlagen hat. Ich wuerde aber die Methode [c]setColorPaletteLoader[/c] oder so aehnlich nennen. Verwirrt sonst nur, wieso der Setter namens ColorPalette einen Loader will.

Arbeitest du bei Microsoft? Die neigen auch dazu Antworten zu geben die nicht falsch sind, aber auch kein bisschen weiter helfen.

Was hat all das mit Microsoft zu tun? Wer im Jahre 2012 immer noch peinlich auf Microsoft rumhackt, hat wirklich ein wenig die Zeit verpennt, glaub ich ;-)

Deiner Aussage zum Einsatz von Interfaces kann ich aber zustimmen.
 
Ich halte nix von saemtlichen Pre- oder Postfixen
Trotzdem ist jedem selbst überlassen, wie er das händelt. Ich verwende auch den prefix I für Interfaces, genauso wie es die Entwickler von Eclipse tun.

irgendjemand hat gesagt.:
2) warum so umständlich ... reichen properties nicht ?
auch wenn ich mit Punkt 1 nicht übereinstimme, würde ich hier auch zu properties raten. Im prinzip baust du diese nach. Sollte das hier der Fall sein:

2: Weil es möglicherweise einfach so sein muss.

Dann könntest du dir mal JMapper anschauen. Das mapped dir deine Properties einfach auf ein vorgegebenes Interface.
 
Interfaces irgendwie zu kennzeichnen ist eine Unsitte. Es kommt nun einmal häufiger vor, dass eine abstrakte Klasse zum Interface mutiert oder umgekehrt. Wenn Java (endlich !) extension methods hat, werden die Grenzen noch fließender. Wenn es für den Nutzer irgend einen Unterschied macht, ob er gerade mit einem Interface oder einer Klasse arbeitet, ist etwas furchtbar, furchtbar schief gelaufen, und in den wenigen Fällen, wo das wirklich wichtig ist (wenn man z.B. einen Proxy basteln will oder so), findet man es mit einem einfachen Reflection-Aufruf heraus. Die Benennung dient also nicht dem Anwender des Codes, sondern "nur" den für den Code Verantwortlichen. Und hier zeigt inzwischen jede IDE, die etwas auf sich hält, Klassen und Interfaces unterschiedlich an (und zeigen Implementierungen für ein Interface), und ich würde sogar soweit gehen, dass es auch hier in den wenigsten Fällen eine Rolle spielen sollte - höchstens dann, wenn man die Datei sowieso öffnen muss, um etwas nachzuschauen, und dann sieht man ja sofort, um was es sich handelt.
 
Für die Konfiguration benutze ich Ini4j. Properties fand ich für meine Zwecke nicht passend, weil ich jeden möglichen Quatsch in die Konfiguration reinhauen will. Interfaces nutze ich, weil noch nicht absehbar ist, ob es bei Ini4j bleiben wird. Es ist nur ein kleines Hobbyprojekt, weshalb ich mir einen späteren Wechsel leisten kann.

Wegen der Benennung von Interfaces: Aus IConfig kann ich problemlos Configurable machen. Aber wie soll dann IConfigLoader heißen? ConfigLoadable? Nur Loadable?

Füg dann aber bitte Generics hinzu, so dass du den konkreten Typen der Configs bereits kennst, also [c]ConfigLoader<ColorPalette>[/c] o.ä. 🙂

Trotz Generics muss ich immer noch Casten:

Java:
    public void setColorPaletteLoader(IConfigLoader<ColorPalette> loader) {
        colorPalette = (ColorPalette) loader.getConfig();
    }

Java:
public interface IConfigLoader<T> {

    public IConfig<T> getConfig();  // geht nicht
    public void load(String fileName);
    
}

Edit: Das passiert, wenn man ein paar Monate nicht mehr programmiert hat. Es muss natürlich
Java:
    public T getConfig();
heißen. *kopfschüttel*
 
Zuletzt bearbeitet:
Java:
public interface IConfigLoader<T extends IConfig> {
    public T getConfig();
    public void load(String fileName);
}
?
 
@faetzminator: Da warst Du wohl schneller. Ich hab' noch mal in die IDE geschaut und dann stach es gleich ins Auge: was für einen Blödsinn schreibe ich denn da?
 
ich wollte mit dem >I< nicht auf C rumhacken ... aber laut java-conventions sollte man so etwas nun mal vermeiden ...
genau wie "m_" und der gleichen ...

sowas gehört halt einfach nicht in java code ... und wurde durch umsteiger aus der C welt mit "eingeschleppt" ...

[ot]hatten wir nicht mal die diskusion was passiert wenn jemand C-conventions versucht in java umzusetzen oder dergleichen ?[/ot]
 
NamingConventions hat gesagt.:
Interface names should be capitalized like class names.

So auf die schnelle sehe ich nichts in den NamingConventions, die vorschreiben, dass I verboten ist. Es ist imho eine Sache des Entwicklers. Das so zu verteufeln, wie es so manch einer hier macht, halte ich für übetrieben.
 
Ich finde die Interface-Diskussion immer wieder lustig :8

Aber als Beispiel, unabhängig von Java, sei mal folgendes genannt:

Ich entwickle eine Klasse MusicLoader, da ich zunächst nicht davon ausgehe, verschiedene Formate zu laden.

Merke ich, dass ich ja neben MP3 auch WMV laden will, ich also ein Interface brauche und wohl 2 Klassen, die dieses implementieren, da für die Anwendung selbst z.B. nur Kernfunktion lade() relevant ist!

Also würde das Interface MusicLoader und die Klassen MusicLoaderMP3 und MusicLoaderWMV heissen. Wo ist da noch der Sinn das Interface separat mit nem Prefix, Suffix oder Infix zu kennzeichnen?

Ich komme ursprünglich aus dem Delphi-Umfeld wo das Prefix I für Interfacenamen oder Suffixes wie _Intf oder _Impl für Quelldateien üblich sind und selbst da habe ich mir das abgewöhnt, da es schlichtweg überflüssig ist 😀
 
Wenn es denn nur einen Vorteil gäbe! Aber es gibt nur Nachteile. Siehe Beitrag von Landei.

Ne sorry, ich sehe das keine Nachtteile. Noch nie hatte ich mir gedacht: "Ach mist, hier stört aber das I". Im notfall gibt es immernoch Refactoring.

Es ist einfach nur ein Buchstabe der beim Überfliegen schonmal verrät "Das ist ein Interface" (egal ob mans braucht oder nicht. Mir z.B. gefällt es so einfach besser). Wem es nicht gefällt, der solls weglassen, alle anderen schreiben es ran.
Wenn man nicht gerade damit gegen Projekt-/Geschäftskonventionen verstößt, verstehe ich die Aufregung ehrlich gesagt nicht.

ARadauer hat gesagt.:
echt Leute es gibt schlimmeres...
dito.
 
Sollte man dann nicht konsequenterweise ein 'C' vor Klassen und ein 'E' vor Enums schreiben? Genauso wie ein 'i' vor einen Int und ein 'f' vor einen Float. Und wenn man schon dabei ist, kann man auch ein 'm_' vor Membervariablen schreiben und ein 'p_' vor Parameter. Auch koennte man auf diese Weise die komplette Signatur einer Methode als Prefix vor den Namen schreiben... ;-)

*duckundweg*
 
Du hast ein 'A' für Abstrakte Klassen vergessen ;-)
(wenn wir schon dabei sind: N für Nested Classes)
 
Für die Konfiguration benutze ich Ini4j. Properties fand ich für meine Zwecke nicht passend, weil ich jeden möglichen Quatsch in die Konfiguration reinhauen will

Das klingt eher nach einem Job für Preferences. Die Werte sind im Gegensatz zu den "flachen" Properties in einer baumartigen Struktur angelegt. Wie gespeichert wird, kann man konfigurieren, aber ohne weitere Angaben werden betriebssystemtypische Mechanismen (etwa die Registry unter Windows) verwendet.
 
Zuletzt bearbeitet:
Das klingt eher nach einem Job für Preferences. Die Werte sind im Gegensatz zu den "flachen" Properties in einer baumartigen Struktur angelegt. Wie gespeichert wird, kann man konfigurieren, aber ohne weitere Angaben werden betriebssystemtypische Mechanismen (etwa die Registry unter Windows) verwendet.
Ich wollte aber ausnahmesweise mal kein XML-Format, damit man die Konfiguration schnell mit dem Text-Editor ändern kann. Bin bis jetzt mit Ini4j ganz zufrieden.
 
JSON ist auch immer eine Option fuer sowas. Find ich ganz praktisch und viel uebersichtlicher als XML.

Noch cooler ist nur, wenn du deine Konfiguration per Script (z.B. Ruby) steuerst. D.h. du laedst einfach eine App und die fuehrt nach der Initialisierung ein Rubyscript aus, welches dann alles konfiguriert. Der Vorteil: Kein XML sondern Code, dort kannste natuerlich auch mit Schleifen, Switch/Case, Klassen und Objekten hantieren.

Je besser deine API ist, desto maechtiger wird dann das Ruby-Konfigurationscript. Letztlich kann es sogar zur eigentlichen Main mutieren 🙂
 
anstatt JSON -> YAML (eine konfiguration die simple und auch lesbar ist)
anstatt Ruby -> Groovy (weil... so halt)

dann passt schalentiers aussage ;-)
 
Ich finde wichtig, dass es im Projekt einheitlich ist.

Wir haben bei uns im Projekt überall dieses Impl dabei... was mir auch nicht besonders gefällt...

Natürlich würde ich für ein Enum kein E und vor eine Klasse kein C schreiben... aber ich finde das ist was anderes...
Warum ich es private gerne mache ist, dass ich beim Öffnen vom Typ jetzt genau weiß ich will das Interface editieren und dann gleich das I schreibe.

Aber es stimmt schon, im Grunde soll ich bei der benützung des Interface gar nicht dran denken müssen, dass es ein Interface ist...

Also wichtig: einheitlich bleiben....
 
Groovy (weil... so halt)

Lol, habs mir endlich mal angeschaut. Resultat:

Hatte mir für eine Aufgabe mal eine DSL geschrieben, weil in Java es mir zu unübersichtlich war ... ich teste Groovy ... denke mir "hey moment mal" ... Ergebnis: die DSL hätte ich mir sparen können. Mit Groovy hätte ich zwar wohl trotzdem einige Zeilen mehr, aber das wäre noch verkraftbar gewesen ;(

Mal schauen, ob ich die DSL in naher Zukunft loswerde und ob ich Groovy überhaupt mit Android verwenden kann.
 

Zurück
Oben