[UML] 클래스 다이어그램 의존 관계 설정

우연·2023년 6월 8일
0

문서화

목록 보기
1/1

최근, 디자인 패턴을 학습하며 클래스 다이어그램을 그리며 별 생각없이 화살표를 작성했었는데요.. 🥲
그 화살표에 의미가 있다는건 알았지만 별로 신경쓰지 못하는 저를 발견해서 정리하는 시간을 갖고자 작성하였습니다.

UML

UML은 통합 모델링 언어(Unified Modeling Language)의 약자입니다.
모델을 만들고 설명하는 표준 언어라고 생각하면 됩니다.

왜 UML을 알아야 하나요?🤔

  • 다른 사람들과의 협업에 필요합니다.
    UML 형식을 차용해 의사소통하면, 의미가 명확하고 설계에 대한 논의가 순조롭게 이루어질 수 있습니다.

  • 전체 시스템의 구조와 클래스의 의존성을 파악합니다.
    다이어그램을 분석하면, 시스템의 구조는 물론 클래스 간의 의존성도 파악하기 쉽습니다.
    그 후에 설계를 더 세분화할 수 있겠죠?

  • 유지보수를 위한 백엔드 문서로 사용합니다.
    위의 항목과 이어지는 방법입니다. 구조적으로 효율적이지 않거나, 모듈화 또는 구체화해야하는 작업이 필요하다고 생각한다면 UML을 먼저 작성해보고 구조를 수정하는 것이 좋겠습니다.

Class Relationship

클래스 다이어그램의 주 목적은 클래스 간의 관계와 의존 관계를 쉽게 파악하는 것입니다.
그렇기 때문에 가장 중요한 것이 클래스 간의 관계라고 볼 수 있습니다.

일반화 (Generalization)

부모(슈퍼) 클래스와 자식(서브) 클래스 간의 상속 관계 (Inheritance) 를 나타냅니다.
부모 클래스는 자식 클래스를 일반화한(Generalize) 것이고, 자식 클래스는 부모 클래스를 구체화한(Spectialize) 입니다. IS-A 관계

상속은 부모 클래스의 필드 및 메소드를 구체화해 사용하며 필드 및 메소드를 추가하거나 필요에 따라 메소드를 재정의하여(overriding) 사용합니다.
부모 클래스가 추상 클래스인 경우는 추상 메소드를 반드시 오버라이딩 해야합니다.

위와 같이 표기법은 클래스 사이에 실선을 연결하고 부모 클래스 쪽에 비어 있는 삼각형 화살표를 그립니다.

public class User {
	private int id;
    private String name;
    
    public Todo getTodo() {
    	// 투두리스트를 확인한다.
        return null;
    }
    
    public void write(String text) {
    	// 투두리스트에 글을 적는다.
    }
}
public class Student extends User {
	public void study() {
    	// 공부한다.
    }
}
public class Teacher extends User {
	public void teach() {
    	// 가르친다.
    }
}

자바에서는 extends 키워드를 사용해 상속을 구현합니다.

실체화 (Realization)

interface 의 기능을 실제 기능으로 구현하는 것을 의미합니다.

인터페이스와 클래스 사이의 Relize 관계는 점선과 인터페이스 쪽에 비어있는 삼각형 화살표로 연결합니다.

public interface Shape {
	public double area;
    
    public abstract double calcArea();
}
public class Circle implements Shape {
	@Override
	public double calcArea() {
    	// 면적 계산
        return area;
    }
}

자바에서는 implements 키워드를 사용해 인터페이스를 구현합니다.

의존 (Dependency)

클래스 다이어그램에서 일반적으로 제일 많이 사용되는 관계입니다.
어떤 클래스가 다른 클래스를 참조하는 것을 의미합니다.

클래스 사이를 점선과 참조할 클래스에 화살표를 선으로 그려 표현합니다.
참조의 형태는 아래와 같습니다.

  • 메서드 내 대상 클래스 객체 생성
  • 메서드 내 대상 클래스 객체 사용
  • 메서드 내 대상 클래스 메서드 호출
  • 메서드 내 대상 클래스 객체 리턴
  • 메서드에서 대상 클래스 객체를 매개변수로 받는 것
    이와 같은 객체 참조는 계속 유지하지 않고 메서드의 호출이 끝나면 의존 관계의 클래스와 관계가 끝납니다.

다이어그램은 위에 그려진 어떤 형태로도 모두 가능합니다.
스테레오 타입으로 어떤 목적의 Dependency인지 의미를 명확히 명시할 수 있습니다.
스테레오 타입을 사용하는 방법은 Dependency의 목적 또는 형태가 중요할 경우 사용할 수 있습니다.

public class User {
	public Todo createTodo() {
    	// 객체 생성 및 리턴
    	return new Todo();
    }
    
    public void writeTodo(Todo todo) {
    	// 객체를 매개변수로 받아 사용
        Todo todo = todo.getTodo();
    }
}

자바에서 참조하는 형태에 따른 코드입니다.

연관 (Association, Directed Association)

클래스 다이어그램에서의 Association은 보통 다른 객체의 참조를 가지는 필드를 의미합니다.

위의 다이어그램은 두 가지 형태의 Association 을 나타내고 있습니다.

  • 일반적인 Association
    실선 하나로 클래스를 연결합니다.
    방향이 없으므로 UserPhone 을 참조할 수도, PhoneUser 를 참조할 수도, 둘 다일 수도 있습니다.

  • Directed Association
    클래스를 실선으로 연결 후 끝에 화살표를 추가합니다.
    User 에서 Phone 으로 화살표가 향하고 있으므로 UserPhone 을 참조하는 것을 의미합니다.
    화살표 옆의 -phones 는 roleName(역할명)을 나타내고 어떤 역할로 참조되는지를 의미합니다.

두 형태의 Association 간의 차이는 방향성입니다.
방향의 유무에 따라 참조하는 쪽과 참조 당하는 쪽을 구분합니다.

* 은 개수를 나타내는데 대상 클래스에 가질 수 있는 인스턴스 개수 범위를 뜻합니다.

  • 1 : 1개
    • : 0~n개
  • n...m : n부터 m까지 연관관계를 맺음
public class User {
	private List<Phone> phones;
}

자바로 위 다이어그램의 연관 관계를 나타냈습니다.

집합 (Aggregation, Shared Aggregation)

Association 관계를 조금 더 특수하게 나타내 전체(whole)와 부분(part)의 관계를 나타냅니다.
Aggregation은 Association의 집합 관계를 나타내는 것으로 Collection 이나 Array 를 이용하는 관계입니다.
이 관계는 일반적인 Association으로도 나타낼 수 있어 논란이 지속되고 있습니다.

합성 (Composition, Composite Aggregation)

Aggregation과 비슷하게 전체(whole)와 부분(part)의 집합 관계를 나타내지만 개념적으로 Aggregation 보다 강한 집합을 의미합니다.

Composition vs Aggregation

  • Composition은 Aggregation보다 강한 집합입니다.
  • Composition은 part가 whole의 소유입니다.
  • Aggregation은 part가 whole에 독립적이어서 whole이 part를 빌려쓰는 것과 비슷합니다.

Aggregation과 명확하게 다르게 나타나는 부분들

  • part를 가지는 whole 인스턴스가 part 인스턴스의 전체 수명을 책임집니다.
    - whole 인스턴스가 part 인스턴스를 생성
    - whole 인스턴스가 소멸하면 part 인스턴스도 함께 소멸
    - whole 인스턴스가 복사되면 part 인스턴스도 함께 복사
  • part에 해당하는 인스턴스는 공유될 수 없습니다.

Aggregation과 Composition을 UML 툴에서 그린 후 코드를 만들면 똑같은 코드가 생성됩니다.
하지만 Composition에서는 개발자가 구현해야 할 부분이 몇 가지 있습니다.

  • part 인스턴스의 공유 방지를 위한 Deep Copy 를 구현합니다.
  • whole 인스턴스가 part 인스턴스의 수명을 책임져야 하므로 whole 클래스의 생성자 또는 기타 메소드 내에서 part 인스턴스를 생성합니다.
  • 외부에서 part 객체를 생성하지 못하도록 whole 클래스에는 part 인스턴스에 대한 setter를 삭제합니다.
  • 자바는 Garbage Collector 가 객체 소멸을 담당하므로 part 인스턴스의 소멸은 신경쓰지 않아도 됩니다.
profile
Backend Developer

0개의 댓글