간단하게 짜야 유연성을 얻는다.
객체지향 진영에서 유일하게 제시하는 한 가지 방법은 역할모델이다.
역할모델 이외에는 어떠한 도메인을 격리시킬 수 있는 수단을 발견하지 못 했다.
역할 모델을 이해하려면 추상화에 대한 이해가 필요하다
- 일반화(Genralization) - modeling, function, algorithm
- 연관화(Association) - reference, dependence <- 위임 가능
- 집단화(Aggregation) - group, category
- Modeling: 특정 목표에 따라 기억하고 싶은 것만 추린 것
- Categorization
- Grouping: 집합
프로시저는 데이터의 처리를 함수에게 양도함을 뜻하는 "고유명사"다.
- Genralization: 일반화를 잘 사용하면 함수를 여러개 만들 필요가 없음
- Capsulization: 캡슐화는 보다 추상적인 행위를 표현한다 (정보은닉과는 다름)
- Genralization: 인터페이스나 추상클래스로 일반화
- Realization: 인터페이스나 추상클래스를 구현
- Dependency: 인자를 받거나 참조
- Association: 필드들
- Directed Association
- Association
- Composition
프로그램이 실행되는 순간이 언제냐
자바는 최초로 런타임 로딩을 사용하였다.
그래서 실행이될때 모든 것을 메모리에 적재하지 않고 사용이될떄 클래스로더로 불러온다.
그래서 배포할때 첫 요청들은 느렸군아
파일에 있는 변수들은 VTable 로 관리되다가 실제 실행이 될 떄 가상 메모리 주소를 진짜 메모리 주소로 치환한다.
데이형은 데이터가 얼마나 길게 가져가야하는지를 나타냄
직접 참조는 모든 버그의 원인이다 ....
그래서 참조의 참조를 통해서 사용
class ValueType(val name: String) {
override operator fun equals(n: Any?) = n == name
}
객체를 구분한느 방법은 식별자이다.
식별자는 런타임에 메모리에 적재되어 있던 메모리 주소, 똑같은 객체가 있다고 하더라도 메모리 주소가 틀리니 같은 주소가 아니다.
그러기 때문에 객체인지 값인지에 따라 비교 기준이 다르게 된다.
즉 값 컨텍스트와 객체 컨텍스트는 다르다.
ValueType("abc") == ValueType("abc") // true
ValueType("abc") === ValueType("abc") // false
이론적으로 모든 값들도 객체로 구성이 되어야 진정한 객체지향 프로그래밍이라고 할 수 있다.
- Subsitution: 대첵가능성 <- 서로 대체 ??
- Internal identity: 내적동질성 <- 출신지가 더 중요
open class Worker: Runnable {
override fun run(): println("working")
}
var worker: Runnable = Worker()
println(worker.run()) // workimg
상속은 참조에 참조의 연속이다.
-
Encapsulation of Functionality 기능을 캡슐화할 수 있어야함
-
Maintenance of State 상태를 관리할 수 있어야함 ex) 은닉
격리가 되었는지 확인을 하는 가장 확실한 방법은 다른 파일도 같이 수정이 되었는가 확인
극장이 ticket office 를 아는 것이 맞지 않을까 ??
class Theater {
private final List<TicketOffice> ticketOffices = new ArrayList<>;
private final Long fee;
/**
* 다수의 ticketOffice 수용
*/
public void setTicketOffices(TicketOffice ... ticketOffices) { }
/**
* 티켓은 극장에서 티켓오피스로 줄 수 밖에 없다.
* 티켓의 주요 식별자는 극장이다.
*/
public void setTicket(TicketOffice ticketOffice, Long num) { }
/**
* 극장이 특정 귀빈에게 초대권을 준다.
*/
public void setInvitation(Audience audience) { }
/**
* 입장을 시켜준다.
*/
public boolean enter(Audience audience) { //TODO: validate }
}
class Ticket {
final static public Ticket EMPTY = new Ticket(null); // Null 객체 패턴
final private Theater theater;
private boolean isEntered = false;
public Ticket(Theater theater) {
this.theater = theater;
}
public boolean isValid(Theater theater) {
if (isEntered || theater != this.theater || this == EMPTY) {
return false;
} else {
isEntered = true;
return true;
}
}
public Long getFee() {
return theater.getFee();
}
}
public class Invitation {
final static public Invitation EMPTY = new Invitation(null);
final private Theater theater;
public Invitation(Theater theater) {
this.theater = theater;
}
}
/**
* TicketOffice 는 Theater 를 알 필요가 없다.
*/
class TicketOffice {
private Long amount;
private List<Ticket> tickets = new ArrayList<>();
public TicketOffice(Long amount) {
this.amount = amount;
}
public void addTicket(Ticket ticket) {
this.tickets.add(ticket);
}
public Ticket getTicketWithFee() {
if (tickets.size() == 0) {
return Ticket.EMPTY;
} else {
Ticket ticket = tickets.remove(0);
amount += ticket.getFee();
return ticket;
}
}
public Ticket getTicketWithNoFee() {
if (tickets.size() == 0) {
return Ticket.EMPTY;
} else {
return tickets.remove(0);
}
}
public Long getTicketPrice() {
if (tickets.size() == 0) {
return 0L;
} else {
return tickets.get(0).getFee(0);
}
}
}
class TicketSeller {
private TicketOffice ticketOffice;
public TicketSeller(TicketOffice ticketOffice) {
this.ticketOffice = ticketOffice;
}
public Ticket getTicket(Audience audience) {}
}
이러한 설계를 TDD 로 할 수 있는 사람은 켄트백 말고는 없다고함 ....