티스토리 뷰
728x90
객체지향 설계의 3가지 관점
- 아래 3가지 관점은 순서가 아닌 동일한 클래스를 3가지 다른 방향에서 바라보는 것을 의미
개념 관점 설계
- 도메인 안에 존재하는 개념과 개념들 사이의 관계를 표현
- 실제 도메인의 규칙과 제약을 최대한 유사하게 반영하는것이 핵심
명세 관점 설계
- 실제 소프트웨어 안에서 살아 숨쉬는 객체들의 책임에 초점을 맞춰 설계
- 인터페이스와 구현을 분리하는 것은 훌륭한 객체지향 설계를 낳는 가장 기본적인 원칙
구현 관점 설계
- 객체들이 책임을 수행하는데 필요한 동작을 코드로 작성하는 것
실전 - 커피 전문점
커피 전문점
- 커피 전문점이라는 도메인은 손님, 메뉴 항목, 메뉴판, 바리스타, 커피 객체로 구성된 작은 세상
도메인 모델
- 소프트웨어가 대상으로 하는 영역인 도메인을 단순화해서 표현한 모델을 도메인 모델이라고 함
- 어떤 타입(클래스)가 도메인을 구성하고 타입들 사이에 어떤 관계가 존재하는지 파악하기위한 용도
- 메뉴판과 메뉴항목은 하나의 단위로 움직임
- 메뉴판과 메뉴 항목은 합성 관계 표현 (최대 4개의 항목을 가짐)
- 손님은 메뉴판을 알아야 커피를 선택할 수 있으나 메뉴판은 손님의 일부가 아니므로 연관 관계로 표현
- 바리스타는 커피를 제조해야 하므로 커피를 알고 있어야함
- 커피는 바리스타의 일부가 아니므로 연관관계로 표현
협력(메시지) 설계
- 협력을 설계할때 메시지를 먼저 선택하고 후에 메시지를 수신하기에 적절한 객체를 선택해야함
- 메시지를 먼저 선택시 수신할 객체에 대한 정보를 알수 없기 때문에 캡슐화를 지킬수 있음
- 첫번째 메시지는 ‘커피를 주문하라’로 시작
- 괄호 안은 메시지에 담아 전달될 부가적인 정보 인자
- ‘커피를 주문하라’메시지를 수신할 객체로는 손님을 선택
- 손님 객체는 커피를 주문할 책임 할당받음
- 손님은 메뉴 항목에 대해 알지 못하니 메뉴 항목을 찾아줄 대상을 찾는다
- ‘메뉴 항목을 찾아라’ 메시지가 새로 등장함
- 메뉴판 객체가 메뉴를 포함하고 있으므로 메뉴판이 ‘메뉴 항목을 찾아라’ 메시지를 수신
- 손님은 메뉴 항목을 알게되었으니 커피 제조를 요청할 객체를 찾는다
- 바리스타는 커피를 제조하는데 필요한 정보를 알고있으므로 바리스타가 ‘커피를 제조하라’메시지를 수신
인터페이스 정리
- 위에서 정리된 메시지를 가지고 인터페이스를 만든다
- 각 객체를 협력에라는 문맥에서 떼어내서 수신하는 메시지만 추려내면 객체의 인터페이스가 됨
class Customer {
public void order(String menuName) {}
}
---
class MenuItem {
}
---
public class Menu {
public MenuItem choose(String menuName) {
return null;
}
}
---
class Barista {
public Coffee makeCoffee(MenuItem menuItem) {
return null;
}
}
---
class Coffee {
}
코드작성
- 위의 협력 관계를 참고하여 코드를 작성
- 설게는 간단히 끝내고 최대한 빨리 구현에 들어가야함
- 설계가 제대로 그려지지 않는다면 실제 코드를 작성해가면서 협력의 전체적인 밑그림을 그려본다
class Customer {
public Coffee order(String menuName, Menu menu, Barista barista) {
MenuItem choose = menu.choose(menuName);
return barista.makeCoffee(choose);
}
}
---
public class Menu {
private final List<MenuItem> menuItems;
public Menu(List<MenuItem> menuItems) {
this.menuItems = menuItems;
}
public MenuItem choose(String menuName) {
for (MenuItem menuItem : this.menuItems) {
if (menuItem.getName().equals(menuName)) {
return menuItem;
}
}
return null;
}
---
class MenuItem {
private final String name;
private final int price;
public MenuItem(String name, int price) {
this.name = name;
this.price = price;
}
public int cost() { return price; }
public String getName() { return name; }
}
---
class Coffee {
private final String name;
private final int price;
public Coffee(MenuItem menuItem) {
this.name = menuItem.getName();
this.price = menuItem.cost();
}
public void drink() {
System.out.println("drink " + this.name + " coffee");
}
}
---
class Barista {
public Coffee makeCoffee(MenuItem menuItem) {
return new Coffee(menuItem);
}
}
도메인 개념을 참조하는 이유
- 어떤 메시지가 있을때 수신할 객체를 선택할때 도메인 개념중에 가장 적절한 것을 선택하는것
- 도메인지식을 기반으로 코드의 구조와 의미를 쉽게 유추가능
인터페이스와 구현을 분리하라! (캡슐화)
728x90
'독서 > 객체지향의 사실과 오해' 카테고리의 다른 글
chapter6. 객체지도 (1) | 2023.12.22 |
---|---|
chapter5. 책임과 메시지 (1) | 2023.12.22 |
chapter4. 역할, 책임, 협력 (1) | 2023.12.22 |
chapter3. 타입과 추상화 (0) | 2023.12.22 |
chapter2. 이상한 나라의 객체 (0) | 2023.12.22 |
댓글