# Sinnvolle Eclipse-Projektstruktur



## FreakyM (4. November 2011)

Hallo an Alle,

ich habe in den letzten 3 Jahren im Rahmen meines Studiums ein sehr großes Java-Programm geschrieben. Unter anderem enthält es sehr viele Klassen mit Methoden zum Lesen/Schreiben von verschiedene Dateien (spaltenweise aufgebaute ASCII-Dateien, sind CSV ähnlich)

Ich habe für jede Datei eine Klasse angelegt welche diese mit Hilfe 2 statischer Methoden Lesen bzw. Schreiben kann, wobei die Lese-Methode immer ein Objekt als Rückgabeparameter hat welches die gelesenen Infos enthält. Die Schreib-Methode bekommt dementsprechend dieses "DataHolder"-Objekt als Parameter übergeben und schreibt es wieder als ASCII-File raus.


Um mal ein Beispiel zu nennen (echte Struktur/Code würde denke ich den Rahmen sprengen):

Es gibt 3 Dateien, eine enthält geometrische Informationen über ein Schiff (wie genau, ist egal). Eine weitere geometrische Informationen über ein Fluss und die letzte enthält Daten über Strömungen in diesem Fluss.
Meine Projektstruktur, Projektname bsp. "Schifffahrt", sieht bisher so aus...



Und natürlich viel viel mehr Packages und Klassen...

Die Lese- und Schreibmethoden so:



Die "DataHolder"-Klassen enthalten nur Variablen und Getter/Setter



1. Ist es sinnvoll eine Klasse für das Lesen/Schreiben der ASCII-Datei zu haben mit statischen Methoden und dazu immer eine passende Klasse mit den gelesenen Informationen (eine Art "DataHolder")

2. Diese I/O-Klassen und damit auch die "DataHolder"-Klassen werden leider auch in vielen anderen Eclipse-Projekten gebraucht. Dafür müsste ich immer dieses Projekt importieren, wobei hier natürlich für das neue Projekt viele unwichtigen Klassen enthalten sind wie die Simulation oder Berechnungen...
Also würde es Sinn machen ein Eclipse-Projekt (Jar-Datei) zu erstellen, was nur diese Einlese/Schreib-Klassen und "DataHolder"-Klassen enthält? Wobei das auch unübersichtlich werden kann..
Oder bei einer sehr großen Anzahl an Dateien (nicht nur 15) sogar diese in 2 Projekte (Jars) zu teilen (bessere Übersicht), wobei dann natürlich wieder eine Abhängigkeit dar wäre zwischen den Beiden?

Die Dateien zu "verschmelzen" ist leider nicht möglich, also um weniger Klassen und Methoden schreiben zu müssen, auch wenn es eventuel besser wäre.
Was meint ihr dazu? Wie hättet ihr das alles aufgeteilt?

Danke im Vorraus...

Gruß
Dennis


----------



## Fabio Hellmann (4. November 2011)

Hi,

1. Also so wie du es erklärt hast, dass du ein Objekt mit den Informationen der Datei hast, ist schon mal sehr gut. Ich würde allerdings nun diesem Objekt - nennen wir's mal "DataHolder" - noch eine Methode 'write' verpassen, an die du einen Writer/Outputstream übergibst. Dann kannst du alle Lese/Schreibe Klassen zu einer zusammenfassen, was dir natürlich ein haufen Klassen spart.
Um alle Klassen einfach einlesen zu können würde ich dir zu einem einheitlichen Format raten. Beispielsweiße das JSON-Anotation (JSONObject). Die ist einfach zu handeln und auch zum lesen/schreiben sehr einfach.

2. Grundsätzlich würde ich sagen, dass man so wenig Projektabhängigkeiten machen sollte wie möglich. Das bringt meistens nur Probleme mit sich. Pack doch alles was du aus einem Projekt an Klassen brauchst in eine Jar-Datei und binde diese über den Buildpath in dein Projekt ein. So hast du nur die Klassen, die du auch wirklich brauchst.

Gruß

Fabio


----------



## FreakyM (4. November 2011)

Hey Fabio,

ich habe gerade nochmal mein Beitrag editiert, vielleicht sind noch wichtige Informationen dabei...

Zu 1. 
Wie meinst du das mit den Writer als Parameter?
Ich habe doch pro Datei eine Klasse, welche das Objekt rausschreibt und eine welche die Inhalte in sich hält (DataHolder). Die Inhalte bzw. die Struktur der DataHolder Klassen sind ja immer anders (andere Variablen etc.) und somit brauch ich immer andere Schreibroutinen oder bin ich falsch? (siehe Bild)

Das mit dem JSON ist ne echt gute Sache,danke für den Tipp, aber leider kann ich die Formate an sich auch nicht verändern... Die Formate sind in meiner Firma dummerweise überall verwendet und können daher auch nicht angepasst werden, sonst wärenm die Änderungen aller anderen Programm zu groß...

zu 2.
Genau so wollt ich es machen... Die Klassen, die in anderen Projekten benötigt werden in eine Jar/Projekt packen und immer einbinden.
Nur wenn ich 20 Einlese-/Schreibklassen und DataHolder-Klassen habe wird auch das unübersichtlich... Daher dachte ich,ich mach eine Jar mit den DataHoldern und eine mit den Lese-/Schreibklassen! Ist das ne dumme Idee?


----------



## Fabio Hellmann (4. November 2011)

Hey,

die Bilder die du hochgeladen hast sind gut, allerdings solltest du diese besser über die Hochladefunktion vom Forum hochladen, da die sonst zu einem späteren Zeitpunkt gelöscht werden.

Zu 1.


> Die Formate sind in meiner Firma dummerweise überall verwendet und können daher auch nicht angepasst werden, sonst wärenm die Änderungen aller anderen Programm zu groß...


Das ist natürlich dann klar, dass du das JSON-Format nicht benutzen kannst. Das wäre auch zu einfach gewesen. 
Damit das aber mehr Struktur bekommt, würde ich deinen Ansatz dann drotzdem nochmal ein wenig verändern. Ich würde ein Interface für alle DataHolder Klassen machen, welche die DataHolder Klassen alle implementieren.

```
public interface DataHolder {
   /*
    * Hier werden die Inhalte der Variablen ins File geschrieben.
   */
   void write(Writer writer);

   /*
    * Hier werden die Inhalte aus dem File in die Variablen geladen.
   */
   void read(Reader read);
}
```

Dann brauchst du, wenn du es so löst, nur eine Schreib/Lese Klasse. Da du die Schnittstelle veralgemeinert hast.

```
public class ReaderWriter {
   public void loadDataFromFile(File file, DataHolder holder) {
      BufferedReader reader = new BufferedReader(new FileReader(file));
      holder.read(reader);
      reader.close();
   }

   public void writeDataToFile(File file, DataHolder holder) {
      BufferedWriter writer = new BufferedWriter(new FileWriter(file));
      holder.write(writer);
      writer.close();
   }
}
```
So könnte dann deine Lese/Schreibe Klasse aussehen. Allerdings musst du noch das Exceptionhandling ergänzen.

Zu 2.


> Genau so wollt ich es machen... Die Klassen, die in anderen Projekten benötigt werden in eine Jar/Projekt packen und immer einbinden.
> Nur wenn ich 20 Einlese-/Schreibklassen und DataHolder-Klassen habe wird auch das unübersichtlich... Daher dachte ich,ich mach eine Jar mit den DataHoldern und eine mit den Lese-/Schreibklassen! Ist das ne dumme Idee?


Ich würde sagen, dass das Geschmackssache ist. Ich würde alle Klassen aus einem Projekt auch in das gleiche Jar-File packen. Aber das ist letztenendes jedem selber überlassen.

Gruß

Fabio


----------



## FreakyM (31. Dezember 2011)

Hey Fabio,

sorry das ich so lange nicht zurückgeschrieben habe.
Danke für die Idee mit dem JSON-Format, habe es direkt bei mir eingebaut!
Nun sind es 9 Formate pro DataHolder (also Stroemung, FlussGeometrie, SchiffsGeometrie)...



Um nochmal auf deinen letzten Beitrag zurück zu kommen:
Ich verstehe nicht ganz was mir die ReaderWriter-Klasse für einen Vorteil bringen soll?

Ich habe dann 4 Zeilen Code ausgelagert, welchen ich somit nicht immer wiederholen muss, das ist klar. Jedoch habe ich dann in jeder DataHolder-Klasse eine write und read Methode, macht man das so? Ich habe es momentan ausgelagert in extra Klassen damit es "sauber" getrennt ist. Also so wie du nur MIT dem read und write Code. Den warum sollten die DataHolder den Read und Write Code kennen müssen?


Ein weiteres Problem ist, dass ich pro Dataholder 9 Formate habe/brauche und somit ja nicht nur eine read und write Methode ausreicht! Deshalb habe ich pro Format eines DataHolders eine eigene Klasse gemacht.
Und pro DataHolder ein Interface mit einer read und write Methode... (siehe Bild des ersten Beitrags)
Wie soll ich mit deiner Idee die verschiedenen Einleseroutinen unterscheiden bzw. wo?


Und die Methoden mit dem Parameter "DataHolder" funktioniert ja sowieso nicht, da Stroemung sowie Schiffsgeometrie und Flussgeometrie andere DataHolder haben und diese auch nicht irgendwie zusammengesteckt werden können. Der Inhalt ist völlig verschieden...


Oder versteh ich dein Beitrag falsch?
Danke schonmal für deine Hilfe!



Hier als Ergänzung wieder mal ein Bild:




Wie du erkennen kannst sind es einige Formate! Diese sind aber nur für die SchiffsGeometrie...
Es gibt noch Stroemung und Flussgeometrie.
Und wie du auch sehen kannst habe ich pro Format eine eigene Klasse mit der read und write Methode, welche immer den jeweiligen DataHolder zurück gibt.

Langsam verlier auch ich den Überblick deshalb nochmal meine Anfangsfrage:
Ist es sinnvoll eine Klasse für das Lesen/Schreiben der ASCII-Datei zu haben mit *statischen *Methoden und dazu immer eine passende Klasse mit den gelesenen Informationen (eine Art "DataHolder").
Vorteil bzw. Nachteil von statischen Einleseroutinen?
UND
Ist es sinnvoll *pro Format eine eigene Klasse* zu haben?
Andere Lösung?


Gruß
Dennis


PS: Vielleicht erklär ich es auch etwas kompliziert...


----------



## Fabio Hellmann (31. Dezember 2011)

Hi,
also wenn du jetzt mit dem JSON-Format arbeitest, erstpart dir das viel arbeit. Du kannst nun einfach die komplette Datei (die im JSON-Format ist) einlesen und einem JSONObject übergeben.

```
public static JSONObject readFileToJSONObject(File file) throws JSONException {
		StringBuilder strBuilder = new StringBuilder();
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			String line;
			while((line = reader.readLine()) != null) {
				strBuilder.append(line);
			}
		} catch(FileNotFoundException e) {
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		} finally {
			try {
				reader.close();
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		return new JSONObject(strBuilder.toString());
	}
```
Dadurch fallen deine 9 Formate dann eigentlich weg, da du über das JSONObject dann auf alle Werte aus der jeweiligen Datei zugreifen kannst.

Ich hoffe ich hab dich richtig verstanden.

Gruß

Fabio


----------



## FreakyM (20. Juni 2012)

Mit deiner Methode bekomme ich ein JSON-Object zurück...

Jedoch habe ich pro Klasse (Stroemung, FlussGeometrie, SchiffsGeometrie) ein JSON-Format...
Und etliche mehr... Was soll dein JSON-Object den beinhalten?

Im Grund wollte ich eine read/write Methode für alle 3 (Stroemung, FlussGeometrie, SchiffsGeometrie) DataHolder.... Oder mindesten eine gleiche Basis...


----------



## Fabio Hellmann (22. Juni 2012)

Hi,
wenn du mal in der API nachschaust, wirst du eine write-Methode von fast allen JSON-Klassen finden. Somit brauchst du lediglich einen Writer an diese Methode übergeben und schon werden die Daten in die Datei geschrieben.

```
JSONObject jsonObject = new JSONObject(string);

FileOutputStream out = new FileOutputStream(file);
jsonObject.write(out);
```

Das lesen einer solchen Datei habe ich dir oben gezeigt. Dabei musst du die komplette Datei einlesen und als String an ein JSON-Object übergeben. Und fertig.

Gruß

Fabio


----------

