# Konfigurationsmanagement - Kundenspezifische Release-Builds



## Togaras (1. Mrz 2008)

Hallo,

ich stehe im Moment vor der Aufgabe ein Projekt mit unterschiedlichen kundenspezifischen Release-Builds zu verwalten. Es handelt sich um ein Applikation, die als Servlet im tomcat läuft und Hibernate als Datenbankanbindung verwendet. Bislang war die Software so gestaltet, dass jedes Release exakt identisch ist, lediglich unterschiedliche Datenbankverbindungsdaten enthält. Da die Anzahl der Releases noch recht übersichtlich ist, stellt es bislang kein Problem dar, die Verbindungsdaten von hand zu ändern, das WAR-file zu builden und auf dem entsprechenden Tomcat zu deployen. 

Leider beginnen jetzt die ersten Anforderungen, dass einige spezialisierte Anpassungen für einige Kunden vorgenommen werden. Das sieht im Grunde so aus, dass einige Klassen für die GUI an die Kundenwünsche angepasst werden müssten und ich somit eine Klasse mehrfach verwalten müsste. Es handelt sich hierbei aber effektiv um weniger als 1% der verwendenten Klassen. Alle anderen unterliegen dem normalen Release und Update Prozess, so dass Bugfixes immer an alle Kunden verteilt werden können.

Ein weiterer Verwaltungsaufwand entsteht, wenn die Menge der Kundenprojekte die Übersichtlichkeit verliert und ein manuelles Anpassen der Datenbankkonfigurationen zu aufwendig wird. 

Ich suche nun nach Lösungsansätzen wie ich diese beiden Probleme gut in den Begriff bekommen kann und die Aufwände für das Builden und die Codeverwaltung reduzieren kann. Ich lese mich im Moment in Tools wie Ant und Maven ein, bin mir aber nicht sicher ob ich damit alles abdecken kann. Welche Empfehlungen zu Tools, Prozessen und Literatur könnt ihr mir geben?

Viele Grüße
Togaras


----------



## maki (1. Mrz 2008)

Ant kannst du dir sparen, ist überholt wenn es um den Build geht.
Maven 2 hilft dir eher, aber eine Quellcode Versionierung brauchst du auch, zB CVS oder (imho) besser gleich Subversion.

Bücher: 
- Better Builds with Maven (gratis ebook: http://www.devzuz.com/web/guest/products/resources)
- Version Control with Subversion (gratis ebook: http://svnbook.red-bean.com/)
- Pragmatic version control using subversion

Gibt bestimmt auch gute Bücher für SW CM, kenne nur leider keine


----------



## Togaras (1. Mrz 2008)

Subversion wird bereits verwendet um den Quellcode des Projektes zu versionieren und die Teamarbeit von im Moment 8 Personen einfach zu gestalten. Für die Kundenspezifischen Anpassungen sehe ich in SVN aber keine Hilfestellung. Je Kunde einen eigenen Branch zu erstellen ist etwas schwierig, denn um die kundenspezifischen Elemente herum gibt es regelmässig Improvements, die immer für alle gelten sollen.

Ein Beispiel:
Wir haben ein Fenster zur Eingabe der Personendaten. WindowPerson.java. In diesem Fenster gibt es verschiedene Tabs oder Bereiche, in denen verschiedene Informationen angezeigt und eingegeben werden können. Diese Tabs sind im Window registriert. Z.B.: PersonTabName.java, PersonTabAddress.java, PersonTabCommunication.java. In einem Tab gibt es nun eine spezielle Anforderung, die nicht mehr mit der Dynamik aus anderen Bereichen realisiert werden kann, sondern nur durch das austauschen der Klasse im Build. Nehmen wir den PersonTabAddress als Beispiel.

Ich habe also im Code: pack.age.path.gui.persons.PersonTabAddress.java.
Von dieser Klasse möchte ich jetzt zwei Versionen haben, eine "Standard" und eine "Customer4711".
Beim Builden soll dann im Falle des Customer4711-Builds die entsprechende Klasse ausgetauscht werden. Die Schnittstellen von beiden sind so identisch, dass sie problemlos mit dem WindowPerson agieren können.

Wie sollte ich nun die Ablage dieser Klassen organisieren? 
Ich habe im Moment zwei verschiedene Ideen, weiss aber nicht ob die so optimal sind. Zunächst einmal werden beide Versionen nebeneinander im Code hinterlegt, z.B.:
A) pack.age.path.gui.persons.PersonTabAddress.java
B) pack.age.path.gui.persons.customer4711.PersonTabAddress.java

Weg 1 sieht nun vor, vor dem Builden den Inhalt von A zu sichern und den Inhalt von B in A zu kopieren, anschließend den Build zu erstellen. 

Weg 2 sieht vor, die Import-Zeile von WindowPerson.java mit dem Verweis auf den PersonTabAddress auszutauschen. 

Fragen die sich mir dazu stellen:
a) welcher weg ist optimaler
b) gibt es nicht noch einen besseren weg
c) kann ich dies mit maven (oder ant) überhaupt entsprechend ansteuern?


----------



## maki (1. Mrz 2008)

> Je Kunde einen eigenen Branch zu erstellen ist etwas schwierig, denn um die kundenspezifischen Elemente herum gibt es regelmässig Improvements, die immer für alle gelten sollen.


Was bleibt denn als Alternative? 

Branching und Merging sind alltägliche Aufgaben, gibt sogar eigene Stellen dafür.
Change- und Configuration Management helfen dir den Überblick zu behalten wenn es um Änderungen geht die in mehrere Branches eingepflegt werden müssen.

Finde deine beiden Vorschläge nicht besonders praxistauglich.

Tatsache ist, dass du verschiedene Anforderungen, Designs und Produktstrukturen verwalten musst , am besten mit Baselines.
Für das Design (Quellcode und Metainfo aus denen Quellcode generiert wird) eignet sich Subversion besser als irgendein schräges Script was Java Quellcode manipuliert.

Wie willst du mit deinen 2 Wegen in der Lage sein ein bestimmtes Release nachzubauen?

Denkbar wäre auch die zu verwendende Klassen per Dependency Injection festzulegen per (XML) Konfig Datei, aber wieder ist das Quellcode der Versioniert und Branches zugeordnet werden sollte.


----------



## Togaras (2. Mrz 2008)

Ok, ich verstehe, dass meine Idee mit den Scripten und dem Austauschen nicht sonderlich optimal sein könnte. 

Doch wie sollte ich den deiner Meinung nach das SVN organisieren, wenn von 1000 Klassen gerade mal 2 in einem Projekt anders sind. Wenn ich im SVN mit Branches arbeite, sind es doch praktisch paralele Versionen, dass heisst, ich muss Bugfixes, Erweiterungen etc doch doppelt pflegen. Das jedenfalls ist es, was ich an der Arbeit mit mehreren Branches bislang verstanden habe. Ich möchte, dass alle anderen 998 Klassen absolut identisch sind, die zwei besonderen aber unter gar keinen Umständen verändert werden, es sei denn sie werden gezielt geändert für dieses Kundenprojekt. Ich möchte definitiv vermeiden, dass ein Build für einen bestimmten Kunden.

Durch die Scriptideen oben, sehe ich übrigens kein Problem einen entsprechenden Build zu erstellen. Zunächst springe ich Codetechnisch auf die entsprechende Revision und dann verwende ich gezielt das Build-Script um entweder eine Standardversion oder eine kundenspezifische Anpassung zu starten. Und damit habe ich exakt das Build, welches ich suche.

Aber okay, ich würd gern verstehen, wie ich das Problem mittels SVN Branches lösen kann. Hab ich irgendwas an Branches noch nicht verstanden oder seh ich nur die Lösung vor lauter Bäumen nicht? Ich sehe einfach den Aufwand zwei Branches zu betreiben für sehr groß an.


----------



## AlArenal (2. Mrz 2008)

Für die Verwaltung von Kundenanpassungen habe ich diese einfach immer als Features angesehen. Entsprechend haben alle Kunden dieselbe Software bekommen, lediglich unterschiedliche Konfigurationen.
Mitunter ist es natürlich eine Menge Aufwand im Nachhinein die Logik komplett umzustricken, aber den Aufwand hat man ja so oder so.


----------



## kama (2. Mrz 2008)

Hallo,



			
				Togaras hat gesagt.:
			
		

> Doch wie sollte ich den deiner Meinung nach das SVN organisieren, wenn von 1000 Klassen gerade mal 2 in einem Projekt anders sind.


Wenn das tatsächlich so ist, dann bedeutet es, dass die Informationen in den beiden Klassen in eine Konfigurationsdatei gehört...



			
				Togaras hat gesagt.:
			
		

> Wenn ich im SVN mit Branches arbeite, sind es doch praktisch paralele Versionen, dass heisst, ich muss Bugfixes, Erweiterungen etc doch doppelt pflegen.


Falsch. Die Bug-Fixes / Features werden ebenfalls auf einem Branch entwickelt...und danach wird der Branch einfach einmal in den einen Branch integriert und nochmal in den anderen Branch. 
Der Einzige Aufwand der Notwendig ist, ist die Arbeit der Integration.....aber das rechnet sich...die sollte im üblichen Fall ohne Problem laufen.

Nach einer Release wird wieder ein sog. Baseline gezogen und danach wieder jeweils zwei bzw. n-Branches pro Kunde erzeugt....und das Spiel läuft von Vorne.....

Zu Deinem Problem mit den Kundenspezifischen Klassen, könnte man in der Form lösen, dass Du ein Interface erstellst, dass die Schnittstelle definierst. Die Kundenspezifischen Implementieren entsprechend einer Namenskonventions ablegen...
Beim Start der Applikation wird aus einer Konfigurationsdatei gelesen welche Klassen denn nun tatsächlich instanziert wird (Reflection)....
Fertig....


Weiterhin kann auch nur empfehlen Maven einzusetzen...Ant funktioniert auch.....ist aber insgesamt gesehen mehr arbeit..

Weiterhin empfehle ich den Einsatz eines Build-Servers (z.B. Continuum o.ä.)...

Wichtig sind auch Unit Tests !!!


EDIT: Hier noch mal nachschauen http://www.skmwiki.de/wiki/Base_Lining

MfG
Karl Heinz Marbaise


----------



## Guest (2. Mrz 2008)

Müssen sämtliche Daten auch auf Klassen abgebildet werden? Es gibt Möglichkeiten flexible Datenmodelle 
zu schaffen, die dann anhand von Metadaten kundenspezifisch initialisiert werden. Damit beschränkt sich 
die ganze Geschichte auf die Pflege der Metadaten. Diese sind dann auch beliebig erweiterbar/änderbar.
Nur mal so als Anreiz zum Nachdenken.


----------



## Togaras (18. Mrz 2008)

Ok ich glaub ich habs jetzt verstanden, vorallem das Bild mit dem Base-Lining war sehr hilfreich. Vielen Dank euch. Werd das mal ausprobieren und dann schauen ob ich es so einsetzen kann, wie ich vorhabe.

Vielleicht noch eine letzte Frage dazu:
also ich hab jetzt den Pfad "specific customer 1" (SC1) und den Pfad "unspecific" (U). jetzt wäre es vermutlich sinn voll, die in sc1 geänderte klasse in U nicht mehr weiter ändern zu müssen, jetzt kommt es aber doch dazu. würde ich jetzt von U auf SC1 updaten um bugfixes nach zu ziehen, hätte ich wohl ein problem.

ich sehe jetzt zwei lösungsmöglichkeiten
a) den U-Pfad analog wie SC1 betrachten und die Entwicklung vom trunk auf U und auf SC1 mergen
b) beim mergen die dann entstehenden konflikte manuell lösen

was wäre einfacher? ich denke fast a, weil damit ist der U1 pfad eigentlich wie eine eigene kundenversion.


----------

