Betrachten Sie den folgenden Code:
public void doSomething(int input)
{
while(true)
{
TransformInSomeWay(input);
if(ProcessingComplete(input))
break;
DoSomethingElseTo(input);
}
}
Angenommen, dieser Prozess beinhaltet eine endliche, aber eingabeabhängige Anzahl von Schritten. Die Schleife ist so konzipiert, dass sie aufgrund des Algorithmus von selbst endet und nicht auf unbestimmte Zeit ausgeführt wird (bis sie durch ein externes Ereignis abgebrochen wird). Da sich der Test, ob die Schleife enden soll, in der Mitte einer logischen Reihe von Schritten befindet, überprüft die while-Schleife selbst derzeit nichts Sinnvolles. Die Prüfung wird stattdessen an der "richtigen" Stelle innerhalb des konzeptionellen Algorithmus durchgeführt.
Mir wurde gesagt, dass dies ein fehlerhafter Code ist, da er aufgrund der Endbedingung, die von der Schleifenstruktur nicht überprüft wird, fehleranfälliger ist. Es ist schwieriger herauszufinden, wie Sie die Schleife verlassen würden, und es kann zu Fehlern kommen, da die Unterbrechungsbedingung möglicherweise umgangen oder bei zukünftigen Änderungen versehentlich weggelassen wird.
Der Code könnte nun folgendermaßen aufgebaut sein:
public void doSomething(int input)
{
TransformInSomeWay(input);
while(!ProcessingComplete(input))
{
DoSomethingElseTo(input);
TransformInSomeWay(input);
}
}
Dies dupliziert jedoch einen Aufruf einer Methode im Code, wodurch DRY verletzt wird. Wenn TransformInSomeWay
sie später durch eine andere Methode ersetzt würden, müssten beide Aufrufe gefunden und geändert werden (und die Tatsache, dass es zwei gibt, ist in einem komplexeren Codeteil möglicherweise weniger offensichtlich).
Sie könnten es auch so schreiben:
public void doSomething(int input)
{
var complete = false;
while(!complete)
{
TransformInSomeWay(input);
complete = ProcessingComplete(input);
if(!complete)
{
DoSomethingElseTo(input);
}
}
}
... aber Sie haben jetzt eine Variable, deren einziger Zweck darin besteht, die Bedingungsüberprüfung auf die Schleifenstruktur zu verschieben, und die außerdem mehrmals überprüft werden muss, um dasselbe Verhalten wie die ursprüngliche Logik zu erzielen.
Ich für meinen Teil sage, dass angesichts des Algorithmus, den dieser Code in der realen Welt implementiert, der Originalcode am besten lesbar ist. Wenn Sie es selbst durchgehen würden, würden Sie so darüber nachdenken, und daher wäre es für Leute, die mit dem Algorithmus vertraut sind, intuitiv.
Also, was ist "besser"? Ist es besser, die Zustandsüberprüfung der while-Schleife zu übertragen, indem die Logik um die Schleife herum strukturiert wird? Oder ist es besser, die Logik auf "natürliche" Weise zu strukturieren, wie dies durch Anforderungen oder eine konzeptionelle Beschreibung des Algorithmus angezeigt wird, obwohl dies bedeuten kann, dass die eingebauten Funktionen der Schleife umgangen werden?
do ... until
Konstrukt ist auch für diese Art von Schleifen nützlich, da sie nicht "grundiert" werden müssen.