Dev Book Review/Clean Code

CleanCode 2장 의미 있는 이름

1. 의도를 분명이 밝혀라 변수나 함수 클래스 이름은 의도가 분명한 이름이어야한다. 변수(함수, 클래스)의 존재 이유 변수(함수, 클래스)의 수행 기능 변수(함수, 클래스)의 사용 방법 // 변경 전 int d; //경과 시간 (단위: 날짜); // 변경 후 int daysSinceCreation; 코드의 단순성이 아닌 코드의 함축성을 고려해야한다 -> 코드 맥락을 코드 자체에 명시적으로 드러나야한다. 코드 맥락 정보 제공 방법 : 개념에 이름을 붙인다 // 변경 전 public List getThem(){ List list1 = new ArrayList(); for(int[] x : the List) if(x[0] == 4) list1.add(x); return list1; } /* 변경 후 - 각 칸..

CleanCode 2장 의미 있는 이름

728x90

1. 의도를 분명이 밝혀라

변수나 함수 클래스 이름은 의도가 분명한 이름이어야한다.

  • 변수(함수, 클래스)의 존재 이유
  • 변수(함수, 클래스)의 수행 기능
  • 변수(함수, 클래스)의 사용 방법
// 변경 전
int d; //경과 시간 (단위: 날짜);

// 변경 후
int daysSinceCreation;

코드의 단순성이 아닌 코드의 함축성을 고려해야한다 -> 코드 맥락을 코드 자체에 명시적으로 드러나야한다.
코드 맥락 정보 제공 방법 : 개념에 이름을 붙인다

// 변경 전
public List<int[]> getThem(){
  List<int[]> list1 = new ArrayList<int[]>();
  for(int[] x : the List)
    if(x[0] == 4)
      list1.add(x);
  return list1;
}

/* 변경 후
- 각 칸을 Cell 클래스로 표현
- Cell 필드 값 flagged 확인 메서드로 변경
*/
public List<Cell> getFlaggedCells(){
  List<Cell> flaggedCells = new ArrayList<Cell>();
  for(Cell cell: gameBoard)
    if(cell.isFlagged())
      flaggedCells.add(cell);
  return flaggedCells;
}

 

2. 그릇된 정보를 피하라

여러 계정을 그룹으로 묶을 때, 실제 List가 아니면 accountList라 명명하지 않는다.

  • accountGroup, bunchOfAccounts, Accounts

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

  • XYZControllerForEfficientHandlingOfStrings <-> XYZControllerForEfficientStorageOfStrings

이름만 보고 객체를 선택할 수 있게, 유사한 개념은 유사한 표기법을 사용해 일관성을 준다.
주의 ) l O 1 0 조심히 사용하기!

 

3. 의미있게 구분해라

연속된 숫자를 덧붙인 이름은 아무런 정보를 제공하지 못한다.

public static void copyChars(char a1[], char a2[]){ // source, destination으로 고치자
  for (int i =0; i < a1.length; i++){
    a2[i] = a1[i];
  }
}

불용어를 추가한 이름은 아무런 정보도 제공하지 않는다. 불용어는 중복이기 때문이다.

Product; ProductInfo; ProductData // 의미가 불분명하다.
NameString; Name;    
Customer; CustomerObejct;     // 차이를 알 수가 없다.

읽는 사람이 차이를 알 수 있도록 이름을 지어라

moneyAmount; money;
customerInfo; customer;
accountData; account;
theMessage; message;

 

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

발음하기 쉬운 단어를 사용할 때 대화가 편해진다.

// 변경 전
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";

// 변경 후
private Date generationTimeStamp;
private Date modificationTimeStamp;
private final String recordId = "102";

 

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

문자 하나를 사용하는 이름이나 상수는 검색이 어렵다.

검색의 관점에서 긴 이름이 짧은 이름보다 좋다.
간단한 메서드의 로컬변수 : 한 문자 (이름 길이는 범위 크기에 비례)

상수의 의미를 나타내는 변수로 바꾸어주자.

// 변경 전
for(int j=0; j>34; j++){
  s += (t[j]*4)/5;
}

// 변경 후 : 검색도 가능하고, 이름의 의미를 쫒아 코드 파악이 가능하다.
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for(int j=0; j < NUMBER_OF_TASKS; j++){
  int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
  int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK);
  sum += realTaskWeeks;
}

 

6. 인코딩을 피하라

6-1. 헝가리식 표기법

이전에 컴파일러가 타입을 점검하지 않아 타입을 기억할 단서로 헝가리식 표기법을 사용했다.
그러나 지금은 변수 이름에 타입을 인코딩할 필요가 없다.

// 헝가리식 표기법
PhoneNumber phoneString;    // 타입 바뀌어도 이름은 안 바뀐다.
// 헝가리식 표기법 적용 X
PhoneNumber phonenumber;

 

6-2. 멤버변수 접두어

접두어를 무시하고 이름을 해독하자. 멤버 변수를 눈에 띄게 보여주는 IDE를 사용하자.

// 멤버변수를 의미하는 접두어 m_
public class Part{
  private String m_dsc;  
}

// 접두어가 필요없을 정도로 작아야한다.
public class Part{
  private String description;
}

 

6-3. 인터페이스 클래스와 구현 클래스

인코딩이 필요한 경우가 있다.

  • 인터페이스 클래스 : ShapeFactory.class
  • 구현 클래스 : ShapeFactoryImpl.class

 

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

문자 하나만 사용하는 변수이름은 문제가 있다. (루프에서 반복횟수를 세는 변수는 괜찮다.)

전문가 프로그래머는 명료함이 최고다 : 남들이 이해하는 코드를 내놓는다.
URL에서 r이라는 변수를 과시하는 것처럼 기억력을 과시하지말자.

 

8. 클래스와 메서드 이름

클래스 이름 : 명사구

Customer, WikiPage, Account, AddressParser

Manager, Processor, Data, Info 단어는 피하자.

메서드 이름 : 동사나 동사구

postPaymet, deletePage, save
  • 접근자 (Accessor) : getVerb();
  • 변경자 (Mutator) : setVerb();
  • 조건자 (Predicate) : isVerb();

생성자 중복정의 : 정적 팩토리 메서드 - 인수를 설명한다.

Complex fulcrumPoint = Complex.FromRealNumber(23.0);
  • 생성자 사용 제한을 위해 private으로 생성자를 선언한다.

 

9. 기발한 이름은 피하라

재미난 이름보단 명료한 이름 HolyHandGrenade -> DeleteItems

구어체나 속어의 이름보단 의도를 분명하게 하는 이름 whack() -> kill()

 

10. 한 개념에 한 단어 & 한 단어 한 목적

메서드 이름은 문맥에 독자적이고 일관적이어야한다.
추상적인 개념 하나에 여러 단어를 선택하지 말자

// 어떤 클래스에서 어떤 걸 사용했는지 혼란스럽지 않게 일관성을 유지한다.
fetch, retrieve, get    
controller, manager, driver

한 단어를 두 가지 목적으로 사용하지 마라
같은 맥락일 경우에만 '일관성'을 고려하자.

// 기존 : 기존 값 두개를 더하거나 이어서 새로운 값 만듬
add();
// 새로운 것 : 집합에 값 하나 추가 (다른 맥락)
insert(); append()

 

11. 해법 영역 & 문제 영역에서 가져온 이름을 사용하라

해법 영역 (Solution Domain) : 개발자라면 당연히 알고 있을 전산용어, 알고리즘 이름, 패턴 이름, 수학 용어 등은 사용하자.

JobQueue, AccountVisitor(Visitor pattern)

문제 영역 (Problem Domain) : 실제 도메인의 전문가에게 의미를 물어 파악할 수 있도록 문제 영역에서 이름을 가져오자.

 

12. 의미있는 맥락을 추가하라 & 불필요한 맥락을 없애라

의미가 분명한 이름이 있게 하자 : 클래스, 함수, 이름 공간에 넣어 맥락을 부여한다.

// 하나만 사용하면 주소 관련 변수임을 모른다.
String firstName, lastName, street, houseNumber, city, state, zipcode;

// 접두어를 사용하면 맥락이 좀 더 분명해진다.
String addrFirstName, addrLastName, addrStreet, addrHouseNumber, addrCity, addrState, addrZipcode;

// 클래스를 생성 : 변수가 큰 개념임이 컴파일러에도 분명해진다.
class Address{
  String addrFirstName;
  String addrLastName;
  String addrStreet;
  String addrHouseNumber;
  String addrCity;
  String addrState;
  String addrZipcode
}

맥락을 개선하여 클래스로 만들면 함수를 쪼개기도 쉬워진다.

의미가 분명하다면 일반적으로 짧은 이름이 긴 이름보다 좋다 : 불필요한 맥락을 추가하지 말자.

  • 고급 휘발유 충전소 (Gas Station Deluxe) 애플리케이션을 짠다고, 모든 클래스 이름을 GSD로 시작하지 말자
  • accountAddress, customerAddress : 클래스 이름 X, 인스턴스 이름 O
  • PostalAddress, MAC, URI : 클래스 이름 O

'Dev Book Review > Clean Code' 카테고리의 다른 글

CleanCode 1장 깨끗한 코드  (0) 2020.04.28

댓글

Comments

Dev Book Review/Clean Code

CleanCode 1장 깨끗한 코드

1. 코드가 존재하리라 코드는 요구사항을 표현하는 언어이다 언어는 요구사항에 가깝게한다 요구사항에서 정형구조를 뽑아낸다. 코드의 도움 없이 요구사항을 상세히 표현하기는 불가능하다 : 코드는 정밀한 표현이다. 고도로 추상화된 언어나 특정 응용 분야 언어로 기술하는 명세도 코드이다. 프로그래밍 언어에서 추상화 수준은 점차 높아질 것이다. 2. 나쁜 코드 우리 모두는 좋은 코드가 중요하다는 사실을 안다. 회사가 망한 원인 -> 나쁜 코드 버그가 남아있고, 프로그램이 죽는 횟수가 늘어짐 출시에 바빠 코드를 마음대로 짜고, 기능을 추가할 수록 엉망이 되었다. 고행(wading) = 나쁜 코드를 헤쳐나간다 르블랑의 법칙(Leblanc's Law) = 나중은 결코 오지 않는다. 나중에 손보겠다고 한 코드 + 돌아간다..

CleanCode 1장 깨끗한 코드

728x90

1. 코드가 존재하리라

코드는 요구사항을 표현하는 언어이다

  • 언어는 요구사항에 가깝게한다
  • 요구사항에서 정형구조를 뽑아낸다.

코드의 도움 없이 요구사항을 상세히 표현하기는 불가능하다 : 코드는 정밀한 표현이다.
고도로 추상화된 언어나 특정 응용 분야 언어로 기술하는 명세도 코드이다.

프로그래밍 언어에서 추상화 수준은 점차 높아질 것이다.

 

2. 나쁜 코드

우리 모두는 좋은 코드가 중요하다는 사실을 안다.

회사가 망한 원인 -> 나쁜 코드

  • 버그가 남아있고, 프로그램이 죽는 횟수가 늘어짐
  • 출시에 바빠 코드를 마음대로 짜고, 기능을 추가할 수록 엉망이 되었다.

고행(wading) = 나쁜 코드를 헤쳐나간다

르블랑의 법칙(Leblanc's Law) = 나중은 결코 오지 않는다.

  • 나중에 손보겠다고 한 코드 + 돌아간다는 사실에 안도감을 느끼며 위로함 -> 고치지 않는다.
  • 짤 때부터 클린하게 잘 짜보자

 

3. 나쁜 코드로 치르는 대가

개발속도를 크게 떨어뜨린다.
나쁜 속도가 쌓일수록 팀 생산성은 떨어진다. - 얽히고 설킨 코드를 '해독'하고 더한다.

 

3-1. 원대한 재설계의 꿈

깨끗한 코드를 만드는 노력이 비용을 절감할 뿐아니라 전문가로서 살아남는다.

원대한 재설계 : 타이거팀 - 기존 시스템 기능을 제공하는 새 시스템 + 새로운 변경 > (10년 지속) 이에 대한 새로운 재 설계도 나온다

 

3-2. 태도

좋은 코드를 사수하는 일은 프로그래머의 책임이다.

나쁜코드로 전략한 실패 -> 잘못은 프로그래머 책임이다.
요구사항 변경, 일정 촉박, 관리자 고객 마케팅에 대한 불평 : 프로그래머가 프로젝트 계획을 실패한 것 (전문성의 요소였다)

 

3-3. 원초적 난제

기한을 맞추는 방법 = 빨리가는 방법 = 언제나 코드를 최대한 깨끗하게 유지하는 습관
나쁜코드가 업무 속도를 늦춤을 안다.
그럼에도 기한을 맞추려고 나쁜코드를 짠다 = 빨리가려고 시간을 들이지않는다.

 

3-4. 깨끗한 코드라는 예술

깨끗한 코드 = 코드감각 & 절제와 규율

'코드감각'이 있는 프로그래머 = 나쁜 모듈을 보면 좋은 모듈로 개선할 방안을 떠올린다.

 

3-5. 깨끗한 코드란?

a. 비야네 스트롭스트룹 (Biarne Stroustrup)

  • '보기에 즐거운' 코드
  • 나쁜코드는 나쁜코드를 '유혹'한다 = 나쁜 코드를 고치면서 오히려 더 나쁜 코드를 만든다.
    깨진 창문 ) 창문이 일단 깨지고 나면 쇠퇴하는 과정이 시작된다
  • 세세한 사항까지 꼼꼼하게 처리해야한다. (세세한 오류처리)
    메모리 누수, 경쟁상태(race condition), 일관성 없는 명명법
  • 한가지 목적에 '집중'한다

b. 그래디 부치 (Grady Booch)

  • 가독성을 강조 = 깨끗한 코드가 잘 쓴 문장처럼 읽혀야한다.
  • 코드는 추측이 아니라 사실에 기반해야한다. 필요한 내용만 담아야한다 (명쾌한 추상화)

 

c. '큰(big)' 데이브 토마스 (Dave Thomas)

  • 깨끗한 코드란 다른 사람이 고치기 쉽다
  • 아무리 코드가 우아하고, 가독성이 높아도, 테스트 케이스가 없으면 깨끗하지 않다.
  • 큰 코드보다 작은 코드에 가치를 둔다.
  • 코드가 '문학적'이어야한다 - 인간이 읽기 좋은 코드를 작성하라

 

d. 마이플 페더스 (Michael Feathres)

  • 깨끗한 코드는 시간을 들여 깔금하고 단정하게 정리한 코드다 = 주의를 기울인 코드다.

 

e. 론 제프리스 (Ron Jeffries)

  • 모든 테스트를 통과한다
  • 중복이 없다.
  • 시스템 내 모든 설계 아이디어를 표현한다.
  • 클래스, 메서드, 함수 등을 최대한 줄인다.
    여러 객체로 나누기 : 한 객체가 여러 기능을 수행할 때
    메서드 추출 : 기능을 명확히 기술하는 메서드 하나 + 기능을 실제로 수행하는 메서드 여러개
  • 집합에서 특정 항목을 찾는다 : 추상메서드나 추상클래스를 만들어 실제 구현을 감싼다

 

f. 워드 커닝햄 (Ward Cunningham)

  • 읽으면서 짐작한 대로 돌아가는 코드가 깨끗한 코드다.
  • 코드는 그 문제를 풀기위한 언어처럼 보일때 아름다운 코드다
    언어를 단순해 보이게 만드는 열쇠는 프로그래머

 

4. 우리들 생각 & 우리는 저자다

오브젝트 멘토 진영 [Robert C Martin] 이 생각하는 깨끗한 코드를 설명한다 : 깨끗한 변수 이름, 깨끗한 함수, 깨끗한 클래스

새 코드를 짜면서 우리는 끊임없이 기존 코드를 읽는다 [ 10 : 1 = 읽는 시간 : 짜는 시간 ]

읽기쉬운 코드가 매우 중요하다.

 

5. 보이스카우트 규칙

체크아웃할 때보다 좀 더 깨끗한 코드를 체크인 하자.
캠프장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라

시간이 지날수록 코드가 좋아지는 프로젝트를 작업하자

 

6. 객체 지향 설계의 다섯가지 원칙

SRP (The Single Reponsibility Principle) : 단일 책임의 원칙
클래스에는 한 가지, 단 한 가지 변경 이유만 존재해야 한다.

OCP (The Open Closed Principle) : 개방 폐쇄의 원칙
클래스는 확장에 열려있어야하며, 변경에 닫혀있어야 한다.

LSP (The Liskov Substitution Principle) : 리스코프의 치환 법칙
상속받은 클래스는 기초 클래스를 대체할 수 있어야 한다.

DIP (The Dependency Inversion Principle) : 의존 역전의 법칙
추상화에 의존해야하며, 구체화에 의존하면 안된다.

ISP (The Interface Segregation Principle) : 인터페이스 분리 원칙
클라이언트에 밀접하게 작게 쪼개진 인터페이스를 유지한다.

'Dev Book Review > Clean Code' 카테고리의 다른 글

CleanCode 2장 의미 있는 이름  (0) 2020.04.29

댓글

Comments