본문 바로가기
Book

[독서 기록] 엘레강트 오브젝트 - 새로운 관점에서 바라본 객체 지향 1장

by Renechoi 2022. 11. 16.

 

 
엘레강트 오브젝트
『엘레강트 오브젝트』 는 〈-er로 끝나는 이름을 사용하지 마세요〉, 〈생성자 하나를 주 생성자로 만드세요〉, 〈생성자에 코드를 넣지 마세요〉, 〈가능하면 적게 캡슐화하세요〉, 〈최소한 뭔가는 캡슐화하세요〉, 〈항상 인터페이스를 사용하세요〉등을 수록하고 있는 책이다.
저자
Yegor Bugayenko
출판
지앤선
출판일
2020.12.30

 

 

엘레강트 오브젝트 - 새로운 관점에서 바라본 객체 지향 1장 (조영호 옮김, 지앤선) 

 


 

1장 출생 

 

객체를 살아있는 유기체라고 생각하고 이야기를 시작해보겠습니다.

- 16p 

 

객체는 자신의 가시성 범위 안에서 살아갑니다 ... 

 

if (price < 100) {
	Cash extra = new Cash(5); 
    price.add(extra); 
}

제 자신이 extra라면 price는 저를 둘러싸고 있는 주변 세계입니다. 숫자 5는 제 안에 있고, 제 내면의 세계입니다. 사실 이 말이 정확한 표현이라고 하기는 어렵지만, 현재로서는 price가 객체 외부에 존재하고 5는 객체 내부에 존재한다는 사실에 동의하는 것으로 충분합니다.

- 17p

 

 

클래스는 객체의 팩토리입니다. ... 클래스는 객체를 생성합니다. 일반적으로는 클래스가 객체를 인스턴스화한다(instantiate)라고 표현합니다. 

 

class Cash {
	publish Cash(int dollars) {
    //

new 연산자로 할 수 있는 유일한 작업은 객체라고 불리는 클래스의 인스턴스를 생성하는 것뿐입니다. Class 클래스에게 새로운 객체 생성을 요청하면, 그 결과로 새로운 객체를 얻게 됩니다. 

 

...

 

이제 본론으로 돌아가서 클래스 이름을 짓는 적절한 방법을 살펴보겠습니다. 기본적으로 두 가지 방법이 있는데 하나는 올바른 방법이도 다른 하나는 잘못된 방법입니다. 잘못된 방법은 클래스의 객체들이 무엇을 하고 있는(doing)지를 살펴본 후 기능(functionality)에 기반해서 이름을 짓는 방법입니다. 다음은 이 방식으로 이름 지어진 클래스의 예입니다. 

 

class CashFormatter {
	private int dollars;
    
    CashFormatter(int dlr) {
    	this.dollars = dlr;
    }
    
    public String format() {
    	return String.format("$ %d", this.dollars);
    }
}

 

CashFormatter는 존중할 만한 객체가 아니기 때문입니다. 이 객체는 의인화할 수도 코드 안에서 존경받는 시민으로 대우할 수도 없습니다. 

 

... 클래스의 이름은 무엇을 하는지가 아니라 무엇인지(what he is)에 기반해야 합니다. CashFormatter라는 이름은 Cash, USDCas, CashInUsd와 같은 이름으로 바꿔야 하고 메서드 format()은 usd()로 수정해야 합니다. 

 

class Cash {
	private in dollars;
    
    Cash(int dlr) {
    	this.dollars = dlr;
    }
    
    public String usd() {
    	return String.format ...

 

- 18 ~ 21p 

 

 

 

이 책에서 권장하는 방식에 따라 올바르게 클래스를 설계한다면, 클래스는 많은 수의 ctor과 적은 수의 메서드를 포함할 것입니다. 

- 24p 

 

 

 

경험 법칙은 '인자에 손대지 말라'는 것입니다. 먼저 이 규칙을 위반하는 예제를 하나 살펴보겠습니다. 다음 코드에서는 객체를 초기화하는 동안 ctor에 전달된 인자에 접근하고 있습니다. 

 

class Cash {
	private int dollars;
    
    Cash (String dlr) {
    	this.dollars = Integer.parseInt(dlr);
    }
}

 

객체 초기화에는 '코드가 없어야'하고 인자를 건드려서는 안 됩니다. 

 

... 수정안 예제 

 

class Cash {
	private Number dollars; 
    
    Cash(String dlr) {
    	this.dollars = new StringAsInteger(dlr);
    }
}

class StringAsInteger implements Number {
	private String source;
    
    StringAsInteger(String src) {
    	this.source = src; 
    }
    
    int intValue(){
    	return Integer.parseInt(this.source);
    }
}

첫 번째 예제에서는 객체를 초기화하는 시점에 곧장 텍스트를 숫자로 변환합니다. 두 번째 예제에서는 실제로 사용하는 시점까지 객체의 변환 작업을 연기합니다. 

 

- 30 ~ 31p

 

 

제일 처음 할 일은 객체를 인스턴스화하는 것입니다. 두 번째 할 일은 객체가 우리를 위해 작업을 하게 만드는 것입니다. 이 두 단계가 겹쳐서는 안됩니다. ctor은 어떤 일을 수행하는 곳이 아니기 때문에 ctor 안에서 인자에게 어떤 작업을 하도록 요청해서는 안 됩니다. 다시 말해서 생성자는 코드가 없어야 하고, 오직 할당문만 포함해야 합니다.

- 32p 

 

생성자에서 코드를 없애면 사용자가 쉽게 제어할 수 있는 투명한 객체를 만들 수 있으며, 객체를 이해하고 재사용하기도 쉬워집니다.

- 35p 

 

 

 

 

 

반응형