1장. 잘못된 구조의 문제 깨닫기
다음의 경우 잘못된 구조의 코드
- 의미를 알 수 없는 이름
- 컴퓨터 용어 / 일련번호를 매겨 이름을 지으면 코드에서 의도를 읽어내기가 어렵다.
- 이해하기 어렵게 만드는 조건 분기 중첩
- if 조건문의 중첩은 이해하기 힘들다.
- 수많은 악마를 만들어 내는 데이터 클래스
- 데이터를 갖고 있기만 하는 클래스를 데이터 클래스라고 부른다.
- 데이터 클래스에서 선언하는 데이터를 이용한 로직이 필요한데, 이것을 다른 클래스에서 구현하는 일이 벌어지곤 한다.
데이터와 로직이 분산되어 있는 것을 응집도가 낮은 구조라고 한다.
이떄, 발생할 수 있는 문제를 보자면.
- 코드 중복
- 수정 누락
- 가독성 저하
- 초기화되지 않은 상태(쓰레기 객체)
- 잘못된 값 할당
2장. 설계 첫걸음
- 의도를 알 수 있는 이름 붙이기
- 목적별로 변수를 따로 만들어 사용하기
- 변수의 재할당은 변수의 용도가 바뀌는 문제를 일으키기 쉽다.
- 단순 나열이 아니라, 의미 있는 것을 모아 메서드로 만들기
- 유지 보수와 변경이 쉬워진다.
- 관련된 데이터와 로직을 클래스로 모으기
- 클래스는 데이터를 인스턴스 변수로 갖고, 인스턴스 변수를 조작하는 메서드를 함께 모아 놓은 것
3장: 클래스 설계 _ 모든 곳과 연결되는 설계 기반
클래스 단위로 잘 동작하도록 설계하기
- 클래스의 구성 요소
- 인스턴스 변수
- 메서드 -> 인스턴스 변수에 잘못된 값이 할당되지 않게 막고, 정상적으로 조작하는 메서드
왜 이런 구성을 지켜야 하는 걸까 ?
- 데이터 클래스의 경우 자기 자신을 보호할 수 있는 로직을 갖고 있지 않음. 초기화 작업을 하는 코드가 다른 클래스에 구현이 되어있기 때문에.
- 또한, 데이터 클래스는 다른 클래스의 의존도가 높음
모든 클래스터가 갖추어야 하는 자기 방어 임무
- 생성자로 확실하게 정상적인 값 설정하기
- 로우 데이터 객체를 방지하기 위해. 클래스 인스턴스를 생성하는 시점에 확실하게 인스턴스 변수가 정상적인 값을 갖게 만들면 된다.
class Money {
int amount;
Currency currency;
Money(int amount, Currency currency) {
this.amount = amount;
this.currency = currency;
}
> 이렇게 하면 인스턴스 변수가 무조건 초기화 된다.
- 인스턴스 변수를 불변 변수로 만들기
- 인스턴스 변수에 final 수식자를 붙이면, 한 번만 할당할 수 있다.
- 변수 선언 시점 또는 생성자 안에서만 값을 할당할 수 있으며, 이후에는 재할당 할 수 없음
- 인스턴스 변수에 final 수식자를 붙이면, 한 번만 할당할 수 있다.
- 변경하고 싶다면 새로운 인스턴스 만들기
- 인스턴스 변수의 내용을 변경하는 것이 아니라, 변경된 값을 가진 새로운 인스턴스를 만들어서 사용할 수 있음
class Money {
Money add(int onther) {
int added = amount + other;
return new Money(added, currency);
}
}
> 이렇게 하면 불변을 유지하면서도 값을 변경할 수 있다.
- 메서드 매개변수와 지역 변수도 불변으로 만들기
- 지역 변수와 메서드의 매개변수에 final을 붙여 안정성을 높인다
효과 검토하기
Class Money {
final int amount;
final Currency currency;
Money(final int amount, fianl Currency currency) {
if (amount < 0) {
throw new IllegalArgumentException("금액은 0이상의 값을 지정해 주세요.");
}
if (currency == null) {
throw new NullPoninterException("통화 단위를 지정해 주시요.");
}
this.amout = amount;
this.currency = currency;
}
Money add(final Money other) {
if (!currency.equals(other.currency)) {
throw new IllegalArgumentException("통화 단위가 다릅니다.");
}
final int added = amount + ohter.amount;
return new Money(added, currency);
}
}
클래스 설계란 인스턴스 변수가 잘못된 상태에 빠지지 않게 하기 위해 구조를 만드는 것.
프로그램 구조의 문제 해결에 도움을 주는 디자인 패턴
- 완전 생성자 (complete constructor)
- 잘못된 상태로부터 클래스를 보호하기 위한 디자인 패턴
- 쓰레기 객체를 방지하려면, 인스턴스 변수를 모두 초기화 해야만 한다.
- 잘못된 상태로부터 클래스를 보호하기 위한 디자인 패턴
- 값 객체 (value object)
- 값을 클래스로 나타내는 디자인 패턴