Code versionsabhängig ausführen
-
Hallo Forum,
es ist nicht unbedingt ein C# Thema, ich brauch jedoch eine Lösung speziell für C#.
Ich möchte hier mal zu einen Brainstorming einladen, bzw. BestPractise erarbeiten zu dem Thema "Code versionsabhängig ausführen".
Folgendes Problem:
SW in der Version V1 ist am Markt, V2 in der Entwicklung. Die V1 Funktionen sollen (möglichst) nicht angefasst werden und auch in der V2 laufen.1. Function-Switch
if(V1){ foo(); //ursprüngliche Funktion } else{ fooV2(); //neue Funktion }
2. Parameter-Switch
string version="V2"; foo(version); oder: string version="V1"; Object myObject = new Object(version);
Zugegeben sind diese Lösungsvorschläge "billig".
Ich dachte mir auch eine Lösung mit Attributen, schade nur, dass sich Klassennamen/Methodennamen unterscheiden müssen.
Sowas wär cool:[V1] public class Klasse() {...} [V2] public class Klasse() {...} public class UniverselleKlasse() { [V1] public void foo(); [V2] public void foo(); }
Oder aber ein Design-Pattern?
Ich habe diesen Thread eröffnet, weil ich im Netz nichts, aber auch gar nichts gefunden habe. Hoffe auf ein paar Ideen dazu.
-
Hier noch gleich ein Lösungsansatz: Vererbung
public class Object {...} public class ObjectV2 : Object {...} if(V1) Object myObject = new Object(); else ObjectV2 myObject = new ObjectV2();
-
"worst case" gekillt
wie wäre es mit Code duplizieren und neues Projekt anlegen? ... alternativ (wie ich es gerade mache) - komplett neu? ... Letztes sollte sich ggf. lohnen
-
Man hat eine Software draußen und bringt eine neue Version raus, warum kann die neue Version nicht V2 benutzen und die alte bei ihren V1 bleiben?
Oder reden wir von einer Api?
Wenn es um Schnittstellen geht ist es besser wenn diese nicht geändert werden.Aber ist doch ganz simpel, wird es intern einfach weiter delegiert.
//Was der Kunde sieht: TheObject.DoSomething(object param); //Im Code: public void DoSomething(object param) { Transmit(param); }
Nun kommt eine neue Version der Api, diese hat eine neue Funktion die macht das selbe, nur schneller.
Schnittstelle wird nicht geändert und die Schnellere Methode kommt hinzu.//Was der Kunde sieht: TheObject.DoSomething(object param); TheObject.DoSomethingBetter(object param); //Im Code: [Obsolete("The DoSomething is obsolete, please use DoSomethingBetter instead.")] public void DoSomething(object param) { DoSomethingBetter(param); } public void DoSomethingBetter(object param) { Transmit(param); }
Aber wie gesagt, ich habe das Problem nicht ganz verstanden.
-
electron_ schrieb:
Sowas wär cool:
[V1] public class Klasse() {...} [V2] public class Klasse() {...} public class UniverselleKlasse() { [V1] public void foo(); [V2] public void foo(); }
Sowas in der Art gibt es, es heißt bedingte Compilierung, die Syntax ist bloß etwas anders.
-
CSL schrieb:
Nun kommt eine neue Version der Api, diese hat eine neue Funktion die macht das selbe, nur schneller.
Schnittstelle wird nicht geändert und die Schnellere Methode kommt hinzu.Danke für den Beitrag, für API denke ich unbedingt notwendig.
CSL schrieb:
Aber wie gesagt, ich habe das Problem nicht ganz verstanden.
Ein konkretes Beispiel:
WordV1 ist draussen, der Kunde öffnet, bearbeitet und speichert V1 Dokumente. Jetzt wird V2 entwickelt mit der Anforderung, Mit V2 die V1 Dokumente zu öffnen und nach belieben wieder in V1 Mode zu speichern oder aber nach V2 zu migrieren.
D.h. der V1 Code muss wenigstens in Teilen erhalten bleiben.-com- schrieb:
Sowas in der Art gibt es, es heißt bedingte Compilierung, die Syntax ist bloß etwas anders.
...ist ein guter Vorschlag, aber es muss zur Laufzeit umschaltbar sein
-
electron_ schrieb:
-com- schrieb:
Sowas in der Art gibt es, es heißt bedingte Compilierung, die Syntax ist bloß etwas anders.
...ist ein guter Vorschlag, aber es muss zur Laufzeit umschaltbar sein
ISt eher ein richtig schlechter Vorschlag. Versuch Dir das mal mit 4 Versionen vorzustellen oder mit 8... Dann sollte erkennbar sein warum solche Ansätze mittel- und langfristig immer in Chaos enden.
Im Prinzip hat CSL bisher den besten Ansatz gebracht: Gegen Interfaces entwicklen. Version 1 ist dann in einer eigenen dll, nennen wir sie Version1.dll, version 2 in Version2.dll usw.
Zu Laufzeit entscheidest Du dann welche Du gerade brauchst und rufst dann die FUnktionen aus der entsprechenden DLL auf. Einfach, simple und in C# fast geschenkt vom Codeaufwand.
Bonus: Jede Version ist in einem eigenen MOdul (dll) und Änderungen in V2 _können_ garantiert keine Seiteneffekte auf bestehenden Code von V1 haben.
Ausserdem: Mit dem Konzept können auch mehr als zwei Versionen sauber verwaltet werden ohne das man irgendwann im Chaos endet...
-
@electron_:
Normalerweise arbeitet man bei Programmen wie Word o.ä. mit Konvertierungs-Funktionen die das V1 Format nach V2 konvertieren können und umgekehrt.Die interne Representation ist immer V2, d.h. beim Laden wird V1 nach V2 konvertiert.
Idealerweise ist diese Konvertierung verlustfrei möglich.Beim Speichern muss dann V2 zu V1 zurück-konvertiert werden. Diese Konvertierung ist meist nicht verlustfrei möglich. Man kann dem User aber eine Warnung geben, und ihm sagen dass bestimmte Dinge nicht im alten Dokumentformat abgebildet werden können.
-
loks schrieb:
Ausserdem: Mit dem Konzept können auch mehr als zwei Versionen sauber verwaltet werden ohne das man irgendwann im Chaos endet...
Sobald sich die Interfaces der neuen Dokument-Klassen mal ändern, bekommst du schnell ein Problem im Editor. Bzw. in allen Teilen die nicht gesplittet werden sollen.
Davon abgesehen wird deine Code-Base immer grösser. Bugs müssen an mehreren Stellen gefixt werden.IMO ist das nicht viel was anderes, als zwei getrennte Programme auszuliefern (V1 und V2), nur schlechter.
-
hustbaer schrieb:
Bzw. in allen Teilen die nicht gesplittet werden sollen.
Genau. Letztendlich habe ich mit V2 eine neue Appplikation, die aber unbedingt Teile vom original V1 Code aufruft. Ob der V1 Code hineinkopiert wird oder in eine V1 dll ausgelagert wird ist unerheblich. Letztendlich muss ich immmer noch versionsabhängig aufrufen.
Noch weitere konkrete Vorschläge, wie ihr das machen würdet?