# Multiprojektorganisation & Refactoring-Automatisierung



## slawaweis (27. Jan 2011)

Hallo,

wenn man eine größere Software entwickelt, kann man alles in nur einem IDE-Projekt (z.B. "Java Project" in Eclipse) organisieren, oder für bestimmte Teile (Schichten, Module, Komponenten, Tools, Tests) eigene IDE-Projekte anlegen. In Maven kann man so was sogar beliebig tief verschachteln. Gibt es eigentlich schon Richtlinien/Design Guides/Architekturen, wie so eine Multiprojektstruktur am besten aufzubauen und zu verwalten wäre? Oder ist es besser nur ein IDE-Projekt pro Softwareprojekt zu haben? Mich interessieren sowohl Artikel zum Thema, wie auch persönliche Erfahrungen. Was ich bis jetzt an echten Problemen dazu gefunden habe war, dass durch die Aufteilung Subversion übergangen wird und so eine durchgängige Versionierung nicht mehr möglich ist. Weiterhin wird es bei einer Aufteilung in mehrere Hundert kleine Projekte unübersichtlich.

Eine andere Frage habe ich zu Refactoring-Automatisierung. Ist es möglich in Eclipse bestimmte Refactoring-Schritte wie ein Makro aufzuzeichnen und immer wieder automatisch abzuspielen? Oder sich gleich ein Refactoring-Skript schreiben, z.B. mit Ant? Gibt es dafür ein API oder ein Werkzeug?

Slawa


----------



## Wildcard (27. Jan 2011)

Ich verwende fast nur OSGi und da ergibt sich die Struktur fast von selbst. Jedes Modul ist ein Bundle, jedes Bundle ein Projekt.
Mein aktuelles Projekt besteht aus ca. 100 Bundles.
Ein riesiges Projekt zu haben halte ich für eine sehr schlechte Idee. Dabei besteht die große Gefahr das nach einer Weile jedes Package von jedem anderen abhängt. Sowas bekommt man mit OSGi mit Gewalt zwar auch hin, aber die Hemmschwelle ist deutlich größer.





> Eine andere Frage habe ich zu Refactoring-Automatisierung. Ist es möglich in Eclipse bestimmte Refactoring-Schritte wie ein Makro aufzuzeichnen und immer wieder automatisch abzuspielen? Oder sich gleich ein Refactoring-Skript schreiben, z.B. mit Ant? Gibt es dafür ein API oder ein Werkzeug?


Es gab mal Eclipse Monkey, aber das hatte mittlerweile ein Termination Review.
Welche Art von Refactoring soll das denn sein wenn man es automatisiert ausführen kann? :noe:


----------



## slawaweis (28. Jan 2011)

Wildcard hat gesagt.:


> Ein riesiges Projekt zu haben halte ich für eine sehr schlechte Idee. Dabei besteht die große Gefahr das nach einer Weile jedes Package von jedem anderen abhängt.


die Probleme würden dann aber an der Projektorganisation liegen, wenn jeder überall ungeprüft ändern und verknüpfen kann. Auf der anderen Seite hat man in einem einzigen IDE-Projekt die Freiheit, unter der Beachtung der Design Guide, die Änderungen genau an der richtigen Stelle vorzunehmen. Bei verteilten Projekten kann es passieren, dass wenn man etwas sinnvolles nicht in einem fremden Teilprojekt ändern kann, baut man Workarounds, Schichten oder ähnliches auf seiner Seite, was das Problem nur verlagert. Aber wiederum, Projektorganisation. Das sind jetzt keine Gegenargumente, sondern nur Überlegungen meinerseits, um die Sache besser zu verstehen.



Wildcard hat gesagt.:


> Es gab mal Eclipse Monkey, aber das hatte mittlerweile ein Termination Review.
> Welche Art von Refactoring soll das denn sein wenn man es automatisiert ausführen kann? :noe:


es geht darum ein bestehendes größeres Projekt/Softwarebasis global umzustrukturieren. Das Projekt selber ist aktiv und jeden Tag gibt es daran Änderungen. Nur ist es nicht mehr gut wartbar. Weiterhin ist noch nicht klar, wie es endgültig umzustrukturieren wäre, damit danach sich eine deutliche und spürbare Verbesserung der Entwicklung ergibt. Deshalb will ich unter anderem einen (semi-)automatischen Refactoring-Simulator erstellen, welcher die möglichen Folgen/Vorteile/Nachteile an der aktuellen Version darstellt. Damit könnte man auch mehrere Varianten der Umstrukturierung vorher durchtesten.

Slawa


----------



## maki (28. Jan 2011)

Refactoring läst sich nicht automatisieren, genausowenig wie man immer dieselbe Struktur verwenden kann 

Es reicht doch ein Branch um zu zeigen wie sich das Refactoring auswirken würde, kleine Variationen vom "Originalplan" haben oft große Auswirkungen während des Refactorens, positive wie negative, muss man alles ausprobieren.

Das bei Modularisierung mit Maven Subversion übergangen wird stimmt schlicht nicht, die Versionierung leidet auch nicht.
Man muss sich halt schon Gedanken machen was ein eigenständiges Projekt ist, und was ein Modul.
Stur ales in ein Modul zu konvertieren ist genauso gut wie stur alles in ein eigentständiges Projekt zu konvertieren, man muss schon wiessen wie man die Werkzeuge einsetzt.

Es kommt immer auf den konreten Fall an, sonst wäre das ja wirklich sehr einfach und sowas wie refactoring wäre überflüssig weil man immer dasselbe machen könnte


----------



## slawaweis (30. Jan 2011)

maki hat gesagt.:


> Refactoring läst sich nicht automatisieren, genausowenig wie man immer dieselbe Struktur verwenden kann
> 
> Es reicht doch ein Branch um zu zeigen wie sich das Refactoring auswirken würde, kleine Variationen vom "Originalplan" haben oft große Auswirkungen während des Refactorens, positive wie negative, muss man alles ausprobieren.


es geht darum das Refactoring immer wieder auf einer aktuellen Version einer konkreten Software auszuführen. Auch muss nicht alles automatisch ablaufen, aber so viel es geht. Weiterhin sollte es möglich sein, die Veränderungen irgendwie zu messen und miteinander zu vergleichen.



maki hat gesagt.:


> Das bei Modularisierung mit Maven Subversion übergangen wird stimmt schlicht nicht, die Versionierung leidet auch nicht.


wenn man ständig Quelltext zwischen den Projekten verschiebt, schon.



maki hat gesagt.:


> Man muss sich halt schon Gedanken machen was ein eigenständiges Projekt ist, und was ein Modul.
> Stur ales in ein Modul zu konvertieren ist genauso gut wie stur alles in ein eigentständiges Projekt zu konvertieren, man muss schon wiessen wie man die Werkzeuge einsetzt.


und genau an diesem Punkt interessiert es mich, ob es bestimmte Richtlinien oder gute Artikel zum Thema "Multiprojekt" gibt.

Slawa


----------



## maki (30. Jan 2011)

> es geht darum das Refactoring immer wieder auf einer aktuellen Version einer konkreten Software auszuführen. Auch muss nicht alles automatisch ablaufen, aber so viel es geht. Weiterhin sollte es möglich sein, die Veränderungen irgendwie zu messen und miteinander zu vergleichen.


Sehe da wirklich keine andere Möglichkeit als manuelle Arbeit.
Die Codemetriken kann man automatisch erstellen lassen und dann manuell vergleichen.
Anstatt die Refactorings autom. ablaufen zu lassen und dann hoffen dass es passt kann ja ja wie gesagt mit Branches arbeiten und sich dann diese UNterschiede anzeigen lassen, ist aber eben limiert was die Änderungen angeht.

Aber irgendwie denke ich, dass das Problem etwas anderes ist.
Entweder man entscheidet sich für ein refactoring oder nicht, bringt wenig ständig dieselben Refactorings auf den Trunk anzuwenden um dann etwas zu zeigen, es reicht doch wenn man das einmal macht und dann entscheidet dass es angewendet wird, oder eben auch nicht, die Vorteile müssen sich schon beim ersten mal zeigen.

IME: Wenn das schon so losgeht will man u.U. gar nix ändern.
Entweder weil man Angst hat (zB. aus mangelnder Erfahrung) etwas kaputtzumachen, oder weil Entscheidungsträger die Idee nicht unterstützen.
Das Risiko dass danach etwas nciht mehr funktioniert ist immer da, dafür gibt es Tests, refatoring ohne Tests ist ein Spiel mit dem Feuer.



> wenn man ständig Quelltext zwischen den Projekten verschiebt, schon.


Dann ist das aber die Ursache des Problems, nicht Maven Module/Subversion 
Projektstrukturen und -inhalte ständig zu ändern bremst die Produktivität... wenn man seine Module mal richtig strukturiert hat, ist das nicht  mehr häufig ("ständig") sondern selten dass man alles über den haufen wirft und neu mischt...



> und genau an diesem Punkt interessiert es mich, ob es bestimmte Richtlinien oder gute Artikel zum Thema "Multiprojekt" gibt.


Die sind schnell erklärt:
Bei Modulen in einem Multimodulprojekt handelt es es um teile eines Projektes, ein Projekt ist etwas eigenständiges 

Anwenden dagegen ist komplizierter und es kommt immer auf den konkreten Fall an.
Man muss sich eben überlegen wo man die Linie zieht, dabei kann man zB. beachten, wie etwas erstellt/geändert/released/versioniert/genutzt wird.

Beispiele kann man zB. aus bestehenden Projekten nehmen, wenn du ein konkretes Beispiel hast, könnte man das Besprechen.

IME ergibt es wenig Sinn mehrere Teams an den Modulen eines Multimodulprojektes arbeiten zu lassen, da gibt es ziemlich viele Reibungsverluste, ausser die Strukturen ändern sich nicht mehr.
Der Punkt ist eben, wie häufig Änderungen sind und wie aufwändig es ist diese umzusetzen, wie man sich mit den anderen im Team oder gar anderen Teams abspricht und Verträge (Schnittstellen) definiert sind.

Fehler am Anfang sind normal, je schneller man eine passendere Struktur findet umso besser, in meinen Projekten hätte ich alle anderen Entwickler zum warten verdammt (der schlimmer: Arbeit doppelt machen) wenn ich die einmal etablierte Struktur ändere, da wartet man lieber und "sammelt" Änderungen die dann alle auf einmal umgesetzt werden.
Dazu braucht es einerseits Erfahrung aber auch Kollegen die das mitmachen (letzteres ist wichtiger als man denkt), am Anfang eines Projektes sind Änderungen einfacher als später.

Manchmal ist ein total vermurkster Build (von Vorgängern geschaffen) beibehalten worden weil die Änderungen massive Auswirkungen gehabt hätten und keiner bereit war einzusehen dass die Entwickler vom Build ausgebremst wurden, ganz abgesehen davon dass der Build mal ging um mal nicht.
Beispiel: Keine Möglichkeit eine RCP App. aus Eclipse zu starten & debuggen (ausser als Remote Debugsession), die Ursache war der Missbrauch des Assembly Plugins und falsche/unpassende Projektstrukturen von Maven-unwissenden, da hat man dann turn-around Zeiten zwischen entwickeln/ändern, bauen und (manuell) testen das man meint mit dem Notepad & Commandozeilen-Kompilieren ginge es schneller... und das alles in einem Multimodul Projekt an welchem nur von einem Team gearbeitet wurde.


----------



## Herr K. (30. Jan 2011)

Hi Slawa,



> Anwenden dagegen ist komplizierter und es kommt immer auf den konkreten Fall an.


Das ist denke ich der wichtigste Satz, den Du hören wirst (zumindest der Richtigste). Deine eigentliche Frage kann man nicht genauer beantworten, denn es gibt zig Ansätze und Architekturen, die für ganz bestimmte Projekte/Probleme besser oder schlechter geeignet sind. Hier wirst Du auch kein Buch finden, dass Dir sagen kann wann was am Besten funktioniert. Das liegt nicht nur an der schieren Menge die Du hier unterbringen müsstest, ein Projekt verwendet i.d.R. auch gleich mehrere Architekturen für unterschiedliche Elemente. So kannst die Anwendung zwischen einem Client und einem Server unterscheiden, wobei beide Subsysteme wiederum einen eigenen, inneren Aufbau haben (das gilt dann auch für die Komponenten oder Module, aus denen sich jedes Subsystem zusammensetzt usw.).



> Man muss sich eben überlegen wo man die Linie zieht, dabei kann man zB. beachten, wie etwas erstellt/geändert/released/versioniert/genutzt wird.


Auch hier stimme ich maki vollkommen zu. Allerdings würde ich hier noch einen wichtigen Aspekt ergänzen, man sollte die Größe im Auge behalten. 

Ich denke einen wichtigen Punkt hast Du noch offen gelassen, so sagst Du, dass die Wartbarkeit deutlich leidet, aber schön wäre wenn Du auch erläuterst wie sich dies äußert. 

Die wichtige Aufgabe des Projektmanagement besteht darin, dass man die Probleme von den Entwicklern fernhält. Und hierfür ist es unabdingbar, dass man stets einen guten Überblick und ein ausreichendes Verständnis hat. Die beiden Rollen (Entwickler und Projektleiter) haben dabei einen gegenläufigen Fokus. Der Entwickler muss ein Detailverständnis für die Komponente haben, an der er gerade arbeitet, braucht diesen aber nicht auf jede Komponente im Projekt. Die Leitung wiederum muss den Gesamtblick haben und schauen, dass alle Teile zusammenpassen, braucht aber keine Detailkenntnis was in welcher Klasse steht.

Die Projektorganisation ist ganz klar Aufgabe der Leitung. Die muss so aufgebaut sein, dass die Entwickler vernünftig arbeiten können (weil sie alles sehen, was sie benötigen), sie muss aber auch so sein, dass der Gesamtüberblick erhalten bleibt. Das Problem an Deiner Frage ist nun, dass die Granularität der Zerlegung (mehrere Workspaces, mehrere Projekte, mehrere (Sub-)Packages, mehrere Klassen) davon abhängt wie groß das Projekt an welcher Stelle ist. 

Entwickelst Du z.B. eine Office Suite, so kann es sinnvoll sein, dass Du mehrere Projekte erstellst, die jeweils einem eigenen Projektleiter unterstehen und auch nicht zusammen in einem Workspace bearbeitet werden. Natürlich gibt es auch Gemeinsamkeiten (z.B. für den Austausch von Daten zwischen den Komponenten), die gehören natürlich auch in eingenes Projekt. Hier möchte ich nochmal klar sagen, ein Eclipse-Project im Workspace ist bitte nicht mit einem Projekt (im Sinne einer zu erstellende Software) zu verwechseln. 
Auch für ein Projekt bietet es sich an, dass man prüft welche Elemente eine geeignete Größe haben um die noch sinnvoll überblicken zu können. Hast Du etwas in einer Größe, die Du für nicht mehr überschaubar hältst (z.B. ein Projekt mit mehreren hundert packages), dann sollte man hier klar eine Trennung vorsehen. Hier hilft erneut der Tipp von maki:


> Man muss sich eben überlegen wo man die Linie zieht, dabei kann man zB. beachten, wie etwas erstellt/geändert/released/versioniert/genutzt wird.


Die Lebenszeit/Änderungsrate ist ganz entscheidend. Hast Du Komponenten/Subprojekte, die relativ unabhängig sind, dann sollten die auch entsprechend getrennt entwickelt werden. Hier ist es halt wichtig, dass man sich im Vorfeld Gedanken über sinnvolle Schnittstellen gemacht hat, die nun verbindlich sind. Durch die Verwendung von Mocks ist man hier auch unabhängig vom Entwicklungszyklus dieser getrennten Projekte. Das Vorgehen ist somit ganz analog zu einer fertigen Komponente/Bibliothek, die Du verwenden würdest, auch hier unterliegt die Entwicklung einem eigenen Team und zu jeder Version gibt es ein spezifisches API, gegen das Du programmierst.

Für kleinere Projekte kann es auch schon ausreichen, dass Du ein Eclipse Project für jede Schicht (Presentation, Service, Dao, Modell) erzeugst. Die Unterteilung ist hier einerseits möglich, da Du unterschiedliches Know how für die einzelnen Schichten benötigst (GUI Designer sind nicht immer die besten DB Experten und vice versa), noch wichtiger ist aber, dass die Änderungen in den Schichten ganz unterschiedlichen Zyklen unterliegen. 

Was die Probleme angeht, die mit einer Änderung einher gehen, so gilt altbekannt: "Einen Tod muss man sterben". Um es mal klar zu sagen, nur bei einem Projekt, dass demnächst aufgelöst wird lohnt es sich mit schlechter Wartbarkeit zu leben. In jedem anderen Fall geht schlechte Wartbarkeit mit einer Minderung in Qualität und Effizienz einher und da relativiert sich schnell die Frage, ob man es sich leisten kann das Produkt umzustrukturieren und man muss sich frage, ob man es sich leisten kann es nicht zu tun. 
Tatsächlich kann es sogar dazu kommen, dass die Refactorings so umfangreich ausfallen, dass man das Projekt neu schreibt. Das heißt aber nicht, dass man dies als Ziel haben sollte oder gelassen hinnehmen muss. Es ist normal, dass sich Änderungen in einem Projekt ergeben, die Auswahl der Architektur bestimmt jedoch dabei, wie weit sie sich auswirken. Deshalb ist eben auch die Planung wichtig, die hier getroffenen Entscheidungen bestimmen den Erfolg des Projekts.


----------



## schalentier (30. Jan 2011)

maki hat gesagt.:


> Sehe da wirklich keine andere Möglichkeit als manuelle Arbeit.



Naja, ein Usecase diese manuelle Arbeit irgendwie zu automatisieren waere, wenn man die Aufgabe hat die Projektstruktur (auf Quellcodeebene) neu zu organisieren. Mit Automatisierung koennte man:

1. das Konvertieren des Projektes selbst "testen" (Kompilierts? Laufen die Tests?)
2. das Projekt in vergleichsweise kurzer Zeit automatisch konvertieren (kurze Downzeit fuer die eigentliche Umstellung)
3. man umgeht die Gefahr einer Merge-Orgie

Ich hatte mal eine aehnlich geartete Aufgabe und dafuer einen solchen Konverter benutzt. Damit sind aus einem monolitischen Projekt, ca. 10 kleinere Projekte entstanden (die untereinander auch Abhaengigkeiten haben). 

Ob ein solches Vorgehen allerdings hier sinnvoll ist, kann man pauschal wohl nicht sagen. Haengt stark von der Qualitaet des Quellcodes und der gewuenschten, neuen Projektstruktur ab... (nen monolitisches System in 100 Maven Projekte zu ueberfuehren, wird so oder so unendlich aufwendig).


----------



## KSG9|sebastian (17. Feb 2011)

Alles in ein Projekt verpacken führt früher oder später so einem unwartbaren Projekt (eher früher).

Es macht schon Sinn eine gewisse Trennung zu verfolgen. Ob du aber deine Projekte/Module nach fachlichen oder technischen Gesichtspunkten schneidest liegt bei dir. Weiterhin macht es natürlich auch oft Sinn die Schichten in Module/Projekte aufzuteilen.

Hast du alles in einem Projekt garantiere ich dir das nach spätestens 2 Wochen die Präsentationslogik direkte Abhängigkeiten auf die Backendzugriffslogik hat.

Durch die entsprechende Trennung hast du entsprechende Abhängigkeiten gut im Griff, du kannst vernünftig ändern/refactorn weil du sehr gut und schnell siehst welche Änderungen welche Auswirkungen haben (API-Änderungen u.s.w.) Es ist sehr gut möglich zwischen Schnittstelle und Implementierung zu ändern und und und.

Natürlich muss man hier den schmalen Grat zwischen Overengineering und Fummel-Projekt relativ gut treffen. Aber durch Artikel oder Bücher wirst du hier nur schlecht zu einer Lösung finden, da diese nahezu immer auf ein bestimmtes Problem zugeschnitten sind.
Dann kommt es natürlich darauf an was du so als Technologien einsetzt. Mit OSGI ist die Struktur schon relativ gut vorgegeben, Spring fordert auch einen gewissen Aufbau, JEE ebenso. Hast du eine Webapplikation, oder gar eine Client/Server-Anwendung mittels Swing? Im letzten Fall zum Beispiel kannst du gar nicht alles in ein Projekt packen da du gewisse Dinge zum Client und andere auf dem Server deployst. Hast du eine verteile EE-Anwendung wird das auch nicht funktionieren, da oftmals die Laufzeitumgebungen für Web/Client und Geschäftslogik getrennt sind (Stichwort JEE, Remote...).

Letztendlich kannst du die Grundlagen von gutem Software/Packetschnitt schon anlesen, ohne aber praktisch etwas zu tun wirst du den Weg aber nicht finden. Überlegt dir einfach ein fiktives Problem und fang mal an auf dem Papier zu malen wie du dir das vorstellst.
Zerteile die Software in Packete wie du es dir vorstellst. Da hast du dann sehr schnell mehrere Lösungen (fachlich oder technisch getrennt, fachlich und technisch getrennt, Schichten nochmals getrennt u.s.w.).

Und dann schaust du dir mal an welche Lösung welche Vor- und Nachteile bringt. Interesante Fragen wie du dir zu den Lösungen stellen kannst:
- Wartbar?
- Wie groß wirken sich Änderungen aus?
- Wie komplex ist das Buildmanagement?
- Wie sieht die Testbarkeit aus?
- Ist es möglich einzelne Artefakte gezielt zu testen, ohne alle Abhänigkeiten auflösen zu müssen?
- Ist es möglich andere Clients (z.B. Mobile, Desktop) anzubinden ohne Geschäftslogik anpassen zu müssen?
- Ist es zu granular - hast du für ein Miniprojekt 200 Projekte?

Ich denke die Liste kannst du selbst auch beliebig weiterführen. Ist natürlich immer Abhängig von deinem Ziel.
Wenn du mit 20 Leuten an einem Projekt arbeitest ergeben sich ganz andere Anforderungen. Schreibst du eine Anwendung welche nur auf deinem PC läuft, Single-User (...) kannst du dir auch vieles ersparen...

Ich kann nur von mir selbst berichten, aber da bleibt ganz klar nur eins: Erfahrung, Erfahrung und nochmals Erfahrung


----------



## slawaweis (17. Feb 2011)

KSG9|sebastian hat gesagt.:


> Hast du alles in einem Projekt garantiere ich dir das nach spätestens 2 Wochen die Präsentationslogik direkte Abhängigkeiten auf die Backendzugriffslogik hat.


und wie es erst nach ein paar Jahren aussieht ... 

Danke für alle Antworten. Mir war wichtig zu erfahren, wie man so was machen kann bzw. wie es andere machen. Als Lösung für mein Problem bediene ich mich der virtuellen Module. D.h. das Projekt bleibt ein IDE Projekt und somit ein großer Haufen. Allerdings werden zusätzlich Modulbeschreibungen definiert, welcher Teil des Programms zu welchen Modul gehört. Diese globale Beschreibung/Struktur ist zuerst virtuell und kann leicht verändert werden. Zusätzlich gibt es ein Hilfsprogramm, welches das Hauptprogramm auf der Quelltextebene anhand der Definition der virtuellen Module überwacht und Abweichungen meldet. Dann wird Schritt für Schritt das Programm einem Refactoring unterzogen, bis es zu der Definition der virtuellen Module passt.

Slawa


----------



## fastjack (17. Feb 2011)

Bei uns trennen wir logische Schichten (Anbindungen zu externen Systemen, Persistenz, GUI, Webgui, Installer usw.) in eigene Projekte auf.  Projekte die zu einem "Oberprojekt" gehören fassen wir in Workingsets zusammen, ansonsten bleiben sie "allein"  Sind Projekte abhängig von anderen, definieren wir in Eclipse eine Abhängigkeit. So ungefähr ist das auch in SVN abgebildet. Das Refactoring klappt mit Eclipse bestens über mehrere Projekte hinweg, vorausgesetzt sie sind auch im Workspace angelegt.

Edit: In einer anderen Firma gab es immer nur ein Projekt, mit hunderten Packages. Das Problem war, das man immer alles bauen mußte, immer alles taggen mußte usw. Es gab schwere Probleme bei Releases, die nur eine kleine Änderung enthielten, aber immer in einem Volldeploy ausarteten. Alles war unübersichtlich und groß, sozusagen ein FatProjekt.


----------

