읽기 좋은 코드가 좋은 코드다(더스팀 보즈웰, 트레버 파우커 지음, 임백준 옮김) 를 읽고 

자주 참고하면서 습관화하려는 부분을 정리해 놓은 것으로 좀 더 자세한 내용은 책을 보기 바랍니다.


point. 좋은 소스코드는 '눈을 편하게' 해야 한다.

  • 읽기 편한 소스코드를 작성하는 세 가지 원리
    • 코드를 읽는 사람이 이미 친숙한, 일관성 있는 레이아웃을 사용하라.
    • 비슷한 코드는 서로 비슷해 보이게 만들어라.
    • 서로 연관된 코드는 하나의 블록으로 묶어라.

일관성과 간결성을 위해서 줄 바꿈을 재정렬하기

before

public class PerformanceTester {
    public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator(
        500, // Kbps
        80, // millisecs 대기시간
        200, // 흔들림 
        1 //  패킷 손실  
    );

    public static final TcpConnectionSimulator t3_fiber =
        new TcpConnectionSimulator(
            500, // Kbps
            80, // millisecs 대기시간
            200, // 흔들림
            1 // 패킷 손실 
    );

    public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator(
        500, // Kbps
        80, // millisecs 대기시간
        200, // 흔들림
        1 // 패킷 손실
    );
}
after

public class PerformanceTester {
    public static final TcpConnectionSimulator wifi = 
      new TcpConnectionSimulator(
        500, // Kbps
        80, // millisecs 대기시간
        200, // 흔들림
        1 // 패킷 손실
    );

    public static final TcpConnectionSimulator t3_fiber =
      new TcpConnectionSimulator(
        500, // Kbps
        80, // millisecs 대기시간
        200, // 흔들림
        1 // 패킷 손실 
    );

    public static final TcpConnectionSimulator wifi = 
      new TcpConnectionSimulator(
        500, // Kbps
        80, // millisecs 대기시간
        200, // 흔들림
        1 // 패킷 손실
    );
}
public class PerfoemanceTester {
    //     TcpConnectionSimulator (처리량,   지연속도,  흔들림,  패킷 손실)
    //                             [Kbps]      [ms]      [ms]    [percent]

    public static final TcpConnectionSimulator wifi = 
        new TcpConnectionSimulator(500,         80,           20,           1);

    public static final TcpConnectionSimulator t3_fiber = 
        new TcpConnectionSimulator(45000,       0,            0,           0);

    public static final TcpConnectionSimulator cell = 
        new TcpConnectionSimulator(100,        400,          250,           5);


메소드를 활용하여 불규칙성을 정리하라

before

DatabaseConnection database_connection;
string error
assert(ExpandFullName(database_connection, "Donug Adams", &error)
    == "Mr, Douglas Adms");
assert(error == "");
assert(ExpandFullName(database_connection, "Jake Brown", &error)
    == "Mr, Jacob Brown III");
assert(error == "");
assert(ExpandFullName(database_connection, "No Such Guy", &error) == "");
assert(error == "no match found");
assert(ExpandFullName(database_connection, "John", &error) == "");
assert(error == "more than one result");

afrer

  • 중복된 코드를 없애서 코드를 더 간결하게 한다.
  • 이름이나 에러 문자열 같은 테스트의 중요 부분들이 한 눈에 보이게 모아졌다. 수정 전에는 database_connection이나 error 같은 토큰들과 섞인 채 흩어져 있었기 때문에 코드를 한 눈에 파악하기 어려웠다.
  • 새로운 테스트 추가가 훨씬 쉬워졌다.
void CheckFullNAme(string partial_name,
                    string expected_full_name,
                    string expected_error) {
    // database_connection은 이제 클래스 맴버이다.
    string error;
    string full_name = ExpandFullName(database_connection, partial_name, &error);
    assert(error == expected_error);
    assert(full_name == expected_full_name);
}

CheckFullName("Doug Adams", "Mr. Douglas Adams", "");
CheckFullName("Jake Brown", "Mr. Jake Brown III", "");
CheckFullName("No Such Guy", "", "no match found");
CheckFullName("John", "", "more than one result");


도움이 된다면 코드의 열을 맞춰라

after

details  = request.POST.get('details');
location = request.POST.get('location');
phone    = request.POST.get('phone');
email    = request.POST.get('email');
url      = request.POST.get('url');


의미 있는 순서를 선택하고 일관성 있게 사용하라

  • 변수의 순서를 HTML 폼에 있는 <input> 필드의 순서대로 나열하라.
  • '가장 중요한 것'에서 시작해서 '가장 덜 중요한 것'까지 순서대로 나열하라.
  • 알파벳 순서대로 나열하라.

선언문을 블록으로 구성하라

before

class FrontendServer {
	public:
		FrontendServer();
		void ViewProfile(HttpRequest* request);
		void OpenDatabase(string location, string user);
		void SaveProfile(HttpRequest* request);
		string ExtractQueryParam(HttpRequest* request, string param);
		void ReplyOK(HttpRequest* request, string html);
		void closeDatabase(string location);
}

after

class FrontendServer {
	public:
		FrontendServer();
		~FrontendServer();

		// 핸들러들
		void ViewProfile(HttpRequest* request);
		void SaveProfile(HttpRequest* request);

		// 질의/응답 유틸리티
		string ExtractQueryParam(HttpRequest* request, string param);
		void ReplyOK(HttpRequest* request, string html);

		// 데이터베이스 헬퍼들
		void OpenDatabase(string location, string user);
		void closeDatabase(string location);

}

코드를 '문단'으로 쪼개라

  • 비슷한 생각을 하나로 묶어서, 성격이 다른 생각과 구분한다.
  • 문단은 '시각점 디딤돌'역할을 수행한다. 문단이 없으면 하나의 페이지 안에서 읽던 부분을 놓치기 쉽다.
  • 하나의 문단에서 다른 문단으로의 전진을 촉진시킨다.

after

def suggest_new_friends(user, email_password):
	# 사용자 친구들의 이메일 주소를 읽는다.
	friends = user.friends()
	friend_emails = set(f.email for f in friends)

	# 이 사용자의 이메일 계정으로부터 모든 이메일 주소를 읽어들인다.
	contacts = import_contacts(user.email, email_password)
	contact_emails = set(c.email for c in contacts)

	# 아직 친구가 아닌 사용자들을 찾는다.
	non_friend_emails = contact_emails - friend_emails
	suggested_friends = User.objects.select(email_in=non_friend_emails)

	...

	return render("suggested_friends.html", display)



  • 일관성 있는 스타일은 '올바른' 스타일보다 더 중요하다.


+ Recent posts