Was ist mit einer C ++ - Quelldatei mit 11.000 Zeilen zu tun?
Wir haben also dieses riesige (11000 Zeilen riesige?) mainmodule.cpp Quell-Datei in unserem Projekt, und jedes mal, wenn ich haben, es zu berühren ich erschaudern.
Als diese Datei ist so zentral und groß, es hält sich häufen mehr und mehr code und ich kann nicht denken, ein guter Weg, um Sie tatsächlich beginnen zu schrumpfen.
Die Datei verwendet wird und aktiv etwas verändert in mehrere (> 10) maintenance-Versionen unserer Produkte und so ist es wirklich schwer umgestalten. Wenn ich "einfach" es aufteilen, sagen wir für einen start, in 3 Dateien, die dann wieder Zusammenführen änderungen von Wartungs-Versionen wird zu einem Alptraum. Und auch wenn Sie split eine Datei mit eine so lange und reiche Geschichte, Verfolgung und überprüfung von alten Veränderungen in der SCC
Geschichte wird plötzlich viel schwieriger.
Die Datei enthält im Grunde die "main-Klasse" (Haupt-interne Arbeitsaufteilung und-Koordination) unseres Programms, also jedes mal, wenn eine Funktion Hinzugefügt wird, es wirkt sich auch auf diese Datei und jedes mal, wenn es wächst. 🙁
Was würden Sie in dieser situation tun? Irgendwelche Ideen, wie man neue Funktionen in eine separate Quelldatei, ohne in Unordnung zu den SCC
workflow?
(Hinweis auf die Werkzeuge, die Wir verwenden, C++ mit Visual Studio
; Wir verwenden AccuRev
als SCC
aber ich denke, die Art der SCC
ist nicht wirklich wichtig hier; Wir verwenden Araxis Merge
zu tun ist-Vergleich und Zusammenführen von Dateien)
InformationsquelleAutor der Frage |
Du musst angemeldet sein, um einen Kommentar abzugeben.
Finden Sie einige code in die Datei, die relativ stabil ist (nicht schnell ändert, und nicht viel variieren zwischen Zweigen) und konnte sich als eine unabhängige Einheit. Verschieben Sie diese in einer eigenen Datei, und für diese Angelegenheit in seine eigene Klasse, in allen Filialen. Weil es stabil ist, nicht zu (viele) "schwierigen" führt, die angewendet werden müssen, um eine andere Datei, aus der Sie gemacht wurden, beim Zusammenführen der änderungen von einem Zweig auf einen anderen. Wiederholen.
Finden Sie einige code in die Datei, was im Grunde nur für eine kleine Anzahl von Verzweigungen und für sich allein stehen könnte. Egal, ob es sich schnell ändern oder nicht, aufgrund der geringen Anzahl von Filialen. Verschieben Sie diese in Ihren eigenen Klassen und Dateien. Wiederholen.
Also haben wir entfernen den code, der überall gleich ist, und der code ist spezifisch für bestimmte Branchen.
Dies lässt Sie mit einem Kern von schlecht verwalteten code - es ist überall gebraucht, aber es ist anders in jeder Filiale (und/oder es ändert sich ständig, so dass einige Zweige ausgeführt werden, hinter den anderen), und trotzdem ist es in einer einzelnen Datei, die Sie erfolglos versuchen zu verschmelzen zwischen Zweigen. Hör auf damit. Zweig der Datei dauerhaftvielleicht indem Sie es in jeder Filiale. Es ist nicht "main", "main für Konfiguration X". OK, so verlieren Sie die Fähigkeit, die gleiche änderung auf mehrere Zweige durch Fusion, aber das ist in jedem Fall der Kern-code, wo das Zusammenführen funktioniert nicht sehr gut. Wenn Sie mit manuell zu verwalten, das führt eh mit Konflikten umgehen, dann ist es kein Verlust manuell übernehmen Sie selbständig in jeder Filiale.
Ich glaube, du bist falsch, zu sagen, dass die Art der SCC spielt keine Rolle, weil zum Beispiel git ' s merging Fähigkeiten sind wahrscheinlich besser, als das merge-tool, das Sie verwenden. So der Kern des Problems, "die Zusammenführung ist schwierig", tritt zu verschiedenen Zeiten für verschiedene SCCs. Sie sind jedoch kaum in der Lage zu ändern, SCCs, also das Problem ist wohl irrelevant.
InformationsquelleAutor der Antwort
Verschmelzung wird nicht so ein großer Alptraum, wie es sein wird, wenn Sie erhalten 30000 LOC-Datei in die Zukunft. Also:
Wenn man nicht einfach aufhören Codierung während der refactoring-Prozess, Sie verlassen konnte, diese große Datei wie zumindest für eine Weile, ohne das hinzufügen von mehr code hinzu: da Sie enthält eine "main Klasse" konnte man von Ihr Erben und halten geerbten Klasse(N) mit überladenen Funktionen in mehreren neuen kleinen und gut gestaltet-Dateien.
InformationsquelleAutor der Antwort
Es klingt für mich wie Sie sind mit einer Anzahl von code smells hier. Zunächst die main-Klasse zu verletzen scheint die open/closed-Prinzip. Es klingt auch wie es ist der Umgang mit zu viele Aufgaben. Aufgrund dieser würde ich davon ausgehen, den code zu spröder als es sein muss.
Ich kann zwar verstehen Ihre Bedenken in Bezug auf die Rückverfolgbarkeit nach einem refactoring, würde ich erwarten, dass diese Klasse ist eher schwer zu pflegen und zu verbessern und dass alle änderungen, die Sie machen, sind wahrscheinlich, um Nebenwirkungen zu verursachen. Ich würde davon ausgehen, dass die Kosten für diese überwiegt die Kosten für die Umgestaltung der Klasse.
In jedem Fall, da der code riecht wird nur noch schlimmer mit der Zeit, zumindest an einem gewissen Punkt die Kosten für diese überwiegen die Kosten der Umgestaltung. Von deiner Beschreibung würde ich davon ausgehen, dass Sie vorbei an der Wendepunkt.
Refactoring sollte dies in kleinen Schritten. Wenn möglich, fügen Sie automatisierte tests zu überprüfen, ob aktuelle Verhalten vor refactoring nichts. Wählen Sie dann kleine Bereiche von isolierten Funktionen und extrahieren Sie diese als Arten, um das delegieren der Verantwortung.
In jedem Fall, es klingt wie ein großes Projekt, also viel Glück 🙂
InformationsquelleAutor der Antwort
Die einzige Lösung, die ich je vorgestellt haben, um solche Probleme folgt. Der tatsächliche Gewinn durch die beschriebene Methode ist die progressivität der Entwicklungen. Keine Revolutionen hier, sonst wirst du in Schwierigkeiten sehr schnell.
Einfügen einer neuen cpp-Klasse über die ursprünglichen main-Klasse. Für jetzt, wäre es im Grunde Umleitung aller Anrufe auf die aktuelle main-Klasse, sondern Ziel ist es, dass die API dieser neuen Klasse so klar und knapp wie möglich.
Sobald dies geschehen ist, erhalten Sie die Möglichkeit, das hinzufügen von neuen Funktionalitäten in neuen Klassen.
Als für bestehenden Funktionalitäten, müssen Sie schrittweise verschieben Sie Sie in neue Klassen, wie Sie sich stabil genug. Sie verlieren SCC Hilfe für dieses Stück code, aber es ist nicht viel, dass kann getan werden. Wählen Sie einfach das richtige timing.
Ich weiß, das ist nicht perfekt, obwohl ich hoffe, dass es helfen kann, und der Prozess muss angepasst an Ihre Bedürfnisse!
Zusätzliche Informationen
Beachten Sie, dass Git ist ein SCC, die Folgen können Teile des Codes von einer Datei zur anderen. Ich habe gehört, gute Dinge über Sie, so dass es helfen könnte, während Sie schrittweise verschieben Sie Ihre Arbeit.
Git ist konstruiert, um die Vorstellung von blobs, die, wenn ich das richtig verstehe, stellen Sie Stücke von code-Dateien. Verschieben Sie diese Stücke herum, in verschiedenen Dateien und Git wird Sie finden, selbst wenn Sie Sie ändern. Abgesehen von das video von Linus Torvalds erwähnt in den Kommentaren unten, ich habe nicht in der Lage, etwas zu finden deutlich darüber.
InformationsquelleAutor der Antwort
Konfuzius sagen: "der erste Schritt, um sich aus dem Loch ist halt Loch Graben."
InformationsquelleAutor der Antwort
Lass mich raten: Zehn clients mit unterschiedlichen feature-sets und ein sales manager, der fördert "Anpassung"? Ich habe gearbeitet, auf Produkte wie die vor. Wir hatten im wesentlichen das gleiche problem.
Du erkennen, dass die eine enorme Datei ist Mühe, aber noch mehr ärger ist zehn Versionen, die Sie haben, um "aktuelle". Das ist mehrere Wartung. SCC kann das zu erleichtern, aber es kann nicht machen es richtig.
Bevor Sie versuchen, brechen Sie die Datei in Teile, die Sie benötigen, um zu bringen die zehn Niederlassungen Rücken synchron zueinander, so dass Sie sehen können, und die Form der gesamte code auf einmal. Sie können dies tun ein Zweig zu einem Zeitpunkt, testen beide Zweige gegen die gleichen Haupt-code-Datei. Zur Durchsetzung des eigenen Verhaltens, können Sie mit #ifdef und Freunde, aber es ist besser so viel wie möglich mit einem normalen if/else-gegen definierte Konstanten. Auf diese Weise werden Ihre compiler überprüft, ob alle Arten und die meisten wahrscheinlich beseitigen "Toten" Objekt-code trotzdem. (Sie können schalten Sie die Warnung über die dead code, though.)
Einmal gibt es nur eine version der Datei shared implizit durch alle Zweige, dann ist es eher einfacher zu beginnen traditionellen refactoring-Methoden.
Den #ganzen IFDEFs sind in Erster Linie besser für die Abschnitte, in denen der betroffene code macht nur Sinn im Zusammenhang mit anderen pro-Zweig Anpassungen. Man kann argumentieren, dass diese auch eine Chance für den selben Zweig-merging-Schema, aber gehen Sie nicht hog wild". Eine kolossale Projekt in einer Zeit, bitte.
In der kurzen ausführen, die Datei wird angezeigt, um zu wachsen. Das ist OK. Das, was du tust bringt die Dinge zusammen, die müssen zusammen sein. Danach werden Sie beginnen zu sehen, die Gebiete sind klar, die gleichen, unabhängig von der version; diese können Sie allein gelassen werden oder umgestaltet werden. In anderen Bereichen wird deutlich, unterscheiden sich je nach version. Sie haben eine Reihe von Optionen in diesem Fall. Eine Methode ist, zu delegieren, die Unterschiede zur pro-version-Strategie-Objekte. Ein weiteres ist die Ableitung von client-Versionen aus einer gemeinsamen abstrakten Klasse. Aber keiner von diesen Veränderungen sind möglich, solange Sie zehn "Tipps" der Entwicklung in verschiedenen Branchen.
InformationsquelleAutor der Antwort
Ich weiß nicht, ob dies Ihr problem löst, aber was ich denke, Sie tun möchten, migrieren Sie den Inhalt der Datei in kleinere Dateien werden unabhängig voneinander (summiert).
Was mir auch gut bekommen ist, dass Sie über 10 verschiedene Versionen der software im Umlauf und Sie müssen Sie alle ohne irgendwelche Dinge.
Zunächst gibt es nur keine Weise, dass dies leicht und löst sich von selbst in ein paar Minuten brainstorming. Die Funktionen in Verbindung mit in der Datei sind alle wichtig, um Ihre Anwendung, und einfach schneiden Sie Sie von und Migration zu anderen Dateien nicht speichern Ihr problem.
Ich denke, dass Sie nur diese Optionen:
Nicht migriert werden und bleiben mit dem, was Sie haben. Vielleicht beenden Sie Ihre Arbeit und starten Sie die Arbeit auf ernsthafte software mit gutem design zusätzlich. Extreme programming ist nicht immer die beste Lösung, wenn Sie auf eine lange Zeit ein Projekt mit genug Geld, um zu überleben einen Absturz, oder zwei.
Erarbeiten ein layout, wie Sie lieben würden, Ihre Datei zu suchen, sobald es aufgeteilt sind. Erstellen Sie die erforderlichen Dateien und integrieren Sie in Ihre Anwendung. Die Funktionen umbenennen oder überlast, die Ihnen einen zusätzlichen parameter (vielleicht auch nur eine einfache boolean?).
Sobald Sie die Arbeit an Ihrem code ist, migrieren Sie die Funktionen, die Sie arbeiten müssen, um die neue Datei und ordnen Sie die Funktionsaufrufe von alten Funktionen zu den neuen Funktionen.
Sollten Sie noch Ihre Haupt-Datei auf diese Weise, und noch in der Lage zu sehen, die änderungen, die gemacht wurden, um es, einmal geht es um eine spezifische Funktion Sie genau wissen, Wann es ausgelagert und so weiter.
Versuchen, Sie zu überzeugen Ihre Mitarbeiter mit einige guten Kuchen, der workflow wird überbewertet und, dass Sie müssen neu schreiben einige Teile der Anwendung, um zu tun ernstes Geschäft.
InformationsquelleAutor der Antwort
Genau dieses problem behandelt in einem Kapitel aus dem Buch "Working effectively with Legacy Code" (http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052).
InformationsquelleAutor der Antwort
Ich glaube, Sie würden am besten ab, erstellen eine Reihe von Befehl Klassen, die anzeigen der API-Punkte der mainmodule.cpp.
Sobald Sie vorhanden sind, müssen Sie überarbeiten Sie den vorhandenen code-Basis den Zugriff auf diese API-Punkte über den command-Klassen, sobald das erledigt ist, sind Sie frei umgestalten jedem Befehl die Umsetzung in eine neue Klasse Struktur.
Natürlich mit einer einzigen Klasse von 11 KLOC code in es ist sehr wahrscheinlich gepaart und spröde, aber individuelle Erstellung von command-Klassen wird helfen, viel mehr als jeder andere proxy/Fassade Strategie.
Ich nicht neidisch auf die Aufgabe, aber mit der Zeit auf dieses problem wird nur noch schlimmer, wenn es nicht angegangen.
Update
Ich würde vorschlagen, dass der Befehl Muster besser ist als eine Fassade.
Pflegen/organisieren viele verschiedene Command-Klassen, die über ein (relativ) monolithische Fassade ist zu bevorzugen. Mapping einer einzelnen Fassade auf ein 11 KLOC-Datei wird wahrscheinlich müssen aufgebrochen werden in ein paar verschiedene Gruppen selbst.
Warum die Mühe zu versuchen, herauszufinden, diese Fassade Gruppen? Mit dem Befehl Muster werden Sie in der Lage zu gruppieren und zu organisieren, diese kleinen Klassen organisch, so haben Sie viel mehr Flexibilität.
Natürlich beide Optionen sind besser als die single-11 KLOC und wächst-Datei.
InformationsquelleAutor der Antwort
Einen wichtigen Rat: nicht zu verwechseln refactoring und bugfixes. Was Sie wollen ist eine Version des Programms, die identisch zu der vorherigen version, außer, dass der source code ist anders.
Eine Möglichkeit könnte sein, zu Beginn der Aufteilung des mindestens big-Funktion/Teil in seine eigene Datei, und dann entweder mit einem header (also drehen main.cpp in einer Liste von #include, das klingt ein code smell in sich selbst *ich bin kein C++ Guru, obwohl), aber zumindest ist es jetzt aufgeteilt in Dateien).
Dann könnten Sie versuchen, schalten Sie alle Wartungs-releases über den "neuen" main.cpp oder was auch immer Ihre Struktur. Wieder: Keine weiteren änderungen oder Bugfixes, da tracking-wer ist verwirrend wie die Hölle.
Andere Sache: so viel, Wie Sie vielleicht den Wunsch, was zu einem großen Durchgang an der Umgestaltung der ganzen Sache in einem gehen, Sie könnte mehr abzubeißen, als Sie kauen kann. Vielleicht wählen Sie einfach eine oder zwei "Teile", erhalten Sie in allen Versionen, dann fügen Sie etwas mehr Wert für Ihre Kunden (nach alle, Refactoring nicht den direkten Wert, so ist es eine Kosten, die gerechtfertigt ist) und dann wählen Sie noch ein oder zwei Teile.
Offensichtlich das erfordert eine gewisse Disziplin in der Mannschaft, um tatsächlich die split-Dateien und nicht nur neue Sachen, die main.cpp die ganze Zeit, aber wieder versuchen zu tun eine massive umgestalten, vielleicht nicht die beste Vorgehensweise.
InformationsquelleAutor der Antwort
Rofl, das erinnert mich an meinen alten job. Es scheint, dass, bevor ich dazukam, war alles in einer riesigen Datei (auch C++). Dann haben Sie es aufteilen (in völlig zufällige Punkte mit umfasst) in etwa drei (immer noch riesige Dateien). Die Qualität dieser software war, wie man erwarten könnte, schrecklich. Das Projekt beliefen sich auf über 40k LOC. (enthält fast keine Kommentare, aber VIEL doppelten code)
Am Ende habe ich eine komplette überarbeitung des Projekts. Ich begann, indem ich nochmal das Schlimmste, das Projekt von Grund auf neu. Natürlich hatte ich im Hinterkopf eine mögliche (kleine) - Schnittstelle zwischen dem neuen Teil und der rest. Dann habe ich legen Sie diesen Teil in dem alten Projekt. Ich wusste nicht, überarbeiten Sie den alten code zum erstellen der Schnittstelle notwendig, sondern nur ersetzt. Dann nahm ich machte kleine Schritte, überschreiben Sie den alten code.
Muss ich sagen, dass das alles nahm etwa ein halbes Jahr und es war keine Entwicklung von der alten code-Basis, die neben bugfixes während dieser Zeit.
edit:
Die Größe blieb bei etwa 40k LOC, sondern die neue Anwendung enthalten sind viele Funktionen-und damit vermutlich auch weniger bugs in der ersten version als die 8 Jahre alte software. Ein Grund für das umschreiben war auch, dass wir brauchten, die neuen features und führt Sie in den alten code war fast unmöglich.
Wurde die software für ein embedded system, eine label-Drucker.
Anderen Punkt, den ich hinzufügen sollte, ist, dass in der Theorie das Projekt wurde in C++. Aber es war nicht OO an alle, es hätte C. wurde Die neue version der Objekt-orientierten.
InformationsquelleAutor der Antwort
Also OK für die meisten Teil umschreiben API der Produktions-code ist eine schlechte Idee, wie ein start. Müssen zwei Dinge passieren.
Die Sie benötigen, um Ihr team zu entscheiden, zu tun ist, einen code-freeze auf aktuelle Produktions-version dieser Datei.
Beiden, Sie brauchen, um das Produktions-version und erstellen Sie einen Zweig für die Verwaltung der builds mit preprocessing Direktiven zum aufteilen der großen Datei. Die Spaltung der Zusammenstellung mit NUR Präprozessor-Direktiven (#ganzen IFDEFs, #include, #endifs) ist einfacher als Rekodierung der API. Es ist definitiv leichter für Ihre SLAs und den Laufenden support.
Hier konnte man einfach nur die cut-out-Funktionen, die sich auf ein bestimmtes subsystem innerhalb der Klasse und setzen Sie Sie in einer Datei sagen mainloop_foostuff.cpp und in mainloop.cpp an der richtigen Stelle.
ODER
Ein zeitaufwändiger, aber robuste Möglichkeit wäre der Aufbau eines internen Abhängigkeiten-Struktur mit Doppel-Dereferenzierung, wie die Dinge mit enthalten. Dies ermöglicht es Ihnen, split Dinge noch kümmern, co-Abhängigkeiten. Beachten Sie, dass dieser Ansatz erfordert die positions-Kodierung und daher sollte gekoppelt werden mit entsprechenden Kommentaren.
Dieser Ansatz würde beinhalten Komponenten, die man verwendet, basierend auf der Variante, die Sie kompilieren.
Die Grundstruktur ist, dass Sie Ihre mainclass.cpp wird eine neue Datei namens MainClassComponents.cpp nach einem block von Aussagen wie die folgenden:
Die primäre Struktur des MainClassComponents.cpp Datei wäre dort zu arbeiten, Abhängigkeiten innerhalb der sub-Komponenten wie:
Nun für jede Komponente, die Sie erstellen component_xx.cpp Datei.
Bin ich natürlich mit zahlen, aber Sie sollten etwas mehr logische basierend auf Ihrem code.
Verwendung von Präprozessor erlaubt das teilen von Dingen, ohne sich sorgen über API-änderungen, die ein Alptraum in der Produktion.
Einmal haben Sie Produktion angesiedelt, können Sie dann tatsächlich die Arbeit an einer Neugestaltung.
InformationsquelleAutor der Antwort
Gut, ich verstehe deinen Schmerz 🙂 ich habe seit ein paar solche Projekte auch, und es ist nicht schön. Es gibt keine einfache Antwort für dieses.
Einen Ansatz, der möglicherweise Arbeit für Sie ist, starten Sie das hinzufügen von sicheren Wachen in allen Funktionen, d.h. überprüfung der Argumente, pre/post-Bedingungen in Methoden, dann schließlich das hinzufügen von unit-tests alle in Ordnung zu erfassen, die die aktuellen Funktionen der Quellen. Sobald Sie diese haben, sind Sie besser ausgestattet, um re-Faktor-der code ist, da haben Sie behauptet und Fehler auftauchen, das Sie alarmiert, wenn Sie etwas vergessen haben.
Manchmal jedoch gibt es Zeiten, wenn die Umgestaltung kann nur bringen mehr Schmerz als nutzen. Dann kann es besser sein, nur lassen Sie das original-Projekt und in einem pseudo-Wartung Stand und von vorne zu beginnen und dann schrittweise hinzufügen der Funktionalität, die von der Bestie.
InformationsquelleAutor der Antwort
Sollten Sie nicht sein, die sich mit der Verringerung der Datei-Größe, sondern um die Reduzierung der Klassengröße. Es kommt auf fast das selbe, aber macht man sich das problem aus einem anderen Blickwinkel (@Brian Rasmussen suggeriertIhre Klasse zu haben scheint, viele Aufgaben).
InformationsquelleAutor der Antwort
Was Sie haben, ist ein klassisches Beispiel einer bekannten design antipattern genannt der blob. Nehmen Sie sich Zeit und Lesen Sie den Artikel, den ich Punkt hier, und vielleicht können Sie etwas finden, nützlich. Außerdem, wenn dieses Projekt so groß, wie er aussieht, sollten Sie einige design-um zu verhindern, dass immer in code, den Sie nicht kontrollieren können.
InformationsquelleAutor der Antwort
Dies ist nicht eine Antwort auf das große problem, aber eine theoretische Lösung zu einem bestimmten Stück:
Herausfinden, wo Sie teilen möchten, auf die große Datei in Teildateien. Kommentare zu einigen speziellen format an jedem dieser Punkte.
Schreiben Sie ein Recht triviales Skript, das brechen wird die Datei auseinander in Teildateien auf diese Punkte. (Vielleicht ist der spezielle Kommentare eingebettete Dateinamen, dass das Skript verwenden können, als Anweisungen, um es zu teilen.) Es sollten erhalten Sie die Kommentare als Teil der Aufteilung.
Führen Sie das Skript. Löschen Sie die ursprüngliche Datei.
Wenn Sie brauchen, um merge von einem branch, zunächst erstellen Sie die große Datei, die durch verketten die Stücke wieder zusammen, führen Sie den Seriendruck, und dann re-split.
Auch, wenn Sie wollen, erhalten Sie die SCC-Datei Geschichte, ich erwarte, dass der beste Weg, dies zu tun, ist zu sagen, Ihre source-control-system, das das einzelne Stück-Dateien sind Kopien der Originale. Dann wird es bewahren die Geschichte von den Abschnitten, die gehalten wurden, die in dieser Datei, obwohl es natürlich auch aufnehmen, dass große Teile wurden "gelöscht".
InformationsquelleAutor der Antwort
Einen Weg, um es zu teilen, ohne zu viel Gefahr würde zu nehmen, einen historischen Blick auf alle änderungen. Gibt es bestimmte Funktionen, die stabiler sind als andere? Hot-spots ändern, wenn du willst.
Wenn eine Zeile geändert wurde, in ein paar Jahren kann man wahrscheinlich verschieben Sie es an eine andere Datei, ohne zu viel Sorge. Ich würde nehmen Sie einen Blick an der Quelle Anmerkungen der letzten revision, die berührt einer gegebenen Linie und sehen, ob es irgendwelche Funktionen, die Sie herausziehen konnte.
InformationsquelleAutor der Antwort
Wow, das klingt Super. Ich denke, erklären Sie Ihrem Chef, dass Sie viel Zeit benötigen, umgestalten, das Tier ist einen Versuch Wert. Wenn er nicht einverstanden ist der Ausstieg eine option.
Sowieso, was ich Vorschlage, ist im Grunde werfen alle die Umsetzung und Umgruppierung in die neue Module, nennen wir diese "global services". Die "Haupt-Modul" würde nur bei uns auf die Dienste und ALLE neuen code, den Sie schreiben, verwenden Sie statt dem "Haupt-Modul". Dies sollte machbar sein, in einer angemessenen Höhe der Zeit (weil es meistens kopieren und einfügen), Sie brechen nicht vorhandenen code, und Sie können es tun, eine Wartungs-version, zu einer Zeit. Und wenn Sie noch etwas Zeit bleibt, können Sie es ausgeben Umgestaltung aller alten Module je auch die Globale services.
InformationsquelleAutor der Antwort
Meine Sympathien - in meinem vorherigen job stieß ich auf eine ähnliche situation mit einer Datei, die mehrere Male größer als die, die Sie zu bewältigen haben. Lösung war:
Den Klassen, die Sie erstellen in Schritt 3. Iterationen werden wahrscheinlich wachsen, absorbieren mehr code, um Ihre neu-Funktion "löschen".
Ich könnte auch hinzufügen:
0: kaufen Michael Feathers' Buch auf die Arbeit mit legacy-code
Leider ist diese Art der Arbeit ist nur allzu üblich, aber meine Erfahrung ist, dass es einen großen Wert in der Lage zu machen, arbeiten, aber schrecklichen code inkrementell weniger schrecklich, während Sie arbeiten.
InformationsquelleAutor der Antwort
Möglichkeiten zu schreiben, die gesamte Anwendung in einem sinnvoller Weise. Vielleicht umschreiben einen kleinen Teil davon als Prototyp, um zu sehen, ob Ihre Idee machbar ist.
Wenn Sie identifiziert haben, eine praktikable Lösung, überarbeiten Sie den Antrag entsprechend.
Wenn alle versuche, zu produzieren, eine mehr rationale Architektur scheitern, dann mindestens Sie wissen, die Lösung ist wahrscheinlich in die Neudefinition der Funktionalität des Programms.
InformationsquelleAutor der Antwort
Meiner 0.05 Cent:
Re-design das ganze Durcheinander, es teilen sich in die Subsysteme unter Berücksichtigung der technischen und geschäftlichen Anforderungen (=viele parallel Wartung tracks mit potenziell unterschiedlichen Codebasis für jeden, offensichtlich gibt es eine Notwendigkeit für eine hohe Modifizierbarkeit, etc.).
Wenn die Aufteilung in Subsysteme, Analyse der Orte, an denen die meisten geändert und trennen diese von der unveränderlichen Teile. Dies sollte zeigen Sie die Probleme-spots. Trennen Sie die meisten Teile austauschen, um eigene Module (z.B. dll) in einer solchen Weise, dass die Modul-API kann intakt gehalten und Sie brauchen nicht zu brechen BC die ganze Zeit. Auf diese Weise können Sie die Bereitstellung verschiedener Versionen des Moduls für die verschiedenen Wartungs-äste, wenn nötig, während der Kern unverändert.
Die Neugestaltung werden wahrscheinlich brauchen, um ein separates Projekt, versuchen, es zu tun, um ein sich bewegendes Ziel wird nicht funktionieren.
Als für den source-code der Geschichte, meine Meinung: vergiss es für den neuen code. Aber halten Sie die Geschichte irgendwo so können Sie es überprüfen, wenn nötig. Ich Wette, Sie werden es nicht brauchen, dass es viel nach dem Beginn.
Werden Sie wahrscheinlich benötigen, um das management-buy-in für dieses Projekt. Sie können argumentieren vielleicht mit schneller Entwicklungszeit, weniger bugs, leichter Pflege und insgesamt weniger chaos. Etwas entlang der Linien von "Proaktiv aktivieren Sie die Zukunft-Sicherheit und Wartung Lebensfähigkeit unserer kritischen software-assets" 🙂
Dies ist, wie ich beginnen, um das problem anzugehen zumindest.
InformationsquelleAutor der Antwort
Starten Sie durch hinzufügen von Kommentaren. Mit Verweis auf, wo die Funktionen aufgerufen werden und, wenn Sie kann Dinge bewegen. Dies kann etwas bewegen. Sie wirklich brauchen, um zu beurteilen, wie brüchig die code-Basis. Dann bewegen Sie die gemeinsamen bits der Funktionalität zusammen. Kleine änderungen zu einem Zeitpunkt.
InformationsquelleAutor der Antwort
Andere Buch für Sie interessant/hilfreich ist Refactoring.
InformationsquelleAutor der Antwort
Etwas, was ich nützlich finde (und ich Tue es jetzt-wenn auch nicht auf die Waage, die Sie Gesicht), extrahieren von Methoden als Klassen (method object-refactoring). Die Methoden unterscheiden sich in Ihren verschiedenen Versionen verschiedene Klassen, die injiziert werden kann, in einer gemeinsamen Basis, um die verschiedenen Verhalten, die Sie benötigen.
InformationsquelleAutor der Antwort
Fand ich diesen Satz ist der interessanteste Teil von deinem post:
> Die Datei wird verwendet und aktiv verändert in mehrere (> 10) maintenance-Versionen unserer Produkte und so ist es wirklich schwer umgestalten, es
Zuerst, ich würde empfehlen, dass Sie verwenden ein source-control-system für die Entwicklung dieser 10 + Wartung-Versionen, unterstützt die Verzweigung.
Zweiten, ich würde zehn Niederlassungen (eine für jedes Ihrer IH-Versionen).
Ich kann fühlen Sie sich krümmenden schon! Aber entweder Ihre Quelle die Kontrolle nicht funktioniert für Ihre situation wegen fehlender features, oder es ist nicht richtig eingesetzt.
Nun zu den Niederlassungen Sie arbeiten, auf - gestalten Sie es, wie Sie sehen, passen, in dem sicheren wissen, dass Sie nicht stören die anderen neun Niederlassungen, von Ihrem Produkt.
Wäre ich ein bisschen besorgt, dass Sie so viel in Ihrer main () - Funktion.
Alle Projekte, die ich Schreibe, würde ich mit main() nur dann durchführen Initialisierung von core-Objekten - wie eine simulation oder ein application-Objekt - diese Klassen ist, wo die eigentliche Arbeit gehen sollte.
Ich würde auch die Initialisierung der Anwendung-logging-Objekt in der main verwenden Sie Global im gesamten Programm.
Schließlich, in der ich auch hinzufügen, Lecksuche code in Präprozessor-Blöcke, die sicherstellen, dass es nur aktiviert DEBUG-builds. Dies ist alles, was ich möchte hinzufügen zu main(). Main() sollte kurz sein!
Ihnen sagen, dass
> Die Datei enthält im Grunde die "main-Klasse" (Haupt-interne Arbeitsaufteilung und-Koordination) unser Programm
Es klingt wie diese beiden Aufgaben können aufgeteilt werden in zwei separate Objekte - ein Koordinator und eine Arbeit dispatcher.
Wenn Sie teilen diese, können Sie mess up Ihre "SCC-workflow", aber es klingt wie die Einhaltung streng zu Ihrem SCC-workflow verursacht die software-Wartung Probleme. Graben Sie es jetzt und schau nicht zurück, denn sobald Sie es zu beheben, werden Sie beginnen zu schlafen einfach.
Wenn Sie nicht in der Lage eine Entscheidung zu treffen, kämpfen zahn und Nagel mit Ihren Vorgesetzten für Ihre Anwendung refaktorisiert werden - und schlecht von den Klängen davon! Nehmen Sie nicht Nein für eine Antwort!
InformationsquelleAutor der Antwort
Wie du es beschrieben hast, ist der wichtigste Punkt die diff-pre-split vs post-split, verschmelzen Bugfixes etc.. Werkzeug um ihn herum. Es dauert nicht lange um fest ein Skript in Perl, Ruby, etc. rippen aus die meisten, das Geräusch von diff-pre-split gegen eine Verkettung von post-split. Tun, was am einfachsten in der Handhabung Lärm:
Man könnte sogar es so machen, wenn es eine Check-in, die Verkettung läuft, und Sie haben etwas vorbereitet, um diff gegen die single-Datei-Versionen.
InformationsquelleAutor der Antwort
InformationsquelleAutor der Antwort
"Die Datei enthält im Grunde die "main-Klasse" (Haupt-interne Arbeitsaufteilung und-Koordination) unseres Programms, also jedes mal, wenn eine Funktion Hinzugefügt wird, es wirkt sich auch auf diese Datei und jedes mal, wenn es wächst."
Wenn das große WECHSELN (was ich denke, es ist), wird die Haupt-Wartung problem, könnte man umgestalten, es zu verwenden-Wörterbuch und das Command-Muster und entfernen Sie alle schalten die Logik aus dem vorhandenen code für den loader, füllt die Karte, d.h.:
InformationsquelleAutor der Antwort
Ich denke, der einfachste Weg, um die Geschichte der Quelle beim teilen einer Datei würde so etwas wie dieses:
InformationsquelleAutor der Antwort
Ich denke, was ich tun würde in dieser situation ist bit die Kugel und:
Tracking-alt änderungen an der Datei, ist einfach gelöst, die von Ihrem ersten check-in Kommentar sagen so etwas wie "split aus mainmodule.cpp". Wenn Sie brauchen, um zurück zu gehen, um etwas neueres, die meisten Menschen werden sich erinnern, das zu ändern, wenn es 2 Jahre von jetzt, wird der Kommentar wird Ihnen sagen, wo Sie zu suchen. Natürlich, wie wertvoll wird es sein, zurück zu gehen mehr als 2 Jahren zu schauen, wer änderte den code und warum?
InformationsquelleAutor der Antwort