반응형
오브젝트 01 - 객체, 설계
1.1 티켓 판매 애플리케이션 구현하기
조건
- 초대장을 가진 사람은 티켓으로 교환 후 입장 가능
- 일반 입장객은 티켓을 구매 후 입장 가능
간단하고 예상대로 동작하지만 몇가지 문제점이 있는 프로그래밍
public class Theater {
private TicketSeller ticketSeller;
public Theater(TicketSeller ticketSeller){
this .ticketSeller = ticketSeller;
}
public void enter(Audience audience) {
if (audience.getBag().hasinvitation()) {
Ticket ticket = ticketSeller.getTicketOffice().getTicket();
audience.getBag().setTicket(ticket);
} else {
Ticket ticket = ticketSeller. getTicketOffice().getTicket() ;
audience.getBag().minusAmount(ticket.getFee());
ticketSeller.getTicketOffice().plusAmount(ticket.getFee( ));
audience.getBag().setTicket(ticket);
}
}
1.2 무엇이 문제인가?
1.2.1 소프트웨어 모듈이 가져야 하는 세 가지 기능
- 실행 중 제대로 동작할 것
- 모듈의 존재 이유
- 변경이 용이할 것
- 대부분의 모듈은 생명주기 동안 변경되기 때문에 간단한 작업만으로도 변경 가능해야 함
- 변경하기 어려운 모듈은 제대로 동작해도 개선이 필요
- 코드를 읽는 사람과의 의사소통
- 모듈은 특별한 훈련 없이도 개발자가 쉽게 읽고 이해할 수 있어야 함
-> 앞에서 작성한 코드는 제대로 동작하나, 변경 용이성과 가독성이 떨어지므로 수정이 필요하다. 그 이유를 살펴보자
1.2.2 예상을 빗나가는 코드
1. 수동적인 존재들
- 현실에서는 관람객이 직접 자신의 가방에서 초대장을 꺼내고, 돈을 직접 꺼내 판매원에게 지불한다.
- 판매원은 매표소에 있는 티켓을 직접 꺼내 관람객에게 건네고 관람객에게서 직접 돈을 받아 매표소에 보관한다.
- 하지만 코드 안의 관람객, 판매원은 그렇게 하지 않는다.
- 현재의 코드는 우리의 상식과는 너무나도 다르 게 동작하기 때문에 코드를 읽는 사람과 제대로 의사소통하지 못한다.
2. 복잡한 정보들
- 이 코드를 이해하기 위해서는 여러 가지 세부적인 내용들을 한꺼번에 기억하고 있어야 한다.
- Theater의 enter 메서드를 이해하기 위해서는 Audience가 Bag을 가지고 있고, Bag 안에는 현금과 티켓이 들어 있으며 TicketSeller가 TicketOffice에서 티켓을 판매하고, TicketOffice는...등등
- 하나의 클래스나 메서드에서 너무 많은 세부사항을 다루기 때문에 코드 작성자와 코드를 읽고 이해해야 하는 사람 모두에게 큰 부담.
- 가장 심각한 문제는 Audience와 TicketSeller를 변경할 경우 Theater도 함께 변경해야 한다는 사실
1.2.3 변경에 취약한 코드
- 세부적인 코드가 바뀌면, 해당 코드를 의존하고 있는 클래스도 전부 변경되어야 함.
- 최소한의 의존성만 유지하고 불필요한 의존성을 제거하는 것이 목표
- 의존성 <-> 결합도
- 의존성이 높을수록 결합도가 높고, 의존성이 낮을 수록 결합도가 낮다!
1.3 설계 개선하기
- 개선 방법은 간단하다. 관람객과 판매원을 자율적인 존재로 만들자.
1.3.1 자율성을 높이자
- 변경이 어려운 이유는 Theater가 Audience와 TicketSeller뿐만 아니라 Audience의 Bag과 TickeSeller의 TicketOffcie까지 전부 접근할 수 있기 때문.
- Audience와 TicketSeller가 직접 Bag과 TicketOffice를 처리하는 자율적인 존재가 되도록 설계를 변경하면 해결 된다.
public class Theater {
private TicketSeller ticketSeller;
public Theater(TicketSeller ticketSeller) {
this.ticketSeller = ticketSeller;
}
public void enter(Audience audience) {
ticketSeller.sellTo(audience);
}
}
public class TicketSeller {
private TicketOffice ticketOffice;
public TicketSeller(TicketOffice ticketOffice) {
this .ticketOffice = ticketOffice;
}
public void sellTo(Audience audience) {
ticketOffice.plusAmount(audience.buy(ticketOffice.getTicket()));
}
}
public class Audience{
private Bag bag;
public Audience(Bag bag) {
this.bag = bag;
}
public Long buy(Ticket ticket) {
if (bag.hasinvitation()) {
bag.setTicket(ticket);
return 0L;
} else {
bag.setTicket(ticket);
bag.minusAmount(ticket.getFee());
return ticket.getFee();
}
}
- 코드를 수정한결과, 각 클래스 사이의 결합도가 낮아졌다.
- 또한 내부 구현이 캡슐화됐으므로, 한 클래스의 수정이 다른 클래스에 영향을 미치지 않는다.
- 캡슐화를 통해 객체와 객체 사이의 결합도를 낮추게 되면 설계를 좀 더 쉽게 변경할 수 있게 된다.
1.3.2 무엇이 개선됐는가?
- 수정된 코드는 첫번째 코드와 마찬가지고 필요한 기능을 오류없이 수행한다.
- 수정된 Audience와 TicketSeller는 우리의 예상대로 자신이 가지고 있는 소지품을 스스로 관리한다. 코드를 읽는 사람과의 의사소통이 개선되었다.
- Audience나 TicketSeller의 내부 구현을 변경하더라도 Theater를 함께 변경할 필요가 없어졌다.
1.3.3 캡슐화와 응집도
- 핵심은 객체 내부의 상태를 캡슐화하고 객체들은 단지 메시지를 통해서만 상호작용하도록 하게한다.
- 자신과 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도(cohesion)가 높다고 말한다.
- 자신의 데이터를 스스로 처리하는 자율적인 객체를 만들면 결합도를 낮추고 응집도를 높일 수 있다.
1.3.4 절차지향과 객체지향
절차지향 프로그래밍
- 수정 전 코드에서는 한 클래스에서 모든 프로세서가 진행됐고 나머지 클래스는 단지 데이터의 역할만 수행했다.
- 이처럼 프로세스와 데이터를 별도의 모듈에 위치시키는 것을 절차지향 프로그래밍이라고 부른다.
- 절차지향 프로그래밍은 데이터의 변경으로 인한 영향을 지역으로 고립시키기 어렵고, 이는 변경에 대한 두려움을 증가시킨다.
객체지향 프로그래밍
- 데이터와 프로세스가 동일한 모듈 내부에 위치하도록 하는 것을 객체지향 프로그래밍이라고 한다.
- 각자의 프로세스는 각자의 클래스에만 의존한다.
- 변경으로 인한 여파가 여러 클래스로 전파되는 것을 효율적으로 억제한다.
- 캡슐화와 의존성 관리를 통해 객체 사이의 결합도를 낮춰 변경을 용이하게 한다.
1.4 객체지향 설계
1.4.1 설계가 왜 필요한가?
- 설계란 코드를 배치하는 것이다.
- 좋은설계란 오늘 완성해야 하는 기능을 구현하는 동시에 내일 쉽게 변경할 수 있는 코드다.
- 요구사항은 항상 변경되므로 코드는 변경이 용이해야 한다.
- 변경이 용이한 코드란 이해하기 쉬운 코드이다.
- 코드가 변경에 유연하다고 해도 읽기 어렵다면 코드를 수정하겠다는 마음이 사라질 것이다!
728x90
반응형
'스터디 > 오브젝트' 카테고리의 다른 글
오브젝트 06 - 메시지와 인터페이스 (0) | 2024.02.26 |
---|---|
오브젝트 05 - 책임 할당하기 (0) | 2024.02.20 |
오브젝트 04 - 설계 품질과 트레이드오프 (0) | 2024.02.19 |
오브젝트 03 - 역할, 책임, 협력 (0) | 2024.02.13 |
오브젝트 02 - 객체지향 프로그래밍 (0) | 2024.02.06 |
댓글