- 이 글은 UML Distilled (마틴 파울러)책을 기반으로 작성하였습니다.
- 개요
클래스 다이어그램은 가장 기본적이며 많이 사용되는 다이어그램이다. 클래스 다이어그램은 객체의 타입과 이 타입간의 존재하는 관계에 대하여 기술한다. 또 프로퍼티와 오퍼레이션 및 제약사항을 보여준다. UML 에서는 클래스의 프로퍼티와 오퍼레이션을 특징이라는 단어로 언급한다.
클래스 다이어그램에서 상자는 클래스이며, 클래스의 이름과, 속성(attribute), 오퍼레이션(operation)을 표시한다. 클래스 간의 관계에는 연관(association)과 일반화(generalization)이다.
- 프로퍼티(Property)
프로퍼티는 클래스의 구조를 나타낸다. 원래는 더 복잡하지만 우선 클래스의 필드라고 생각하면 된다. 프로퍼티는 두 가지 표기법으로 나타낼 수 있는데 하나는 속성이고 다른 하나는 연관이다.
- 속성(attribute)
상자안에 한 줄로 표시되는 프로퍼티
[가시성] [이름]: [타입] [다중성] = [기본 값] {[프로퍼티 문장]}
ex) - name: String = "Untitled" {readOnly}
-
가시성: public(+), private(-)
-
이름: 프로그래밍 언어에서의 필드이름
-
타입: 필드의 타입
-
다중성: 여기에서는 언급하지 않는다.
-
기본 값: 객체 생성시 default 값
-
프로퍼티 문장: 속성의 추가 프로퍼티, 위에서는 읽기 전용을 표시하였으며, 다른 프로퍼티 문장도 있다.
이를 Java로 변환하면private(가시성) String(타입) name(이름) = "Untitled"(기본 값);이 된다.
- 연관(association)
연관은 소스 클래스 -> 타겟 클래스와 같이 두 클래스 사이의 실선으로 표시한다. 타겟 끝쪽에 다중성과 함께 표시하며, 프로퍼티의 타입이 되는 클래스와 연결된다.
- 속성과 연관
왜 하나를 표시하는데 두 가지 표기법이 존재하는가? 그냥 아무거나 쓰면 되는가? 보통은 Boolean, String, 날짜 처럼 값 타입을 표시할때에는 속성을 사용하며, 주문과 같은 클래스에 대해서는 연관을 사용한다.
또는 중요도 여부에 따라서도 속성이나 연관을 나누어 사용할 수 있다. 따라서 어떤 상황에서 무조건 속성이나 연관을 사용해야 한다는 절대적인 기준은 없으며, 상대적인 중요도에 따라 적절한 표기법을 사용한다.
아래 다이어그램에서 Order는 속성을 이용하여 표기한것이고, 아래 Order1은 연관을 이용하여 표기한것이다.
- 다중성(multiplicity)
프로퍼티의 다중성이란 얼마나 많은 객체가 프로퍼티에 들어갈 수 있느냐를 나타내며 하한과 상한을 정한다.
-
1 (ex - 하나의 주문은 단 하나의 고객만 가져야 한다.)
-
0..1 (ex - 고객은 한명의 판매 담당자를 갖거나 갖지 않는다.)
-
* (ex - 고객을 주문을 하지 않을수도 있으며, 여러개의 주문을 할 수 있다.)
위의 표기를 용어로 나타내면 아래와 같다.
-
선택(Optional): 하한이 0
-
필수(Mandatory): 하한이 1 이상
-
단일 값(Single-valued): 상한이 1
-
다중 값(Multivalued): 상한이 1 이상
- 프로퍼티와 프로그래밍 코드
위의 다이어그램에서 OrderLine을 Java Code로 변환하면 아래와 같아진다.
public class OrderLine {
private int quantity;
private Money price;
private Order order;
private Product product;
}
Java 에서는 프로퍼티가 private 필드에 대응된다. 그리고 이 필드와 관련된 접근자 메소드를 선언하여 외부에서 접근할 수 있도록 한다. 만약 프로퍼티 문장이 {readOnly}라면 setter 메소드나 해당 필드를 설정할 수 있는 접근자메소드를 선언하지 않는식으로 구현한다.
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Money getPrice() {
return product.getPrice().multiply(quantity)
}
만약 OrderLine 클래스에서 위와 같이 메소드가 정의되어 있다고 하자. 여기서 getPrice()를 보면 데이터 필드가 아니라 product 와 quantity에 의해 산출된 값임을 알 수 있다. 하지만 외부에서는 필드와 다를 바 없다. 이런 정보은닉은 캡슐화(encapsulation)의 핵심이다.
위 다이어그램에서 Order - OrderLine 간의 관계를 자바 코드로 나타내면 아래처럼 될 것이다.
public class Order {
private List<OrderLine> lineItems = new ArrayList<>();
public List<OrderLine> getLineItems() {
return Collections.unmodifiableList(lineItems);
}
public void addLineItem(OrderLine orderLine) {
lineItems.add(orderLine);
}
public void removeLineItem(OrderLine orderLine) {
lineItems.remove(orderLine);
}
}
다중 값의 프로퍼티에 대해서는 직접적으로 컬렉션 자체를 외부로 노출시키면 안된다. 위의 코드에서는 컬렉션에 대한 읽기 정보를 제공하기 위해서 getLineItems() 에서 수정 불가능한 컬렉션을 반환하였으며, 갱신을 제공하기 위해서 add와 remove 메소드를 제공하였다.
'Concepts > UML' 카테고리의 다른 글
UML - 클래스 다이어그램과 의존 (0) | 2021.02.10 |
---|---|
UML - 클래스 다이어그램과 일반화 (0) | 2021.02.10 |
UML - 클래스 다이어그램과 오퍼레이션 (0) | 2021.02.10 |
UML - 개발 공정 (0) | 2021.02.10 |
UML - 개요 (0) | 2021.02.10 |
댓글