Trennen von Java-Projekten


12

Ich habe ein großes Java-Projekt und wir verwenden Maven für unseren Build-Zyklus. Dieses eine Projekt wird ausgiebig genutzt - in anderen Projekten, in verschiedenen Anwendungen, von denen einige darin enthalten sind und andere an anderer Stelle ... Um ehrlich zu sein, ist es ein bisschen chaotisch (verschiedene Bits werden zu unterschiedlichen Zeiten für bestimmte hinzugefügt) Zwecke), und ich möchte es ein wenig aufräumen. Außerdem ist es nicht vollständig getestet (viele Bits wurden ohne ordnungsgemäßen Unit- und Integrationstest hinzugefügt), und es gibt einige Tests, deren Ausführung sehr lange dauert oder die nicht erfolgreich sind ... (ähm) - also Tests werden im Maven-Build-Zyklus abgeschaltet (wieder, oh-oh).

Ich denke darüber nach, dieses große Projekt in kleinere spezifische Projekte zu unterteilen, so dass das "endgültige" Unterprojekt (oder mehrere Unterprojekte) die verschiedenen Unterprojekte aufgreift, die es benötigen würde.

Ich denke wie folgt:

  • Wenn ich das große Projekt in verschiedene Unterprojekte aufteile, wird klar, wozu jedes Projekt zuständig ist.
  • Durch Aufteilen in Unterprojekte kann ich dann das Testen jedes Unterprojekts einzeln bereinigen und das Testen für dieses Unterprojekt im Maven-Erstellungszyklus aktivieren.

Ich bin etwas besorgt darüber, welche Auswirkungen dies auf die Build-Zeit haben könnte.

  • Würde das Auferlegen einer Struktur für das große Projekt (dh für kleinere Unterprojekte) den Compiler verlangsamen?

Ich bin auch ein wenig besorgt darüber, welche Auswirkungen dies auf die Bearbeitungszeit in IDEs haben könnte (wir verwenden hauptsächlich Intellij). Intellij scheint jedes Projekt der Reihe nach über den Abhängigkeitsbaum zu erstellen. Wenn also C von B von A abhängt und ich A ändere, wird B erst dann erstellt, wenn A kompiliert und so weiter. Das ist zwar von Vorteil, aber ich habe festgestellt, dass es einige Zeit dauert, bis alle Fehler aus dieser Änderung behoben sind, wenn ich beispielsweise eine in B und C häufig verwendete Schnittstelle in A ändere.

Eine andere Frage ist, wie Factory-Klassen verwendet werden. Einige Aspekte des Projekts hängen von externen Gläsern ab. Gelegentlich (zum Glück nicht oft) werden diese aktualisiert, und wir müssen migrieren. Wir neigen dazu, eine Factory-Klasse zu verwenden, die auf die richtigen Versionen des externen Codes verweist (damit wir nicht alle Implementierungen in der gesamten Codebasis ändern müssen).

Im Moment ist das alles in dem großen Projekt, aber ich denke, dass ich durch den Wechsel zu Unterprojekten ein neues Projekt für die Implementierung von neuem externem Code entwickeln und sicherstellen könnte, dass das Unterprojekt voll funktionsfähig und getestet ist Wechseln Sie dann die Abhängigkeiten / Factory-Klasse im Anwenderprojekt. Dies wird jedoch durch die umfangreiche Verwendung von Schnittstellen im gesamten Großprojekt erschwert. Beispielsweise

  • Unterprojekt A - enthält Schnittstellen
  • Unterprojekt B - hängt von A für Schnittstellen und altes externes Glas ab
  • Unterprojekt C - hängt von B (und damit von A und dem alten externen Jar) ab und enthält eine Factory-Klasse, die die Schnittstellenimplementierungen von B verwendet

Wenn ich das äußere Glas von B wechseln muss, kann ich:

  • Unterprojekt B_ii erstellen - hängt wieder von A und jetzt dem neuen externen Glas ab
  • Sobald ich voll funktionsfähig bin, kann ich Cs Abhängigkeit zu B_ii hinzufügen und die Factory-Klasse ändern, um die neuen Implementierungen von Schnittstellen zu verwenden.
  • Wenn das alles funktioniert, kann ich dann Cs Abhängigkeit von Original B entfernen und, falls gewünscht, Teilprojekt B entfernen.

  • Ist das eine vernünftige Vorgehensweise?

Im Allgemeinen sind meine Fragen also:

  • Hat jemand Erfahrung damit, große Projekte aufzubrechen? Gibt es Tipps / Tricks, die Sie gerne teilen würden?
  • Welchen Einfluss hatte dies auf Ihre Entwicklungs- und Bauzeiten?
  • Welchen Rat könnten Sie zur Strukturierung einer solchen Aufteilung eines solchen Projekts geben?

Beachten Sie, dass Sie ein übergeordnetes Projekt erstellen können, bei dem A, B und C separat nebeneinander ausgecheckt sind. Dies ermöglicht zB IntelliJ, alle drei gleichzeitig im Speicher zu haben und Refactorings über Modulgrenzen hinweg durchzuführen.
Thorbjørn Ravn Andersen

Antworten:


10

Ich werde einen kurzen ersten Schnitt machen (großartige Q BTW!):

Würde das Auferlegen einer Struktur für das große Projekt (dh für kleinere Unterprojekte) den Compiler verlangsamen?

Nicht genug, dass es darauf ankommt, der Overhead liegt tatsächlich bei Maven-Aufrufen.

Ich bin auch ein wenig besorgt darüber, welche Auswirkungen dies auf die Bearbeitungszeit in IDEs haben könnte (wir verwenden hauptsächlich Intellij). Intellij scheint jedes Projekt der Reihe nach über den Abhängigkeitsbaum zu erstellen. Wenn also C von B von A abhängt und ich A ändere, wird B erst dann erstellt, wenn A kompiliert und so weiter. Das ist zwar von Vorteil, aber ich habe festgestellt, dass es einige Zeit dauert, bis alle Fehler aus dieser Änderung behoben sind, wenn ich beispielsweise eine in B und C häufig verwendete Schnittstelle in A ändere.

Unterschiedliche IDEs haben unterschiedliche Stärken in Bezug auf Maven-Bindungen und das Abhängigkeitsmanagement. Der aktuelle Stand scheint zu sein, dass es meistens nur auf den neuesten Eclipse-, Netbeans- und IntelliJ-Versionen funktioniert - aber Sie müssen Ihren Entwicklern den Notfall-Doppelschlag "Quelldateien von der Festplatte aktualisieren und alle zugehörigen Maven-Projekte neu erstellen" beibringen.

Allerdings muss ich das heutzutage immer weniger. Ein SSD-Laufwerk macht hier übrigens einen gewaltigen Unterschied.

Snip Factory Klassen Absätze

Das Abhängigkeitsmanagement ist unglaublich wichtig, unabhängig davon, mit welcher Technologie (Maven / Ivy / was auch immer) Sie es implementieren.

Ich würde damit beginnen, das umfangreiche Reporting aus dem Maven-Abhängigkeits-Plugin zu holen und eine Bestandsaufnahme dessen zu machen, was Sie haben. Im Allgemeinen legen Sie die Abhängigkeit im Abhängigkeitsmanagement des POM so hoch wie möglich in der Nahrungskette fest, jedoch nicht höher. Wenn also zwei Ihrer Submodule eine externe Abhängigkeit verwenden, ziehen Sie diese in ihren übergeordneten POM und so weiter und so fort.

Das Upgrade von externen JARs sollte immer als richtiges Miniprojekt durchgeführt werden. Bewerten Sie, warum Sie ein Upgrade durchführen, ändern Sie den Quellcode, um die Vorteile neuer Funktionen / Fehlerbehebungen usw. zu nutzen. Wenn Sie die Version nur ohne diese Analyse und Arbeit anstoßen, geraten Sie in Schwierigkeiten.

Im Allgemeinen sind meine Fragen also:

Hat jemand Erfahrung damit, große Projekte aufzubrechen? Gibt es irgendwelche> Tipps / Tricks, die Sie gerne teilen würden?

  • Interfaces und Dependency Injection sind dein Freund.
  • Michael Feders Buch über den effektiven Umgang mit altem Code ist ein Muss.
  • Integrationstests sind dein Freund
  • Das Aufteilen der Unterprojekte in foo-api (nur Schnittstellen!) Und foo-core und das Vorhandensein von Modulen, die nur von der foo-api abhängen, hilft sehr und erzwingt die Trennung
  • Jboss-Module und / oder OSGi können dabei helfen, eine saubere Trennung durchzusetzen

Welchen Einfluss hatte dies auf Ihre Entwicklungs- und Bauzeiten?

Sehr geringe Auswirkungen auf die Entwicklungs- und Erstellungszeiten - ein enormer Zeitgewinn für unsere gesamte kontinuierliche Lieferpipeline.

Welchen Rat könnten Sie zur Strukturierung einer solchen Aufteilung eines solchen Projekts geben?

Tun Sie die kleinen Dinge richtig und die großen Dinge neigen dazu, danach sauber herauszufallen. Teilen Sie also die Dinge Stück für Stück auf - strukturieren Sie nicht die gesamte Partie massiv um, es sei denn, Sie haben einen hohen Prozentsatz an Abdeckung bei Ihren Integrationstests.

Schreiben Sie Integrationstests vor dem Split - Sie sollten mehr oder weniger die gleichen Ergebnisse nach dem Split erhalten.

Zeichnen Sie Diagramme der Modularität, die Sie jetzt haben und wo Sie hin möchten. Zwischenschritte entwerfen.

Nicht aufgeben - einige Yak-Rasuren bilden jetzt die Grundlage für die Fähigkeit, "ohne Angst schnell zu bauen und umzugestalten". Schamloser Plug -> von Ben und mir, The Well-Grounded Java Developer .

Viel Glück!


0

Meine Einstellung dazu ist nur dann getrennt, wenn es nötig ist. Dies wirft jedoch die nächste Frage auf: Wie bestimme ich, ob dies erforderlich ist?

  • Wenn sich das Artefakt unterscheidet (dh erstellen Sie die EAR-, WAR-, JAR- und Integrationstest-JAR-Datei nicht im selben Projekt).
  • Wenn Sie während der Trennung feststellen, dass ein Code in mehr als einem Artefakt vorhanden sein muss, müssen Sie ihn in einen neuen umwandeln.
  • Wenn ein anderes Projekt außerhalb Ihres Teams etwas verwenden möchte, das Sie in Ihrem Projekt haben.

Ein Grund dafür ist, dass die Entwickler sich mit mehreren Projekten befassen und versuchen müssen, herauszufinden, zu welchem ​​Java-Paket das Projekt gehören soll. Ich war an Projekten beteiligt, bei denen es sehr anämisch wurde, und hatte ein Projekt, bei dem nur vier Klassen eine Funktionalität implementierten, nur weil dies die architektonische Richtung ist. Dies war auch zurück, bevor Maven populär wurde, so dass die Klassenpfade und was nicht sowohl auf der IDE als auch auf den Ant-Skripten eingerichtet werden müssen.

Der andere Grund ist, dass Sie mehr bewegliche Teile benötigen, um die Dateien zu durchsuchen, und wahrscheinlich Abhängigkeits-Spaghetti haben, bevor Sie es wissen.

Refactoring ist auch innerhalb eines Projekts einfacher als projektübergreifend.

Wenn die Erstellungszeit ein Problem darstellt, stellen Sie einfach bessere Hardware bereit.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.