여기서 물러서겠습니다 코드의 까다로운 세부 사항에 집중하고 있지만 더 큰 그림이 누락되었습니다. 예제 루프 중 하나를 살펴 보겠습니다.
int offset = 0;
while(true)
{
Record r = Read(offset);
if(r == null)
{
break;
}
// do work
offset++;
}
이 코드 의 의미 는 무엇입니까 ? 의미는 "파일의 각 레코드에 일부 작업을 수행합니다"입니다. 그러나 그것은 코드의 모습 이 아닙니다 . 코드는 "오프셋을 유지합니다. 파일을 엽니 다. 종료 조건없이 루프를 입력하십시오. 레코드를 읽습니다. null을 테스트하십시오."와 같은 코드입니다. 우리가 일하기 전에 모든 것! " 이 코드의 모양이 의미와 일치하도록하려면 어떻게 해야 합니까? "입니다.이 코드는 다음과 같아야합니다.
foreach(Record record in RecordsFromFile())
DoWork(record);
이제 코드는 의도 한대로 읽습니다. 의미론에서 메커니즘을 분리하십시오 . 원래 코드에서는 매커니즘 (루프의 세부 사항)과 시맨틱 (semantics)을 각 레코드에 대해 수행 한 작업을 혼합합니다.
이제 구현해야합니다 RecordsFromFile()
. 그것을 구현하는 가장 좋은 방법은 무엇입니까? 무슨 상관이야? 그것은 누군가가 볼 코드가 아닙니다. 기본 메커니즘 코드이며 10 줄 길이입니다. 그러나 원하는대로 작성하십시오. 이건 어때?
public IEnumerable<Record> RecordsFromFile()
{
int offset = 0;
while(true)
{
Record record = Read(offset);
if (record == null) yield break;
yield return record;
offset += 1;
}
}
이제 우리는 느리게 계산 된 레코드 시퀀스를 조작하여 모든 종류의 시나리오가 가능해졌습니다.
foreach(Record record in RecordsFromFile().Take(10))
DoWork(record);
foreach(Record record in RecordsFromFile().OrderBy(r=>r.LastName))
DoWork(record);
foreach(Record record in RecordsFromFile().Where(r=>r.City == "London")
DoWork(record);
등등.
루프를 작성할 때마다 "이 루프를 메커니즘이나 코드의 의미처럼 읽습니까?" 대답이 "메커니즘과 같다"면 해당 메카니즘을 자체 메서드로 옮기고 의미를 더 잘 보이도록 코드를 작성하십시오.