Skip to content

Latest commit

 

History

History
158 lines (122 loc) · 6.68 KB

220226.md

File metadata and controls

158 lines (122 loc) · 6.68 KB

1. 깨끗한 코드

나쁜 코드

80년대 후반 Killer App을 구현한 회사가 얼마 못가 망하는 일이 있었다. 원인은 나쁜 코드 때문이다.

나중에 코드를 정리하려고 하는 것은 결코 불가능한 일인 것을 인지해야 한다.

나쁜 코드로 치르는 대가

나쁜 코드가 쌓일수록 팀 생산성은 떨어지다가 0에 근접한다.

깨끗한 코드란?

  • Bjarne Stroupstrup
    • 보기에 즐거운 코드
    • 효율적인 코드 (속도, 자원을 고려한 코드)
    • 세사한 사항까지 꼼꼼하게 처리하는 코드 (오류 처리, 메모리 누수, 경쟁 상태 등)
    • 한 가지 일을 잘하는 코드 (한 가지에 집중할 것)
  • Grady Booch
    • 가독성 좋은 코드
    • 추측이 아닌 사실에 기반한 코드 (반드시 필요한 내용만 담을 것)
  • 'Big' Dave Thomas
    • 다른 사람이 고치기 쉬운 코드
    • 테스트 케이스가 있는 코드
    • 간결한 코드
    • 인간이 읽기 좋은 코드
  • Michael Feathers
    • 주의 깊게 작성한 코드
  • Ron Jeffries
    • 중복이 없는 코드
    • 메소드는 한 기능만 수행하도록 한다.
    • 이름은 하는 일을 표현할 수 있어야 한다.
    • 초반부터 간단한 추상화 고려하기
  • Ward Cunningham
    • 읽으면서 짐작한 대로 돌아가는 코드

우리는 저자다

코드를 작성하는 과정에서 코드를 읽는 시간이 높은 비중을 차지한다.
따라서 빠르고, 쉽게 코드를 짜기 위해서는 읽기 쉬운 코드를 작성하는 것이 중요하다.

보이스카우트 규칙

캠프장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라

처음에 코드를 잘 짰더라도 점점 더러워지는 것을 막는 것도 중요하다.
이름을 개선하고, 긴 함수 하나를 분할하고, 약간의 중복을 제거하고, 복잡한 if문 하나를 정리하는 것으로 시간이 지날수록 코드가 좋아질 것이다.

사소한 것 하나라도 개선했다면 그 이전보다 나쁠 수가 없다.


2. 의미 있는 이름

의도를 분명히 밝혀라

주석이 필요 없을 정도로 이름에 존재 이유, 수행 기능, 사용 방법 등이 드러나야한다.

# 예시 1
d = datetime.datetime.now() # 현재 시간
curr_time = datetime.datetime.now() # 현재 시간

독자가 사전에 정보를 알고 있다고 가정하거나 의미를 함축시키지 말아야 한다.

# 예시 2
def getThem():
    list1 = []
    for i in theList:
        if i[0] == 4:
            list1.append(i)
    return list1

# 각 개념에 이름을 붙여서 개선
def getFlaggedCells():
    flaggedCells = []
    for cell in gameBoard:
        if cell[STATUS_VALUE] == FLAGGED:
            flaggedCells.append(cell)
    return flaggedCells

# cell을 클래스로 변경, isFlagged라는 명시적 함수 사용하여 개선
def getFlaggedCells():
    flaggedCells = []
    for cell in gameBoard:
        if cell.isFlagged():
            flaggedCells.append(cell)
    return flaggedCells

그릇된 정보를 피하라

다른 뜻으로 해석될 수 있는 이름을 지양한다.

개발자에게 특수한 의미를 가지는 단어(List 등)는 실제로 그것이 아니라면 사용하지 않는다.

Ex) accountList가 실제로 list가 아니라면 accoutGroup, bunchOfAccounts, Accounts로 명명한다.

서로 흡사한 이름을 사용하지 않는다.

유사한 개념은 유사한 표기법을 사용하여 일관성 있게 만든다.

의미 있게 구분하라

철자를 살짝 바꾸거나, 연속된 숫자를 덧붙이거나, 불용어를 추가하는 방식을 사용하지 않는 것이 좋다.

불용어를 추가한 이름은 아무런 정보도 제공하지 못하고 개념이 구분되지 않는다. 불용어는 중복이다.

  • NameString, Name
  • getActiveAccount(), getActiveAccounts(), getActiveAccountInfo()

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

발음하기 어려운 이름은 대화의 효율을 저해할 수 있다.

genymdhms와 generationTimestamp 중에 어떤 것이 이해하고, 다른 사람과 대화할 때 사용하기 편한지는 눈에 보인다.

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

이름 길이는 범위 크기에 비례하는 것이 바람직하다.

인코딩을 피하라

인코딩이란 이름에 부가 정보를 추가해서 작명하는 것을 말한다.

헝가리안 표기법

  • 이름에 타입을 붙이지 말자 (numInt, phoneString 등)

멤버 변수 접두어

  • 멤버 변수임을 표시하려고 접두어를 붙이지 말자 (m_dsc 등)

인터페이스 클래스와 구현 클래스

  • 인터페이스 클래스와 구현 클래스 중 하나를 인코딩해야 한다면 구현 클래스를 선택하자.

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

독자가 변수 이름을 자신이 아는 이름으로 변환해야 하는 이름은 바람직하지 못하다.

명료함이 최고라는 것을 이해하라.

클래스 이름

명사나 명사구를 사용해라. (Customer, Account 등)
Manager, Processor, Data, Info 등과 같은 단어는 피한다.
동사는 사용하지 않는다.

메소드 이름

동사나 동사구를 사용해라(postPayment, deletePage 등).
접근자, 변경자, 조건자는 get, set, is를 앞에 붙인다.
생성자를 오버로드할 때 메소드는 인수를 설명하는 이름을 사용한다.

기발한 이름은 피하라

재미있는 이름보다 명료한 이름을 선택해서 의도를 분명하고 솔직하게 표현하자.

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

추상적인 개념 하나에 단어 하나를 선택해 이를 고수하자.

  • 같은 메소드를 fetch, retrieve, get으로 다르게 부르면 혼란스럽다.

말장난을 하지 마라

한 단어를 두 가지 목적으로 사용하지 말자.

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

모든 이름을 문제 영역에서 가져오는 일은 하지 말자.
코드를 읽을 사람도 개발자이기 때문에 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등은 사용하자.

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

문제 영역 개념과 관련이 깊고, 적절한 프로그래머 용어가 없다면 문제 영역에서 이름을 가져오자.

의미 있는 맥락을 추가하라

클래스, 함수, 이름 공간에 넣어 맥락을 부여하자.
그래도 의미가 불분명하다면 접두어를 붙여 작명하자.

불필요한 맥락을 없애라

Gas Station Deluxe라는 어플리케이션을 짠다고 해서 모든 클래스 이름을 GSD로 시작하지 말자. 이러면 IDE에서 G를 누르면 모든 클래스가 나열되어 효율적이지 못하다.