다음은 로버트 C. 마틴 Clean Code(클린 코드)를 읽고, 정리한 내용입니다.
의도를 분명히 밝혀라
"의도가 분명하게 이름을 지으라"라고 말하기는 쉽다. 여기서는 의도가 분명한 이름이 정말로 중요하다는 사실을 거듭 강조한다. 좋은 이름을 지으려면, 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다.
public List<int[]> getThem(){
List<int[]> list1 = new ArrayList<int[]>();
for(int[] x : theList)
if(x[0] == 4)
list1.add(x);
return list1;
}
다음 코드는 무엇을 할까?
(theList에 저장된 배열들 중에서 첫 번째 요소가 4인 배열들을 추출하여 리스트로 반환하는 메서드)
다음은 theList를 추론한 형태이다.
theList = {
{4, 10, 15},
{2, 7, 9},
{4, 8, 12},
{6, 4, 11}
};
getThem 메서드는 복잡한 문장은 없지만 코드가 하는 일을 짐작하기 어렵다.
문제는 코드의 단순성이 아니라 함축성이다. 다시 말해, 코드 맥락이 코드 자체에 명시적으로 드러나지 않는다.
public List<int[]> getFlaggedCells(){
List<int[]> flaggedCells = new ArrayList<int[]>();
for(int[] cell : gameBoard)
if(cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}
지뢰게임 게임을 만든다고 가정하자. 그러면 theList가 게임판이라는 사실을 안다. theList를 gameBoard로 바꿔보자.
게임판에서 각 칸은 단순 배열로 표현한다. 배열에서 0번째 값은 칸 상태를 뜻한다. 값 4는 깃발이 꽂힌 상태를 가리킨다.
각 개념에 이름만 붙여도 코드가 상당히 나아진다.
public List<Cell> getFlaggedCells(){
List<Cell> flaggedCells = new ArrayList<Cell>();
for(Cell cell : gameBoard)
if(cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
한걸음 더 나아가, int 배열을 사용하는 대신, 칸을 간단한 클래스로 만들어도 되겠다. isFlagged라는 좀 더 명시적인 함수를 사용해서 FLAGGED라는 상수를 감춰도 좋겠다. 새롭게 개선한 결과는 다음과 같다.
단순히 이름만 고쳤는 데도 함수가 하는 일을 이해하기 쉬워졌다. 바로 이것이 좋은 이름이 주는 위력이다.
(참고로, 실제 컨테이너가 List인 경우라도, 컨테이너 유형을 이름에 넣지 않는 편이 바람직하다)
클래스 이름
클래스 이름과 객체 이름은 명사나 명사구가 적합하다. Customer, WikiPage, Account, AddressParser 등이 좋은 예다.
Manager, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다.
메서드 이름
메서드 이름은 동사나 동사구가 적합하다. postPayment, deletePage, save 등이 좋은 예다. 접근자, 변경자, 조건자 는 javabean 표준에 따라 앞에 get,set,is 를 붙인다.
- 접근자는 변수의 값을 반환하며, 일반적으로 이름은 getXxx() 형식입니다.
- 변경자는 변수의 값을 설정하며, 일반적으로 이름은 setXxx() 형식입니다.
- 조건자는 불리언(boolean) 값을 반환하며, 일반적으로 이름은 isXxx() 형식입니다.
생성자를 중복 정의 할때는 정적 팩토리 메서드를 사용한다.
정적 팩토리 메서드(Static Factory Method) 패턴은 개발자가 구성한 Static Method를 통해 간접적으로 생성자를 호출하는 객체를 생성하는 디자인 패턴이다. 우리는 지금까지 객체를 인스턴스화 할때 직접적으로 생성자(Constructor)를 호출하여 생성하였는데, 별도의 객체 생성의 역할을 하는 클래스 메서드를 통해 간접적으로 객체 생성을 유도하는 것이다. 그리고 이 정적 메서드를 통칭적으로 정적 팩토리 메서드 패턴이라고 부르는 것이다.
출처:
https://inpa.tistory.com/entry/GOF-💠-정적-팩토리-메서드-생성자-대신-사용하자#static_factory_method_pattern
[Inpa Dev 👨💻:티스토리]
Complex fulcrumPoint = Complex.FromRealNumber(23.0);
Complex fulcrumPoint = new Complex(23.0);
위의 코드가 아래 코드보다 좋다.
생성자 사용을 제한하려면 해당 생성자를 private으로 선언한다.
한 개념에 한 단어를 사용하라
추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다. 예를 들어, 똑같은 메서드를 클래스마다 fetch, retrieve, get으로 제각각 부르면 혼란스럽다. 어느 클래스에서 어느 이름을 썼는지 기억하기 어렵다.
마찬가지로 동일 코드 기반에 controller, manager, driver를 섞어 쓰면 혼란스럽다. DeviceManager와 ProtocolController는 근본적으로 어떻게 다른가? 어째서 둘다 Controller가 아닌가? 어째서 둘다 Manager가 아닌가? 정말 둘다 Driver가 아닌가? 이름이 다르면 독자는 당연히 클래스도 다르고, 타입도 다르리라 생각한다.
말장난을 하지 마라
1 단어를 2가지 목적으로 사용하지 마라. 다른 개념에 같은 단어를 사용한다면 그것은 말장난에 불과하다.
때로는 프로그래머가 같은 맥락이 아닌데도 '일관성'을 고려해 add라는 단어를 선택한다. 예를 들어, 지금까지 구현한 add 메서드는 모두 기존값 2개를 더하거나 이어서 새로운 값을 만든다고 가정하자. 새로 작성하는 메서드는 집합에 값 하나를 추가한다.
이 메세드를 add라 불러도 괜찮을까? add라는 메서드가 많으므로 일관성을 지키려면 add라 불러도 괜찮을까? add라는 메서드가 많으므로 일관성을 지키려면 add라 불러야 하지 않을까? 하지만 새 메서드는 기존 add 메서드와 맥락이 다르다. 그러므로 insert 나 append라는 이름이 적당하다. 새 메서드를 add라 부른다면, 이는 말장난이다.
'Clean Code' 카테고리의 다른 글
5장 형식 맞추기 (0) | 2024.02.19 |
---|---|
4장 주석 (1) | 2024.02.11 |
3장 함수 (0) | 2024.02.09 |
1장 깨끗한 코드 (0) | 2024.02.07 |
클린 코드를 향한 첫 걸음 (0) | 2024.02.07 |