형식 맞추기

  • 프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 한다.
  • 팀이 합의하여 규칙을 정하고 모두가 그 규칙을 따라야 한다.

형식을 맞추는 목적

  • 코드 형식은 중요하다.
  • 의사소통의 일환이다. 의사소통은 전문 개발자의 일차적인 의무다.
  • 구현한 코드들이 변경되더라도 개발자의 스타일과 규율은 잘 사라지지 않는다.

적절한 행 길이를 유지하라

  • 자바에서 파일 크기는 클래스 크기와 밀접하다.
  • 일반적으로 작은 파일이 큰 파일보다 이해하기 쉽다.

신문 기사처럼 작성하라

  • 독자는 위에서 아래로 읽는다.
  • 메소드 전체 내용을 요약하는 이름을 작성한다.
  • 세세한 내용은 또 하나의 메소드로 분리한다.

개념은 빈 행으로 분리하라

  • 빈 행은 새로운 개념을 시작한다는 시각적 단서다.
  • 다른 개념 사이에 개행이 빠지면 가독성이 현저히 떨어진다.

세로 밀집도

  • 서로 밀접한 코드 행은 세로로 가까이 놓여야 한다.

수직 거리

  • 같은 파일에 속할 정도로 밀접한 두 개념은 세로 거리로 연관성을 표현한다.
    • 여기서 뜻하는 연관성이란 한 개념을 이해하는데 다른 개념이 중요한 정도다.
    • 연관성이 깊은 두 개념이 멀리 떨어져 있으면 코드를 읽는 사람이 함수 연관관계와 동작 방식을 이해하기 위해 여기저기 찾느라 시간과 노력을 소모한다.

[수직분리]

변수 선언
  • 처음으로 사용하기 직전에 선언하며 수직으로 가까운 곳에 위치해야 한다.
  • 비공개 함수는 처음으로 호출한 직후에 정의해야 쉽게 눈에 띄어야 한다.
인스턴스 변수
  • 클래스 맨 처음에 선언한다.
종속함수
  • 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치한다.
  • 또한 가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치해야 자연스럽게 읽힌다.
개념적 유사성
  • 개념적인 친화도가 높을수록 코드를 가까이 배치한다.
  • 종속적인 관계가 없더라도 기능적으로 유사하다.
public boolean isAdmin() {  
  return StringUtils.equals(RoleCodes.ADMIN, role.getName());  
}

public boolean isManager() {  
  return StringUtils.equals(RoleCodes.MANAGER, role.getName());  
}

public boolean isUser() {  
  return StringUtils.equals(RoleCodes.USER, role.getName());  
}

세로 순서

  • 호출되는 순서대로 함수를 배치하면 소스 코드 모듈이 고차원에서 저차원으로 자연스럽게 내려간다.
  • 가장 중요한 개념을 표현하고나서 세세한 사항을 표현하면 함수 몇 개만 읽어도 개념을 파악하기 쉬워져서 세세한 사항까지 파고들 필요가 없다.

가로 형식 맞추기

  • 행 길이는 어느 정도가 적당할까?
    • 여러 논쟁이 있지만 120자 정도로 제한하는 것을 권고한다고 한다.

가로 공백과 밀집도

  • 가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다.
    • ex) 할당 연산자 명확, 메소드 파라미터 구분, 연산자 우선순위 강조

가로 정렬

  • 정렬을 통해 강조하려고한 진짜 의도가 가려질 수 있다.
  • 변수 유형은 무시하고 변수 이름부터 읽게 되버린다?
    • 정렬이 필요할 정도로 목록이 길다면 문제는 목록 길이지 정렬 부족이 아니다.
    • 만약 선언부가 길어진다면 클래스를 쪼개야 한다는 의미다.

들여쓰기

  • 들여쓰기가 없다면 인간이 코드를 읽기란 거의 불가능일 것이다.
  • 들여쓰기한 파일은 구조가 한눈에 들어온다.
    • ex) 변수, 메소드, 분기문 등..
  • 들여쓰기 무시하기

    • 간혹 간단하고 짧은 메소드에서 규칙을 무시하고픈 유혹이 생긴다.
    public String render() { return ""; }
    
    public String render() {   
      return "";   
    }

팀 규칙

  • 각자 선호하는 규칙이 있지만 팀에 속한다면 자신이 선호해야할 규칙은 바로 팀 규칙이다.
    • 그래야 스타일이 일관적이고 매끄럽다.
    • 팀 규칙을 정하여 IDE 코드 형식기를 설정하여 모두가 그 규칙을 따라야 한다.
  • 좋은 소프트웨어 시스템은 읽기 쉬운 문서로 이뤄진다.

마치며

팀에서 포괄적인 규칙을 정하여 IDE에 적용하여 사용하다가 의아스러운 부분이 있었다.
상세한 부분에 대해서도   규칙을 정하여  사람이 작성한듯한 가독성 좋은 코드를 작성해야 한다.

적용한 룰에 예외적으로 느껴진 항목

  • 테스트케이스 MockMvc 포맷
  • 포맷으로 지정한 가로 길이를 조금 초과하는 경우
  • 조건문 내 1줄 정지성 키워드(break, return, throw ..) 브레이스 여부

참고문헌 - CleanCode 애자일 소프트웨어 장인 정신

'Development > CleanCode' 카테고리의 다른 글

Meaningful Name  (0) 2017.12.31

의미있는 이름

  • 이름은 패키지, 클래스, 메소드, 변수 등 널리 사용된다.
  • 이름을 잘 지으면 여러모로 편하다.

의도를 분명히 밝혀라

  • 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다.
  • 코드를 보고 더 나은 이름이 떠오르면 즉시 개선하는 것이 좋다.
  • 이름에 주석이 필요하다면 의도를 분명히 드러내지 못한 것이다.
    • ex) int d; // 날짜

그릇된 정보를 피하라

  • 일반적으로 떠오르는 생각을 왜곡시키지 말라.
  • 중의적으로 해석될 수 있는 이름은 지양하라.
  • 코드의 일관성을 깨뜨리지 말라.

    ex)
    String codeList; 
    // 실제 데이터를 담는 컨테이너가 List가 아닌데 변수명으로 list를 사용하는 경우
    
    int a = l; 
    if (O == l)
     a = 01;
    else
     l = Ol;
    // 문자 l은 숫자 1처럼 보이고 문자 O는 숫자 0 처럼 보인다.

의미있게 구분하라

  • 불용어(noise word)를 피하라.
    • ex) int a1, a2, a3;
  • 읽는 사람이 차이를 알수 있도록 이름을 지어라.
  • 정확한 개념이 구분이 되지 않는다.
    • ex) ProductInfo? ProductData?

발음하기 쉬운 이름을 사용하라

  • 두뇌는 단어를 바탕으로 발음하려고 한다.
    • ex) genymdhms -> generateTimestamp

검색하기 쉬운 이름을 사용하라

  • 상수는 검색하기 쉽도록 변수로 정의해서 사용하라.
  • 긴 이름이 짧은 이름보다 검색하기 수월하다.
  • 이름 길이는 범위 크기에 비례해야 한다.
  • 간단한 메서드에서나 짧은 변수명을 사용하라.

인코딩을 피하라

  • 불필요한 정신적 부담일 뿐이다. (변수에 부가정보를 덧붙이는 표기. 해독, 발음, 오타)
  • 헝가리식 표기법
    • 변수명에 타입을 명시한다. 타입이나 이름이 바뀌더라도 반드시 같이 변하진 않는다.
  • 멤버변수 접두어
    • 코드를 읽을수록 접두어/접미어는 관심 밖으로 밀려난다. 구닥다리 코드의 징표일 뿐이다. ex) String m_title, strContent;
  • 인터페이스 클래스와 구현 클래스
    • 때론 구분하기 위해서 인코딩이 필요할 때도 있다.
    • ex) 인터페이스 보다는 구현 클래스를 인코딩 하라. ServerManagerImpl, CServerManager (O) / IServerManager (X)

자신의 기억력을 자랑하지 마라

  • 독자가 코드를 읽다가 변수명을 변환하게 해서는 안된다.
    • 이미 변수 a와 b가 있다고 c라는 이름을 선택하는 논리는 최악이다.
  • 똑똑한 프로그래머와 전문가 프로그래머의 차이점은 명료함이다. 다른 사람들이 잘 알아볼수 있도록 코딩해야 한다.

클래스 이름

  • 클래스/객체 이름은 명사/명사구가 적합하다.
    • Manager, Processor, Data, Info와 같은 단어는 피하라.
    • ex) Customer, AddressParser
  • 동사는 사용하지 않는다.

메서드 이름

  • 메서드 이름은 동사/동사구가 적합하다.
    • ex) deletePage, saveBoard
  • 변경자, 접근자, 조건자는 각각 set, get, is로 시작하라.
    • ex) getItem, setName, isStudent

기발한 이름은 피하라

  • 구어체/속어는 사용해서 안된다.
  • 특정 문화에서만 사용되는 사례도 금한다.
    • ex) kill() -> whack() / abort() -> eatMyShort()

한 개념에 한 단어를 사용하라

  • 똑같은 메서드를 클래스마다 get, fetch, retrieve 등 다른 단어로 혼용하면 혼란스럽다.
  • 일관성 있는 어휘가 독자에게 좋다.

말장난을 하지 마라

  • 한 단어를 두가지 목적으로 사용하지 마라.
  • 다른 개념에 같은 단어를 사용한다면 그것은 말장난에 불과하다.
    ex) 
    지금까지 구현한 모든 add 메소드가 기존 값 두개를 더하거나 이어서 새로운 값을 만든다고 가정하자. 
    새롭게 작성하는 메소드는 집합에 값을 하나만 추가한다. 
    일관성 있게 add라는 메소드명을 사용해야 하는가? 아니다. 
    insert나 append 등 다른 이름을 사용하자.
  • 최대한 이해하기 쉽게 작성해야 한다.
  • 집중적인 탐구가 필요한 코드가 아닌 대충 훑어봐도 이해할 수 있는 코드 작성이 목표다.

해법 영역에서 가져온 이름을 사용하라

  • 코드를 읽을 사람도 프로그래머라는 사실을 명심한다.
  • 전산용어, 알고리즘 이름, 패턴 이름, 수학용어 등을 사용해도 괜찮다.
  • 기술적인 개념에는 기술적인 이름이 가장 적합한 선택이다.
    • ex) queue, stack

문제 영역에서 가져온 이름을 사용하라

  • 적절한 용어가 없다면 문제 영역에서 이름을 가져온다.
    • 코드를 유지 보수하는 개발자가 분야 전문가에게 의미를 물어 파악할 수 있다.
  • 우수한 개발자와 설계자라면 해법 영역과 문제 영역을 구분할 줄 알아야 한다.

의미 있는 맥락을 추가하라

  • 스스로 의미가 분명한 이름은 있다. 하지만 대다수 이름은 그렇지 못하므로 클래스, 함수, 이름 공간에 넣어 맥락을 부여한다.
  • 모든 방법이 실패하면 마지막 수단으로 접두어를 붙인다.
    ex)
    firstName, lastName, street, houseNumber, city, state, zipcode 라는 변수가 있다. 
    변수를 훑어보면 주소라는 사실이 금방 알아챈다. 
    하지만 어느 메소드가 state라는 변수 하나만 사용한다면? 
    변수 state가 주소의 일부라는 사실을 금방 알아챌까? 
    addr 접두어를 추가해 addrFirstName, addrLastName, addrState라고 쓰면 맥락이 분명해진다.

불필요한 맥락을 없애라

ex)
 Gas Station Deluxe 라는 어플리케이션을 작성한다고 해서 클래스 이름 앞에 GSD를 붙이지는 말자. GSDAccount, GSDUser ..
 G를 입력하고 자동완성을 누를 경우 모든 클래스가 나타나는 등 효율적이지 못하다.
 개발자를 지원하는 IDE를 방해할 이유가 없다.

마치며

좋은 이름을 선택하려면 설명 능력이 뛰어나야 하고 의미가 뚜렷한 어휘인지 분별할 줄 알아야 한다.
다른 개발자가 반대할까 두려워 이름을 바꾸지 않아서는 안된다. 
나름대로 수정했다가 질책을 받더라도 개선하려는 노력을 중단해서는 안된다. 
그래야 자연스럽게 읽히는 코드를 짜는 데에 더 집중할 수 있다. 
단기적인 효과는 물론 장기적인 이익도 보장한다.

참고문헌 - CleanCode 애자일 소프트웨어 장인 정신

'Development > CleanCode' 카테고리의 다른 글

Formatting  (0) 2018.03.02

+ Recent posts