Priority

코드의 효율성, 잘 구성된 아키텍처, 테스트의 용이성 등과 같이 좋은 코드는 여러가지 제약조건을 가지고 있다.

단순히 이해하기 쉬운 코드가 최선은 아니다. 그럼에도, 차선을 위해서 우리는 코드를 읽기 쉽게 작성하는 것이 좋다.

assert((!(bucket=FindBucket(key)))||!bucket->IsOccupied());

위의 코드보다, 아래의 코드가 이해하기 쉽듯. 이해하기 쉬운 코드가 중요하다.

bucket = FindBucket(key);
if(bucket!=null) assert(!bucket->IsOccupied());

→ 코드가 짧을수록, 좋은 코드는 아니다.

이제부터 좋은 코드. 사용하고싶어지는 코드를 작성하는 방법에 대해 알아보자


표면적 수준에서의 개선

이름은 일종의 설명문으로 간주해야한다. 충분한 공간은 아니지만 변수, 함수, 클래스등의 이름을 잘 고민하고 결정지을 필요가 있다.

그 로드맵은 다음과 같다.

  1. 특정한 단어 고르기
    1. getPage(url) 보다는 fetchPage(url)이 network를 이용한 웹페이지를 가져옮을 더 쉽게 나타낸다.
  2. 더 화려한 단어 고르기 (단, 재치있는 이름 보다는 명확한 이름 사용하기)
    1. send → deliver, dispatch, announce, distribute, route
    2. find → search, extract, locate, recover
    3. start → launch, create, begin, open
    4. make → create, set up, build, generate, compose, add, new

물론, 지나치게 화려하면 속빈강정이다. split → explode는 오히려 로직을 더욱 추상적으로 만들 수 있다.

  1. tmp, retval, resultValue와 같은 보편적인 이름은 피하자
    1. 변수값이 설명하는 이름을 사용하는 것이 좋다.
    2. 루프 반복자는 i, j, k 보다 객체이니셜_i, 객체이니셜_j, 객체이니셜_j가 좋다. 이중 루프, 삼중 루프가 발생할 때 보다 직관적이다.
for(int i = 0; i<clubs.size(); i++){
	for(int j = 0; j<members.size();j++){
		if(clubs[i].getMembers().contains(members[j]){
			....
		}
	}
}
-> 다음으로 변경하는 것이 좋다.
for(int ci = 0; ci<clubs.size(); ci++){
	for(int mi=0; mi<members.size(); mi++){
		if(clubs[ci].getMembers().contains(members[mi]){
			...
		}
	}
}
  1. 추상적인 이름보다는 구체적인 이름 사용하기
    1. serverCanStart() → canListenOnPort()
      1. 위처럼 변경함으로써, 현재 서버의 구체적인 작동방식을 보다 쉽게 나타낼 수 있다.
  2. 추가적인 정보를 이름에 추가하기
    1. String id → String hexId
    2. Long delay → Long delaySecs
    3. size → sizeMB
    4. limit → maxKbps
    5. angle → degreesCW
    6. password → plainTextPassword
    7. html → htmlUtf8
    8. data → encodedDataUrl