-Verschiedene Versionen eines Programms verwalten

CSHW89

Bekanntes Mitglied
Hallo Leute,

ich habe ein Programm geschrieben, das bei einem Kunden schon erfolgreich arbeitet. Nun kam ein anderer Kunde auf mich zu, und möchte das selbe Programm haben, allerdings mit einigen kleinen Änderungen (hier mal ein Text anders, dort ne zusätzliche Schaltfläche ect...).
Nun frage ich mich, wie ich die beiden (oder später vielleicht auch mehrere) verschiedenen Versionen verwalte. Zur Info, ich benutze Eclipse und Git. Ich kam auf die Idee mit Git zwei (bzw. später mehrere) Branches zu erstellen, die dann für immer gleichzeitig verlaufen. Ich habe allerdings gelesen, dass das keine besonders gute Idee ist, da jede noch so kleine Änderung in alle Branches gemergt werden müssen, was deutlich Zeit kostet, und fehleranfällig ist.
Eine andere Idee wären kleine Precompile-Direktiven wie in C/C++. Allerdings hat Java das ja nicht. Weiß jemand, wie man das umsetzen könnte, oder hat vielleicht andere Ideen zu meinem Problem? Wäre da für jeden kleinen Denkanstoß dankbar.

Vielen Dank schon mal
lg Kevin
 
Also unterschiedliche Texte würde ich rein über abweichende Ressourcedateien handhaben.

Funktionale Unterschiede würde ich an Deiner Stelle immer vermeiden wenn irgendwie möglich. Die Branche sind für einen "private Fix" durchaus ok, aber die sollten dann recht schnell in den Main-Zweig eingehen.

Wenn dies überhaupt nicht anders gehen sollte, wäre es evtl. denkbar, die Unterschiede sehr lokal zu halten. Ggf. kann man sich hier ja eine Implementation überlegen, über die eine Art AddOn eingebunden wird. Das eigentliche Programm ist dann immer gleich nur eben bekommt der Kunde dann noch ein weiteres jar mit der notwendigen Konfigurations-Anpassung. (Auch die Anpassungen an den Ressourcen würde ich ebenso additiv umsetzen)

So würde ich das angehen, wobei ich so einen Fall bisher noch nicht wirklich hatte.
 
Es kommt darauf an worin die Unterschiede bestehen und in welchem Umfang! Wenn es nur oberflächige Unterschiede sind dann ist es nicht schwer bzw. kein großes Problem.
Bei Unterschiedlicher Geschäftslogik und/oder Datenmodell wird es schon schwerer.

Generell sollte es kein Problem sein wenn dein Programm eine passende Trennung zwischen den Schichten aufweist (https://de.wikipedia.org/wiki/Schichtenarchitektur).
Hierbei kommunizieren die Schichten nur mit der jeweils darunterliegenden Schicht und auch nur über Interfaces. Dadurch kannst du zum Beispiel die Präsentationsschicht (Oberfläche/UI) einfach austauschen gegen eine andere ohne Code der darunterliegenden Schichten anzupassen.

Soll hingegen statt auf einer MySQL Datenbank in Files oder einer Oracle Datenbank gespeichert werden dann muss man eben die Datenzugriffsschicht austauschen. Sind nur Berechnungen anders dann kann man die Geschäftslogik austauschen.

Sind Änderungen in allen Schichten vorzunehmen dann wäre es wahrscheinlich besser die Projekte zu duplizieren. Wenn beide Varianten laufen kann man schauen welche Gemeinsamkeiten man rausziehen kann in eigene Basisprojekte. Diese können dann eben auch als Grundlagen für die Applikation für Kunde C dienen.
 
Danke schonmal für die Antworten.

Eine gewisse Trennung der Schichten besitze ich. Allerdings finde ich das MVC-Modell etwas zu ideallisiert. Meine Daten sind vom View und Control getrennt. Da sehe ich keine Probleme. View und Control zu trennen sehe ich allerdings immer etwas kritischer. Ich mein, ein Main-Control besitze ich, dass dafür zuständig ist, zwischen den Views zu navigieren. Die "Logik" der Views managen die Views aber selbst. (Ich will aber jetzt hier keine Grundsatzdiskussion führen, nur zeigen, wies bei mir aussieht).

Das mit den Interfaces ist natürlich ein probates Mittel. Ich sehe da allerdings die Gefahr der Codeduplizierung. Mal ein kleines anschauliches Beispiel: Ich hab ein recht unfangreiches View, in der Mitte ist eine Tabelle mit Produkten, jedes Produkt hat nun drei verschiedene Preise zu verschiedenen Zeiten (z.b. Wochenende ein anderer Preis oder so was). Nun will aber Kunde B meines Programms nur ein immer gleichen Preis für jedes Produkt. Intern belasse ich es nun bei drei Preisen, zeige aber immer nur einen an, und wenn dieser geändert wird, ändern sich intern alle drei. Problem mit wenig Aufwand gelöst.
Dafür könnte ich jetzt also hingehen, und das unfangreiche View kopieren und dort die beiden Spalten einfach entfernen. Jetzt hab ich allerdings zwei fast identische Views. Selbst wenn ich das Control vom View trennen würde, müsste ich View und Control duplizieren. Und beim View: selbst wenn ich die Tabelle alleine kopieren würde, wäre es noch einiges an doppeltem Code. Spätere Änderungen an der Tabelle müssten doppelt und dreifach ausgeführt werden.

Gibt es keine bessere Möglichkeit in Git, zwei fast identische Branches (oder was weiß ich) laufen zu lassen, oder gibt es Pre-Compiler-Direktiven in Java per Plugins in Eclipse?
 
Was haben Interfaces mit Codeduplizierung zu tun? Nur wenn die Interfaces nicht passend definiert sind, kann das passieren. (Oder man etwas zu generisch machen will)

Ansonsten musst du dir die Frage stellen, willst du ein Standardprodukt anbieten oder spezielle Lösungen. Bei letzerem wirst du nicht drum rum kommen pro Kunde speziellen Code zu verwendet. Bei ersterem müssen Kunden damit leben, dass die Software vielleicht Features bietet, die sie im moment nicht verwenden.
 
Bei dem speziellen Beispiel von oben sieht die Tabelle fast identisch aus (nur zwei Spalten fehlen). Egal wie man das Interface definiert, das Aussehen und das Verwalten der anderen Spalten muss man immer duplizieren. Gut das könnte man vielleicht irgendwie ohne hinkriegen, aber nicht sehr intuitiv. Vielleicht mit sowas wie einem Standardaussehen/verhalten und einem "Änderungs" bzw. "Abweichungs"-Interface oder so.
 
Also diese Problematik kann man doch durch eine Generalisierung des Datenmodells und der Views / Controller erreichen. Statt 3 Preisen hat man dann eine dynamische Anzahl an Preisen mit ggf. weiteren Eigenschaften (Wann ist welcher Preis gültig). Und die Zugriffe darauf verändern sich dann halt auch, weil ein Zeitpunkt angegeben werden muss. Das Beispiel würde ich also als ein einfaches Feature in der Software sehen.

Komplizierter sind abweichende Logiken, bei der es keine Generalisierung gibt, die alle Fälle abdecken. Aber auch da gibt es durch OO Techniken keinen doppelten Code. (Den Punkt kann ich eh nicht ganz verstehen. Für die Eliminierung von doppeltem Code gibt es ja eben diverse Refactorings.)
 
Ich würde keinesfalls den Source-Code auseinander laufen lassen.

Mein Ansatz wäre eine Brutto-Version, die alle Varianten beinhaltet und über Konfigurationsparameter auf die einzelnen Kunden angepasst wird.
Die Konfigurationsparameter sind entweder Ja/Nein-Schalter, Aufzählungen oder einzustellende Werte.
Dabei würde ich versuchen fachliche Begriffe zu finden, die diese Parameter beschreiben.
Alles, was dann noch an Unterschieden übrig bleibt, würde ich über einen allgemeinen Parameter steuern. Also quasi einen Parameter, der für jeden unterstützten Kunden einen Wert hat.

Bei der Realisierung der Unterschiede gibt es verschiedene Varianten.
Bei der Oberfläche kann man eine Brutto-Maske erstellen und alle in dieser Varianten nicht benötigten Felder verstecken. Ein passender Layouter müsste dann die Maske so rendern, dass Lücken geschlossen werden. Hier hängt es davon ab, ob man einen User-Interface-Editor benutzt oder die Maske im Code dynamisch erstellt.
Funktionale Unterschiede kann man durch verschiedene abgeleitete Klassen (-> Instantiierung über Factories) oder das Delegator-Pattern realisieren.
Kleine Unterschiede können aber auch etwas schlampig durch ein einfaches IF-THEN-ELSE Konstrukt realisiert werden. Wenn es dann immer mehr IF's gibt, kann man später immer noch Refaktoring einsetzen.
 

Zurück
Oben