'Guard Clause'에 해당하는 글 1건

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
예전에 쓴 들여쓰기 최소화라는 글에 많은 분들이 다양한 의견을 주셨습니다. 주신 의견들을 유심히 읽다 보니 해당 글에 대해 깊히 생각하는 기회를 가질 수 있었고, 자연스레 아래와 같은 세 가지 논제를 머리속에 떠올렸습니다.

첫 번째, 들여쓰기 최소화가 정말 가치있는 것인가? 만약 가치 있다면 논리적인 근거를 제시할 수 있는가?
두 번째, 진입점과 종료점을 각 하나씩만 유지해야 하는 것은 의미 있는 일인가?
세 번째, 긍정 조건과 부정 조건 중 어떤 것이 더 이해하기 좋은가? 만약 상황에 따라 적절히 사용해야 한다면 긍정 조건과 부정 조건을 선택하기 위해 사용하는 기준을 도출할 수 있을까?

최근 읽고 있는 켄트벡의 Implementation Patterns에는 위 논제에 대한 답변을 얻는 데 도움이 될만한 내용이 많이 담겨있었습니다. 저는 그동안의 저의 생각과, 최근 해당 책에서 얻은 지식들을 이용하여 위 세 가지 논제 중 첫번째 논제에 대한 저의 생각을 얘기해보고자 합니다.(참고로 Implementation Patterns의 Guard Clause와는 조금 다른 시점의 글입니다. 이 글은 이전 글에서 얘기했던 들여쓰기 최소화 자체에 집중한 글임을 밝힙니다)

들여쓰기를 한다는 것은 현재 들여쓰기 되고 있는 단락 위에 진입 조건이 존재한다는 것을 의미합니다. 조건문, 반복문, 메서드 등이 이러한 진입 조건이 될 수 있습니다.

만약 어떤 사람이 조건문에 속해 있는 하위 단락을 읽는다면, 하위 단락이 어떤 경우에 실행되는지를 '전제'로 인식하고 있어야 합니다. 그런데 이러한 전제가 많아지고 단락이 깊어지면 문제가 생깁니다. 아래 예제 코드는 이러한 문제를 잘 드러내고 있습니다.
void compute() {
    Server server = getServer();
    if (server != null) {
        Client client = server.getClient();
        if (client != null) {
            Request current = client.getRequest();
            if (current != null) {
                 processRequest(current);
            }
        }
    }
}

void compute() {
    Server server = getServer();
   if (server == null)
        return;
    Client client = server.getClient();
   if (client == null)
       return;
    Request current = client.getRequest();
   if (current == null)
       return;
   processRequest(current);
}

Implementation Patterns P71에서 인용

첫 번째 코드를 보면 읽는 사람이 전제로 유지해야 할 조건이 많다는 것을 볼 수 있습니다. 'server가 null이 아니고, client도 null이 아니며, current도 null이 아니면' 이라는 전제 조건이 processRequest에 이르기 전까지 단계적으로 머리속에 유지 되어야 합니다. 켄트백은 이러한 형태의 전제 조건들에 대해 '집중해야 할 것에 집중하지 못하게 방해하는 것들'이라고 얘기합니다. 실제로 위와 같은 코드는 집중해야 할 것에 집중하기 어렵게 하며 만약 else까지 존재한다면 더욱더 어려운 상황이 만들어집니다. 결국 코드를 이해하기가 어려워지는 것입니다.

반면 두 번째 코드는 동일한 일을 하면서도 보다 이해하기 쉬운 코드입니다. 코드에 윗 부분에 조건에 안 맞으면 바로 종료하는 코드가 있음을 볼 수 있습니다. processRequest에 이르렀을 때 첫번째 코드와는 달리 머리속에 전제 조건으로 유지해야 할 것이 없어집니다. 왜냐하면 'server가 null이면 종료','client가 null이면 종료','current가 null이면 종료' 이렇게 세 가지 조건 단락이 독립적으로 분리되어 이미 실행되었기에 더 이상 앞에 코드에 대해서 신경쓰지 않아도 되기 때문입니다.

만약 사람의 두뇌가 스택(Stack) 형태의 기억을 잘 할 수 있다면 첫번째 코드도 큰 문제는 아닐 것입니다. 하지만 저의 경우 스택 형태로 무엇인가를 기억하는 것은 쉽지 않았습니다. 따라서 몇단계의 전제 조건을 가지는 코드를 보면 한 세번째 전제 조건을 보는 중, 첫번째로 보았던 전제 조건을 잊어버려 허둥되곤 했습니다. 사실 이 문제는 저만의 문제는 아닌 것 같습니다. ANT의 depends 기능을 지나치게 활용하여 만들어진 빌드 스크립트를 분석하는 일은 저뿐만 아니라 다른 사람들도 무척 어려워 하더군요.

저는 첫 번째 논제인 '들여쓰기 최소화가 정말 가치있는 것인가?'라는 부분에 대해 '들여쓰기 최소화는 충분한 가치를 가지고 있다'고 주장하고 싶습니다. 왜냐하면 많은 경우 들여쓰기 최소화를 통해 더 이해하기 쉬운 코드를 만들 수 있기 때문입니다.

2008/01/15 ~ 2008/01/17

WRITTEN BY
차민창
르세상스 엔지니어가 사회를 이끌어나가는 상상을 하며!

,