Hayden's Archive

클린코드(Clean Code) 1, 2장 - 로버트 C. 마틴 본문

Book

클린코드(Clean Code) 1, 2장 - 로버트 C. 마틴

_hayden 2021. 2. 16. 15:03

book.naver.com/bookdb/book_detail.nhn?bid=7390287

 

Clean Code

『CLEAN CODE(클린 코드)』은 오브젝트 멘토(OBJECT MENTOR)의 동료들과 힘을 모아 ‘개발하며’ 클린 코드를 만드는 최상의 애자일 기법을 소개하고 있다. 소프트웨어 장인 정신의 가치를 심어 주며

book.naver.com

 


1. 깨끗한 코드

  • 궁극적으로 코드는 요구사항을 표현하는 언어
  • 나쁜 코드가 쌓일수록 팀 생산성은 떨어진다
  • 시간을 들여 깨끗한 코드를 만드는 노력 = 비용을 절감하는 방법 + 전문가로서 살아남는 길
  • 기한을 맞추는, 빨리 가는 유일한 방법은 언제나 코드를 최대한 깨끗하게 유지하는 습관
  • 코드를 읽는 시간 대 코드를 짜는 시간 비율이 10대 1을 훌쩍 넘는다. 새 코드를 짜면서 우리는 끊임없이 기존 코드를 읽는다. 기존 코드를 읽어야 새 코드를 짜므로 읽기 쉽게 만들면 사실은 짜기도 쉬워진다.
  • 코드를 잘 짜는 것에서 그치지 않고 시간이 지나도 언제나 깨끗하게 유지해야 한다. 시간이 지날수록 점점 코드가 좋아지도록 한다.
    • ex) 변수 이름 하나 개선 / 조금 긴 함수 하나를 분할 / 약간의 중복 제거 / 복잡한 if문 하나를 정리

 


 

2. 의미 있는 이름

  • 이름을 잘 짓는 간단한 규칙
    • 의도를 분명히 밝혀라
      • 의도가 분명한 이름이 정말로 중요하다. 이름을 주의 깊게 살펴서 더 나은 이름이 떠오르면 개선하자.
      • 변수(또는 함수나 클래스)의 존재 이유/수행 기능/사용 방법을 드러낼 수 있도록 이름을 짓는다.
      • 따로 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말
      • 코드의 함축성(코드의 맥락)이 명시적으로 드러나야 한다.
    • 그릇된 정보를 피하라
      • 코드에 그릇된 단서를 남겨서는 안 된다. 코드의 의미를 흐릴 수 있기 때문이다.
      • 약어 사용에 유의한다
      • 실제 List가 아니라면 List라 명명하지 않는다. 실제 컨테이너가 List인 경우라도 컨테이너 유형을 이름에 넣지 않는 편이 바람직하다. (accountLIst -> 실제 List가 아니라면, accountGroup, bunchOfAccounts, Accounts로 명명함)
      • 서로 흡사한 이름을 사용하지 않도록 주의한다. ex) XYZControllerForEfficientHandlingOfStrings와 XYZControllerForEfficientStorageOfStrings
      • 유사한 개념은 유사한 표기법 사용(정보) / 일관성이 떨어지는 표기법(그릇된 정보)
    • 의미 있게 구분하라
      • 저자의 의도가 드러나도록 의미 있게 구분한다.
      • 연속적인 숫자를 덧붙인 이름(a1, a2, ..)은 의도적인 이름과 정반대다
      • 불용어를 추가한 이름도 아무런 정보를 제공하지 않고 구분이 되지 않는다 ex) Product와 ProductInfo / money와 moneyAmount
      • a나 the와 같은 접두어는 사용하지 않는다
      • 변수 이름에 variable이라는 단어, 표 이름에 table이라는 단어 금물
    • 발음하기 쉬운 이름을 사용하라
    • 검색하기 쉬운 이름을 사용하라
      • 이러한 관점에서는 긴 이름이 짧은 이름보다 검색하기에 좋다.
      • 검색하기 쉬운 이름이 상수보다 좋다
        • 상수 5만 쓰면 5가 들어가는 이름이 다 검색되지만, WORK_DAYS_PER_WEEK로 쓰면 찾기 편하다
    • 인코딩을 피하라
      • 굳이 부담을 더하지 않아도 이름에 인코딩할 정보는 아주 많음
        • 유형이나 범위 정보까지 인코딩에 넣으면 그만큼 이름을 해독하기 어려워짐
      • 헝가리식 표기법
        • 프로그래밍 언어에서 변수 및 함수의 인자 이름 앞에 데이터 타입을 명시하는 코딩 규칙 
        • 요즘 나오는 프로그래밍 언어는 훨씬 많은 타입을 지원하며, 컴파일러가 타입을 기억하고 강제함
          • 변수 이름에 타입을 인코딩할 필요가 없음
          • 객체는 강한 타입(Strongly_Typed)이며, IDE는 컴파일하지 않고도 타입 오류 감지 가능
      • 멤버 변수 접두어
        • 멤버 변수에 m_이라는 접두어를 붙이지 않음
        • 클래스와 함수는 접두어가 필요없을 정도로 작아야 마땅함
      • 인터페이스 클래스(Interface Class)와 구현 클래스(Concrete Class)
        • 인터페이스 이름은 접두어를 붙이지 않는 편이 좋음
          • 접두어 I는 주의를 흐트리고 과도한 정보를 제공함
        • 인터페이스 클래스 이름과 구현 클래스 이름 중 하나를 인코딩해야 한다면 구현 클래스 이름을 택하는 게 나음
        • ShapeFactoryImpl나 심지어 CShapeFactory가 IShapeFactory보다 좋음
    • 자신의 기억력을 자랑하지 마라
      • 독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 하는 일이 없어야 함
        • 일반적으로 문제 영역이나 해법 영역에서 사용하지 않는 이름을 선택했기 때문임 
      • 문자 하나만 사용하는 변수 이름은 문제가 있음
        • 루프 범위가 아주 작고 다른 이름과 충돌하지 않을 때, 루프에서 반복 회수를 세는 i, j, k는 괜찮음(l은 절대 안 됨)
      • 똑똑한 프로그래머 : 자신의 정신적 능력을 과시
      • 전문가 프로그래머 : 명료함이 최고라는 사실 이해. 자신의 능력을 좋은 방향으로 사용하여 남들이 이해하는 코드를 내놓음
    • 클래스 이름
      • 클래스 이름과 객체 이름은 명사나 명사구가 적합함. 동사는 사용하지 않음
      • 좋은 예
        • Customer, WikiPage, Account, AddressParser 등
      • 피해야 할 단어
        • Manager, Processor, Data, Info 등
    • 메서드 이름
      • 동사나 동사구가 적합함
      • 좋은 예
        • postPayment, deletePage, save 등
      • 접근자(Accessor), 변경자(Mutator), 조건자(Predicate)는 JavaBean 표준에 따라 get, set, is를 붙임
      • 생성자(Constructor)를 중복정의(Overload)할 때는 정적 팩토리 메서드를 사용함. 메서드는 인수를 설명하는 이름 사용.
        • Complex fulcrumPoint = Complex.FromRealNumber(23.0);
        • Complex fulcrumPoint = new Complex(23.0); 보다 위의 코드가 더 좋음
        • 생성자 사용을 제한하려면 해당 생성자를 private로 선언
    • 기발한 이름은 피하라
      • 재미있는 이름보다 명료한 이름 사용
      • 특정 문화에서만 사용하는 농담을 피함. 의도를 분명하고 솔직하게 표현.
    • 한 개념에 한 단어를 사용하라
      • 추상적인 개념 하나에 단어 하나를 선택해서 이를 고수함. 일관성 있는 어휘 사용.
        • 똑같은 메서드를 클래스마다 fetch, retrive, get으로 제각각 부르면 혼란스러움
        • 동일 코드 기반에 controller, manager, driver를 섞어 쓰면 혼란스러움
          • 이름이 다르면 독자는 당연히 클래스도 다르고 타입도 다르리라 생각함
      • 메서드 이름은 독자적이고 일관적이어야 함(주석을 뒤져보지 않고도 프로그래머가 올바른 메서드를 선택할 수 있도록)
    • 말장난을 하지 마라
      • 한 단어를 두 가지 목적으로 사용하지 말 것. 다른 개념에 같은 단어 사용 = 말장난.
      • 같은 맥락이 아닌데도 '일관성'을 고려해서 add라는 단어를 선택한 경우
        • 지금까지 구현한 add 메서드는 모두가 기존 값 두 개를 더하거나 이어서 새로운 값을 만든다고 가정
        • 새로 작성하는 메서드는 집합에 값 하나를 추가해야 함
        • 이럴 경우 새로 작성하는 메서드는 기존 add 메서드와 맥락이 다르므로, insert나 append라는 이름이 적당함
    • 해법 영역에서 가져온 이름을 사용하라
      • 코드를 읽을 사람도 프로그래머이므로 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등을 사용해도 됨
      • 하지만 모든 이름을 문제 영역(domain)에서 가져오는 정책은 현명하지 않음
        • 같은 개념을 다른 이름으로 이해하던 동료들이 매번 고객에게 의미를 물어야 함
      • 프로그래머에게 익숙한 개념에는 기술 이름이 가장 적합한 선택
        • VISITOR 패턴에 익숙한 프로그래머는 AccountVisitor라는 이름을 금방 이해함
        • JobQueue를 모르는 프로그래머는 없을 것
    • 문제 영역에서 가져온 이름을 사용하라
      • 적절한 '프로그래머 용어'가 없을 경우 문제 영역(domain)에서 이름을 가져옴
        • 코드를 보수하는 프로그래머가 분야 전문가에게 의미를 물어 파악 가능
      • 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와야 함
    • 의미 있는 맥락을 추가하라
      • 클래스, 함수, 이름 공간에 분명한 의미를 넣어 맥락을 부여함
      • firstName, lastName, street, houseNumber, city, state, zipcode라는 변수가 있을 때, 변수를 훑어보면 주소라는 사실을 금방 알아챔. 하지만 어느 메서드가 state라는 변수 하나만 사용할 경우, 변수 state가 주소 일부라는 사실을 금방 알아챌 수 없음
        • add라는 접두어를 추가해 addFirstName, addLastName, addState라 쓰면 맥락이 좀 더 분명해짐. 변수가 좀 더 큰 구조에 속한다는 사실이 적어도 독자에게는 분명해지는 것
        • 물론 Address라는 클래스를 생성하는 것이 더 좋음
          • 이러면 변수가 좀 더 큰 개념에 속한다는 사실이 컴파일러에게도 분명해짐
    • 불필요한 맥락을 없애라
      • 고급 휘발유 충전소(Gas Station Deluxe)라는 애플리케이션을 짤 때, 모든 클래스 이름을 GSD로 시작하면 안 됨 
        • IDE에서 지원하는 자동 완성 키를 제대로 활용할 수 없음
      • 일반적으로는 의미가 분명할 경우, 짧은 이름이 긴 이름보다 좋음. 
      • 이름에 불필요한 맥락을 추가하지 않도록 주의함
      • accountAddress나 customerAddress는 Address 클래스 인스턴스로는 좋은 이름이나 클래스 이름으로는 적합하지 않음
      •  Address는 클래스 이름으로 적합함
      • 포트 주소, MAC 주소, 웹 주소를 구분해야 한다면, 의미를 좀 더 분명히 하기 위해 PostalAddress, MAC, URI라는 이름도 괜찮음
  • 마치면서
    • 좋은 이름을 선택하는 능력
      • 설명 능력이 뛰어나야 하고 문화적인 배경이 같아야 함
      • 기술, 비즈니스, 관리 문제가 아니라 교육 문제