Ich habe derzeit das Pech, an Somebody Elses C# -Code zu arbeiten, was mich wirklich umgehauen hat. Ich habe keine Ahnung, wie die Person vor mir diesen Code jemals gepflegt hat, da ihre verschiedenen Pathologien die IDE, den Compiler, die Laufzeitumgebung abgestürzt sind ...Aufräumen pathologisch verschachtelt "if {} else {if {} else {if {...}}}"
Das Problem, mit dem ich heute konfrontiert bin, beinhaltet eine 15-Megabyte-Quelldatei weist einen wahrhaft unglaublichen Grad an pathologischer Verschachtelung auf. Code wie:
if(var == 0) {
// do stuff
}
else {
if(var == 1) {
// do stuff
}
else {
if(var == 2) {
// do stuff, identical word for word to the `var == 1` case
}
else {
// etc.
}
}
}
Dies ist eine fragwürdige Stilwahl zu den besten Zeiten. Dies verbindet sich jedoch mit einer anderen Pathologie des Codes: einige dieser Blöcke sind fast tausend Ebenen tief. (Das tiefste, was ich zu messen versuchte, war weit über 700.) Ich hoffe aufrichtig, dass die Person vor mir, als eine ihrer letzten Handlungen, bevor sie gewaltsam von diesem Kodex getrennt wurde, ein Styling-Tool führte, das zu dem Gräuel vor mir führte. Ich kann mir nicht vorstellen, dass sie diesen Code möglicherweise so geschrieben haben könnten, wie er jetzt ist, zumal jede dritte oder vierte Bearbeitung des Codes die IDE stürzt. (Und manchmal löscht meine Kopie der Quelldatei, als Bonus.)
Ich schrieb ein einfaches Regex-basiertes Tool, um zu versuchen, die einfacheren Fälle zu verdichten, aber es scheint zu halbieren und dann diesen bestimmten Code zu verfälschen. (Ich bin nicht sicher, ob es scheitert, weil dieser Code von Zeit zu Zeit auch Präprozessor-Bedingungen verwendet, oder weil das längste der Matches fast 10 MB lang ist und Lua's regulärer Ausdruck-Matcher einfach nicht zurechtkommt.) Ich hoffe, dass es da ist ein weit verbreitetes Werkzeug oder eine Technik, die dieses Problem umkehren kann. Ich musste bereits Astyle verwenden, um einige andere stilistische "Probleme", die der Code hatte, aufzuräumen. Die --remove-brackets
Option für astyle fast macht, was ich will, aber erfordert, dass die geklammerte Anweisung eine einzelne Aussage in einer einzigen Zeile sein, die hier sehr nicht der Fall ist ... (Und nur um meine "t" s zu überqueren, ich überprüfte, astyle nicht dieses besondere Problem erstellen)
Edit: Deeper Untersuchung des Problems Code zeigt Dinge wie diese:
#if OneThing
int num2296 = otherThing();
#endif
#if AnotherThing
int num44 = otherThing()
int num45 = 0;
#endif
int num72 = 0;
#if OneThing
int num45 = 0; // note: multiple equivalent declarations of num45
#endif
#if OneThing
for(int num2297 = 0; num2297 < num2296; ++num2297) {
num45 = doSomething(num2297);
#endif
#if AnotherThing
for(int num43 = 0; num43 < num44; ++num43) {
num45 = doSomething(num43);
#endif
if(somethingElse(num45)) {
++num72;
}
} // note: only one closing brace for the two protected by #ifs
Zwei Versionen dieses Codes werden für verschiedene Zwecke zusammengestellt, eines mit OneThing. definiert und eins mit AnotherThing definiert. Die meisten Unterschiede zwischen den beiden sind jedoch nur Variablennamen, die logisch identisch sind. (Most, not all.)
Fälle wie die Klammer am Ende des obigen Schnipsel erklärt, warum mein einfaches Werkzeug brach. Das sieht auch mehr und mehr nach Arbeitsplatzsicherheit aus und weniger nach unschuldiger Inkompetenz. (Wenn der Code einmal an einem Punkt war, wo ein Variablenname wie num2276
würde durch einen Decompiler erzeugt wird, ist es nicht derzeit an diesem Punkt.)
Leider bedeutet dies ein automatisiertes Tool wird wahrscheinlich nicht schneiden allein. Ich muss nur noch durchgehen und langsam den Schaden beseitigen, den der letzte Programmierer angerichtet hat. Ich überlasse diese Frage hier auf die Chance, es gibt ein wunderbares Werkzeug, das, ich weiß nicht, kann beide Versionen in SSA konvertieren und ihre logischen Äquivalenzen identifizieren und reduzieren und dann zurück konvertieren ...
Switch-Fall kann eine Lösung oder [Kette der Verantwortung] sein (https://en.m.wikipedia.org/wiki/Chain-of-responsibility_pattern) –
Scheint eine 'switch' Anweisung wird viel viel besser für den Code sein in der Probe zur Verfügung gestellt. Übrigens: gute Frage. –
Ich würde wahrscheinlich nähern, indem Sie Blöcke zu Methoden, tiefer und tiefer zu extrahieren. Dieses Video gibt eine Vorstellung davon, was ich mit [Praktisches Refactoring] meine (https://youtu.be/aWiwDdx_rdo?t=3235) (nicht mein Video). Ich habe mich mit einem relevanten Zeitstempel verbunden, aber es lohnt sich, das ganze Video anzuschauen. Es gibt einen Rundgang durch Refactoring einiger ziemlich horrenden Code, aber Ihre könnte es einfach schlagen. – Tone