[오브젝트] 10장_상속과 코드 재사용

이번 장은, 클래스 재사용을 위해 새로운 클래스를 추가하는 가장 대표적 기법인 상속에 대해 정리한다.

01 상속과 중복 코드

DRY 원칙 (Don’t Repeat Yourself)

“동일한 지식을 중복하지 마라”
중복 여부를 판단하는 기준은 변경이다. 중복 코드는 변경을 방해한다. 이것이 중복 코드를 제거해야하는 핵심적 이유이다.
중복 코드는 코드를 수정하는데 노력을 몇배로 증가시킨다. 왜냐하면,

  1. 어떤 코드가 중복인지 찾아야하고,
  2. 찾아낸 모든 코드를 일관되게 수정해야하고,
  3. 개별적으로 테스트를 다 해야하기 때문이다.
중복과 변경

한 달에 한 번씩 가입자별로 전화 요금 계산하는 간단한 애플리케이션을 개발해보자.
개별 통화 기간을 저장하는 클래스가 필요하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Call {
private LocalDateTime from; //통화 시작 시간
private LocalDateTime to; // 통화 종료 시간

public Call(LocalDateTime from, LocalDateTime to) {
this.from = from;
this.to = to;
}

public Duration getDuration(){
return Duration.between(from, to);
}

public LocalDateTime getFrom(){
return from;
}
}

전체 통화 목록에 대해 알고 있는 정보 전문가에게 요금 계산 책임 을 할당해야한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Phone {
private Money amount;
private Duration seconds;
private List<Call> calls = new ArrayList<>();

public Phone(Money amount, Duration seconds) {
this.amount = amount;
this.seconds = seconds;
}

public void call(Call call){
calls.add(call);
}

public List<Call> getCalls() {
return calls;
}

public Money getAmount() {
return amount;
}

public Duration getSeconds() {
return seconds;
}

public Money calculateFee(){
Money result = Money.ZERO;

for (Call call : calls){
result = result.plus(amount.times(call.getDuration().getSeconds() / seconds.getSeconds()));
}

return result;
}
}
Read more

[오브젝트] 9장_유연한 설계

이번 장은, 8장에서 설명한 의존성 관리 기법들을 원칙이라는 관점에서 정리한다.

01 개팡-폐쇄 원칙

소프트웨어 개체(클래스, 모듈, 함수 …) 는 확장에 열려있고, 수정에 닫혀 있어야한다.

  1. 확장에 열려 있다
    요구사항이 변경될 때, 변경에 맞게 새로운 동작을 추가해서 애플리케이션의 기능을 확장할 수 있다.

  2. 수정에 닫혀 있다
    기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경할 수 있다.

컴파일타임 의존성을 고정시키고 런타임 의존성을 변경하라
  1. 런타임 의존성
    실행 시에 협력에 참여하는 객체들 사이의 관계

  2. 컴파일 타임 의존성
    코드에서 드러나는 클래스들 사이의 관계

중복 할인 정책을 추가하기 위해 한 일은, DiscountPolicy 의 자식 클래스로 OverlappedDiscountPolicy 클래스를 추가한 것이다. 단순히 새로운 크래스를 추가하는 것만으로 Movie 를 새로운 컨텍스트에 사용되도록 확장할 수 있었다.
이 설계 방식은,

  1. 새로운 할인 정책을 추가해서 새로운 기능을 확장할 수 있도록 허용한다. 즉, 확장에 열려 있다.
  2. 기존의 코드를 수정할 필요 없이 새로운 클래스 추가만으로 새로운 할인 정책을 확장한다. 즉, 수정에 닫혀 있다.

의존성 관점에서 개방-폐쇄 원칙을 따르는 설계란, 컴파일 타임 의존성은 유지하면서 런타임 의존성의 가능성을 확장하고 수정할 수 있는 구조이다.

추상화가 핵심이다
Read more

[오브젝트] 8장_의존성 관리하기

이번장에서는 충분히 협력적이고 유연한 객체를 만들기 위해, 의존성을 관리하는 방법을 정리한다.

01 의존성 이해하기

변경과 의존성

어떤 객체가 협력을 위해 다른 객체가 필요할 때, 두 객체 사이의 의존성이 존재한다.
아래 코드에서, 어떤 형태로든 DayOfWeek, LocalTime, Screening, DiscountCondition 이 변경되면 PeriodCondition 도 함께 변경될 수 있다.

1
2
3
4
5
6
7
8
9
10
public class PeriodCondition implements DiscountCondition {
private DayOfWeek dayOfWeek;
private LocalTime startTime;
private LocalTime endTime;
...

public boolean isSatisfiedBy(Screening screening){
...
}
}
의존성 전이

PeriodCondition 이 Screening 에 의존하면, PeriodCondition 은 Screening 이 의존하는 대상에 대해서도 의존하게 된다는 것이다.
의존성이 실제로 전이 될지 여부는 변경의 방향과 캡슐화의 정도에 따라 다르다. Screening 이 내부 구현을 효과적으로 캡슐화하면 Screening 에 의존하고 있는 PeriodCondition 까지는 변경이 전파되지 않는다.
의존성의 종류는,

  1. 직접 의존성
    한 요소가 다른 요소에 직접 의존하는 경우. PeriodCondition 이 Screening 에 의존

  2. 간접 의존성
    의존성 전이에 의해 영향이 전파되는 경우

런타임 의존성과 컴파일타임 의존성
Read more

[오브젝트] 7장_객체 분해

하향식 기능 분해 -> 모듈 -> 추상 데이터 타입 -> 클래스

01 프로시저 추상화와 데이터 추상화

  • 데이터 추상화
    • 추상 데이터 타입 : 데이터 중심으로 타입을 추상화
    • 객체지향 : 데이터 중심으로 프로시저를 추상화

02 프로시저 추상화와 기능 분해

메인 함수로서의 시스템

전통적인 기능 분해방법은 하향식 접근법이다. 즉, 최상위 기능을 좀 더 작은 단계의 하위 기능으로 분해해 나가는 방법이다.

급여 관리 시스템

모든 문장이 정제 과정을 거치면서 하나 이상의 좀 더 단순하고 구체적인 문장들의 조합으로 분해된다.

  • 직원의 급여를 계산한다
    • 사용자에게 소득세율을 입력 받는다
      • “세율을 입력하세요 : “ 라는 문장을 화면에 출력한다
    • 직원의 급여를 계산한다
      • 전역 변수에 저장된 직원의 기본접 정보를 얻는다
    • 양식에 맞게 출력한다
급여 관리 시스템 구현
Read more

[오브젝트] 6장_메세지와 인터페이스

이번 장에서는, 유연하고 재사용 가능한 퍼블릭 인터페이스를 만드는데 도움이 되는 설계 원칙과 기법을 익힌다.

01 협력과 메세지

클라이언트-서버 모델
  1. 클라이언트 : 메세지를 전송하는 객체
  2. 서버 : 수신하는 객체

객체는 자신의 희망을 메세지 형태로 전송하고 메세지를 수신한 객체는 요청을 처리하고 응답한다.
객체는 독립적으로 수행할 수 있는 더 큰 책임을 수행하기 위해, 다른 객체와 협력해야 한다.

메세지와 메세지 전송

메세지는 객체들이 협력하기 위해 사용하는 유일한 의사소통 수단이다. 한 객체가 다른 객체에게 도움을 요청하는 것을 메세지 전송이라고 한다.

메세지와 메서드

메세지를 수신했을 때 실제로 수행되는 함수 또는 프로시저를 메서드라고 한다.
메세지 전송자와 메세지 수신자는 서로에 대한 상세한 정보를 알지 못하고 메세지라는 얅고 가는 끈을 통해 연결된다.

퍼블릭 인터페이스와 오퍼레이션
Read more