본문 바로가기
Concepts/UML

UML - 클래스 다이어그램과 프로퍼티

by ocwokocw 2021. 2. 10.

- 이 글은 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

댓글