다음 코드를 고려하십시오.
public void doSomething(int input)
{
while(true)
{
TransformInSomeWay(input);
if(ProcessingComplete(input))
break;
DoSomethingElseTo(input);
}
}
이 프로세스에는 유한하지만 입력 종속적 인 단계가 포함되어 있다고 가정합니다. 루프는 알고리즘의 결과로 자체적으로 종료되도록 설계되었으며 무한정 실행되도록 설계되지 않았습니다 (외부 이벤트에 의해 취소 될 때까지). 루프가 끝나야하는지 확인하는 테스트가 논리적 단계 집합의 중간에 있기 때문에 while 루프 자체는 현재 의미있는 것을 확인하지 않습니다. 대신 검사는 개념적 알고리즘 내의 "적절한"위치에서 수행됩니다.
루프 구조로 확인되지 않는 종료 조건으로 인해 버그가 발생하기 쉽기 때문에 이것이 나쁜 코드라고 들었습니다. 루프를 종료하는 방법을 파악하기가 더 어려우며, 향후 변경으로 인해 실수로 우회되거나 생략 될 수 있으므로 버그가 발생할 수 있습니다.
이제 코드는 다음과 같이 구성 될 수 있습니다.
public void doSomething(int input)
{
TransformInSomeWay(input);
while(!ProcessingComplete(input))
{
DoSomethingElseTo(input);
TransformInSomeWay(input);
}
}
그러나 이것은 코드에서 메소드에 대한 호출을 복제하여 DRY를 위반합니다. TransformInSomeWay
나중에 다른 방법으로 대체 된 경우 두 호출을 모두 찾아서 변경해야합니다 (더 복잡한 코드에서는 두 가지가 있다는 사실이 덜 분명 할 수 있음).
다음과 같이 작성할 수도 있습니다.
public void doSomething(int input)
{
var complete = false;
while(!complete)
{
TransformInSomeWay(input);
complete = ProcessingComplete(input);
if(!complete)
{
DoSomethingElseTo(input);
}
}
}
...하지만 이제 조건 확인을 루프 구조로 전환하는 유일한 목적을 가진 변수가 있으며 원래 논리와 동일한 동작을 제공하기 위해 여러 번 확인해야합니다.
필자는이 코드가 실제 환경에서 구현하는 알고리즘을 고려할 때 원본 코드가 가장 읽기 쉽다고 말합니다. 당신이 그것을 직접 겪고 있다면, 이것은 당신이 그것에 대해 생각하는 방식이므로 알고리즘에 익숙한 사람들에게는 직관적입니다.
그렇다면 "더 나은"것은 무엇입니까? 루프 주변의 논리를 구성하여 while 루프에 조건 확인의 책임을 부여하는 것이 더 낫습니까? 또는 루프의 내장 기능을 우회 할 수 있음에도 불구하고 요구 사항 또는 알고리즘에 대한 개념적 설명으로 표시된대로 "자연적인"방식으로 논리를 구성하는 것이 더 낫습니까?
do ... until
구조는 "프라이밍"할 필요가 없기 때문에 이러한 종류의 루프에도 유용합니다.