The Art of readable code

in #kr-dev7 years ago

국내에서는 "읽기 좋은 코드가 좋은 코드다"라는 제목으로 번역된 책을 소개합니다.
로버트 마틴(밥 아저씨)가 지은 클린 코드 보다 유명한 책은 아닙니다만, 코드의 기본기를 다지는데 도움을 줄수 있는 책이라 생각됩니다.

이 책을 보다가 당황스럽지만 재밌는 구절이 있어서 소개해 봅니다.
Part II Simplifying Loops and Logic 에 있는 구절입니다.

if (user_result == SUCCESS) {
    if (permission_result != SUCCESS) {
        reply.WriteErrors("error reading permissions");
        reply.Done();
        return;
    }
    reply.WriteErrors("");
} else {
    reply.WriteErrors(user_result);
}
reply.Done();



If 문의 중첩에 대해서 이야기하고 있습니다. 이 코드는 원래 아래 코드에서 시작되었을 것입니다.
웹 서비스로 사용자 인증을 하다 보면 자주 만나게 되는 코드입니다. user_result 는 아마도 사용자 인증이 성공되었는지를 가지고 있는 듯 합니다. 성공했으면, 에러를 뿌리지 않고, 그렇지 않다면 에러를 뿌린다. 그리고 reply 를 끝낸다. 이정도로 해석되네요.

if (user_result == SUCCESS) {
    reply.WriteErrors("");
} else {
    reply.WriteErrors(user_result);
}
reply.Done();



이후에 사용자 이용권한 관련 내용이 추가되었을 것입니다. (permission_result)

아 user_result 가 성공한 경우에만 permission_result 가 의미가 있군...
그렇다면 if 문의 전반부에 이 코드를 넣으면 되겠군...

이렇게 생각하는 것은 너무나 당연한 일이라 바로 이를 코딩합니다.
그 결과 중첩된(Nested) IF 문이 탄생하였습니다.

이 책에서는 다음과 같이 코드를 간략화 하였습니다. 간략화라는 뜻은 Nested 를 없앴다는 뜻입니다.

if (user_result != SUCCESS) {
    reply.WriteErrors(user_result);
    reply.Done();
    return;
}
if (permission_result != SUCCESS) {
    reply.WriteErrors(permission_result);
    reply.Done();
    return;
}
reply.WriteErrors("");
reply.Done();



이전보다 나은 코드가 되었을까요?

  • 로그인이 성공적이지 않으면, 에러를 출력하고 끝
  • 이후에는 무조건 로그인 성공인 경우만 들어오므로 이제 권한을 확인해서 권한이 성공적이지 않으면 에러를 출력하고 끝
  • 이제는 로그인도 성공, 권한도 성공

이러한 의식의 흐름이 따라오게 되는 읽기 좋은 코드가 되었네요.

이 책에서는 당황스럽게도 이렇게 바꾸는 방법에 대해서 설명하고 있습니다.

KEY IDEA
Look at your code from a fresh perspective when you’re making changes. Step back and look at it as a whole.
코드를 바꾸는 경우 새로운 관점에서 바라보라, 뒤로 물러서서 전체를 바라보라.

예전에도 이런 코드에 대한 개선(리팩토링)을 설명한적이 있었는데, 그 당시에는

if (condition) A and B 가 있으면 A B 를 바꾸면 좋을지 보고
Early return on exception 방식을 사용해라

이런 구차한 설명을 했던 것 같습니다. 답을 보고 과정을 설명하는 것이라 구차하다고 한 것입니다.

이 책에서는 한마디 테크닉(?)도 없이 그저 "뒤에서 전체를 바라보라" 라는 말로 방법을 설명하고 있었고, 이 당황스러운 말에 큰 감동을 받아 지금도 모니터를 멀찌감치 두고 코딩을 하고 있습니다.

코드는 잘 짜야하고 잘 짜지 않은 코드는 1주일 내에 쓰레기가 될 확률이 높습니다.
오늘도 이러한 일이 발생하였고, 예전 생각이나서 글을 한번 올려봅니다.

Sort:  

유지보수를 하다보면 다른 사람의 소스를 봐야 할 때도 많고 반대로 다른 사람이 제 소스를 봐야할때가 많습니다.
때문에 유지보수 입장에서는 장애 발생시 즉각 대처할 수 있도록 가독성이 높은 소스가 잘 짜여진 소스라는게 저의 지론입니다.
그래서 예전처럼 라인을 줄이기 위한 노력보다는 한 블럭에서 한 가지 일만 하도록 하는 것이 좋더군요.
그런 면에서 kdj님이 소개한 방법은 아주 좋은 방법인 듯 합니다. ^^

근데 javascript로 코드를 볼 일이 많은 요즘 callback 함수를 실행시키기 위한 루틴에서는 저런 코딩 방식이 되지 않아서 고민입니다.

자바스크립트에서 async 를 sync 하는 것 때문에, 귀찮고 짜증납니다. ^^

지당하신 말씀입니다 ^^

Async/Await bless you!!!

코드를 보다가 전체로 멀리 봐야한다는 말씀에 공감하고 갑니다.
Flow 차트를 써도 실제 구현 들어가면 뭔가 뱅뱅도는 느낌? 그런 적이 있었거든요.
생각해보니 그럴 때마다 차를 마시거나 운전하고 있다보면 아! 그렇지? 이러면 되겠다. 라는 생각이 들곤 했어요. 그게 본문에 써주신 전체를 바라보는 것이었군요.
좋은 글 올려주셔서 정말 감사합니다. 좋은 하루 되세요.
(미약하지만 저도 보팅하고 가요 ^^)