객체는 살아있는 유기체이다.
if (price < 100) {
Cash extra = new Cash(5);
price.add(extra);
}
가독성이 떠오르네요. 가독성 좋은 코드 = 유지보수하기 좋은 코드 ?
객체가 필요하면 꺼내쓰고, 더 이상 필요하지 않은 객체를 반환할 수 있는 객체의 웨어하우스로 클래스를 바라봐라, 클래스는 능동적인 관리자
클래스는 객체의 팩토리입니다.
클래스는 객체를 생성합니다. 일반적으로는 클래스가 객체를 인스턴스화한다라고 표현합니다.
new는 객체의 팩토리를 제어할 수 있는 원시적인 수단입니다.
클래스는 객체의 어머니라고 할 수 있다.
클래스 이름 짓기의 잘못된 방법은 클래스의 객체들이 무엇을 하고 있는지를 살펴본 후 기능에 기반해서 이름을 짓는 방법
class CashFormatter {
private int dollars;
CashFormatter(int dlr) {
this.dollars = dlr;
}
public String format() {
return String.format("$ %d", this.dollars);
}
}
CashFormmater 클래스의 객체는 dollar에 저장된 금액을 문자열로 포맷팅하는 일을 수행합니다.
클래스의 이름은 객체가 노출하고 있는 기능에 기반해서는 안 됩니다. 클래스의 이름은 무엇을 하는지가 아니라 무엇인지에 기반해야합니다.
class Cash {
private int dollars;
Cash(int dlr) {
this.dollars = dlr;
}
public String usd() {
return String.format("$ %d", this.dollars);
}
}
객체는 속성이 아닌 역량으로 특징지어져야합니다. What I can do
CashFormatter 가 아니라 -> Cash, USDCash, CashInUSD
format() 가 아니라 -> usd()
Primer
PrimeFinder
PrimeChooser
PrimeHelper
PrimeNumbers
라고 지어야 합니다.util이나 utils를 사용해왔는데 이게 잘못된 이름이라는게 좀 놀랐어요. 이외에도 -er 이 들어간 우리가 당연하다는 듯이 사용했던 class 이름들도요. 해당 상황에서는 또 어떤 이름을 사용해할까 고민이 되었습니다. 보통 util로 사용하는 메서드들을 모아두는 클래스고 객체를 따로 만들지 않는게 보통인데 이 친구를 굳이 네이밍에 맞춰줘야할까 라는생각도 드네요
책에서 표시한 3.2.3 을 먼저 읽어봤습니다. 잘 알려진 유틸리티 클래스의 예제로 java.lang.Math 가 있습니다. 유틸리티 클래스는 어떤 것의 팩토리가 아니기 때문에 진짜 클래스라고 부를 수 없다고 하네요. 네이밍을 떠나서 정적 메서드의 단점을 몇배로 증폭시키고 안티 패턴이라고 가까이 하지마라고 하네요
class Cash {
private int dollars;
Cash(int dlr) {
this.dollars = dlr;
}
}
class Cash {
private int dollars;
//부생성자
Cash(float dlr) {
this((int) dlr);
}
//부생성자
Cash(String dlr) {
this(Cash.parse(dlr));
}
//주생성자
Cash(int dlr) {
this.dollars = dlr;
}
}
주생성자를 부생성자 뒤에 위치시키는 이유는 유지 보수성 때문입니다.
보통 주 생성자를 제일 앞에 뒀는데 제일 뒤에 두는게 편하다고 생각할 수도 있다는게 의외였습니다. 저는 그래도 제일 앞에 둘거에용
주생성자는 인자로 전달된 정수를 이용해서 this.dollars를 초기화합니다. 부생성자는 정수형이 아닌 인자를 전달받아 파싱하거나 변환한 후 주 생성자로 전달할 정수형 인자를 준비합니다.
dollars의 값이 항상 양수여야한다고 가정을 하면 위의 코드는 한 곳에만 유효성 검사 로직을 추가하면 됩니다.
주 생성자는 초기화만 해야합니다 ! 부생성자에서 인자를 준비하고, 포맷팅하고, 파싱하고 변환만 해야합니다.이를 통해(생성자 오버로딩) 코드의 복잡성을 줄이고 중복을 제거할 수 있습니다.
<첫 번째 예제>
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);
}
}