충남대학교 컴퓨터공학과 김현수 교수님의 "소프트웨어 공학" 강의를 필기한 내용입니다.

다소 잘못된 내용과 구어적 표현 이 포함되어 있을 수 있습니다.

동적 모델링

  • 시스템의 기능을 수행하기 위해 컴포넌트들이 어떻게 상호작용하는지 표현
  • 시퀀스 다이어그램, 상태 다이어그램, 액티비티 다이어그램이 있댄다

시퀀스 다이어그램

  • 컴포넌트간 메세지(데이터?) 교환 과정을 순서대로 시각화하여 나타낸 것
  • 유스케이스 단위로 Initial Class Diagram(지난번에 그렸던 그거)로부터 작성한다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image1.png

  • 일단 보면 뭔가 많이 익숙한 그림일거임
  • 왼쪽 위에 Initiating Actor가 위치하고
  • 박스 안에 객체이름:클래스이름 이렇게 되어있는 게 하나의 객체 표현법인데
  • 먼저 중요한 개념은 세로축이 시간흐름이고 세로축으로 그려진 길다란 박스가 Activation Box라고 해서 해당 객체가 활성화되어있는 기간이라는 것이다
  • 이것만 봐도 어떤 느낌인지 알것제? 세로축 시간흐름대로 객체들이 메세지를 주고 받는 것을 화살표로 표시하고 어떤 작업을 하느라 객체가 활성화되어 있는 기간이 세로방향 박스인 것
    • 실선 → 은 Synchronous message 로 메세지 이름과, 괄호에 매개변수가 드간다
      • 보통 메세지 이름은 메소드의 이름이나 Signal이 드간다
      • 아니면 객체의 생성을 나타내기 위해 <<create>> 라는 메세지를 붙일 수도 있다
    • 점선 → 은 이제 값을 리턴하는 것을 의미함
    • 세로 실선은 Life Line 이라고 하는데 이게 객체가 살아있는 기간인 것 - 활성화랑 다르다! 생성과 동시에 Life Line 이 생기고 소멸되면 이게 끊기는 것

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image2.png

  • 객체가 소멸되면 이 그림처럼 X 를 적어주고 Life Line 이 더이상 이어지지 않는다

사례

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image3.png

  • 수강신청 예시임
  • 여기서 알아야 할 것은
  • return message를 생략하고 화살표 위에 반환값 := 라고 적어주기도 한다는 것과
  • 화살표 위에 [조건] 의 형태로 조건부 메세지를 적어줄 수도 있다 - Guard Message 라고 하더라

Combined fragments

  • Combined fragments는 약간 확장판같은거임

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image4.png

  • 먼저 조건부 메세지의 경우에는 메세지가 날아가는 구역에 opt[조건] 의 형태로 제목을 붙이고 박스로 감싸면 된다
  • 즉, 위의 그림에서 condition을 만족하면 op1() 메세지가 날아가는 것
  • 그리고 택 1의 경우에는 그 구역을 alt로 제목을 붙여 박스로 감싼다
  • 위의 그림에서는 condition1이 맞으면 op2, condition2가 맞으면 op3가 날라가는 식
  • 옆에 코드로 작성된거 보면 단번에 이해 가능

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image5.png

  • 예시임
  • 이걸 수도코드로 적어보면 이렇게된다
if changeQuantity {
	setQuantity()
}
if item.quantity == 0 {
	delete item
} else if deleteItem {
	delete item
}

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image6.png

  • 반복문은 위처럼 표현된다
  • loop min, max[condition]으로 최소 반복횟수와 조건을 만족했을 시에 최대 반복 횟수를 정해줄 수 있고
  • 아니면 loop[condition] 으로 조건을 만족하는 와중에 반복하다가 break[condition] 으로 빠져나올 수도 있다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image7.png

  • 이건 이렇게 할 수 있다
func FindCourse(name string) Course {
	for course := range courses {
		courseName := getName();
		if name == courseName {
			return course;
		}
	}
	return null;
}

상태 다이어그램

  • 얘는 쉽다 - Finite State Automata 생각하면 됨 - 상태 Node와 전이 Arc로 표현된 다이어그램

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image8.png

  • 검은점이 시작상태 사각형이 중간상태 원 두개가 종료상태
  • 그리고 위 그림에는 안나와있지만 각 Arc에 전이(트랜지션, Transition) 조건이 붙는다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image9.png

  • Transition의 경우에는 시간개념 없이 바로 일어나는게 원칙이지만 위처럼 ()를 통해 걸리는 시간을 명시할 수 있고 이런걸 결과 시간 표시 트랜지션이라고 한댄다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image10.png

  • 그리고 Transition은 그냥 적는 경우가 일반적이지만 위처럼 Boolean operator를 이용하여 적기도 한댄다

Activity

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image11.png

  • Activity는 해당 상태에 머물면서 하게 되는 일이다
  • 일정 시간이 소요되고
  • 끝난 후에 Transition이 일어나거나 끝나기 전에 외부의 Interrupt에 의해 Transition이 될 수도 있다
  • 위 그림처럼 상태 안에 또 다른 박스를 그리고 do: 키워드를 달아주면 됨

Action

  • 얘는 시간 지연 거의 없이 바로 일어날 수 있는 동작이다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image12.png

  • 일단 첫번째 종류는 Enter / Exit of State Event Listener라고 생각하면 된다 - 해당 노드에 방문했을때 Trigger되거나 해당 노드에서 빠져나왔을 때 Trigger되는 것
  • 저렇게 상태 안의 박스 안에 Enter / 혹은 Exit / 을 달면 된다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image13.png

  • 그리고 이거처럼 event / action 을 통해 Transition이 일어날때 수행되는 Action을 명시할 수 있다

Nested State, Guard Condition

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image14.png

  • 상태 안에 또 다른 상태를 두는 Nested state가 가능하다
    • 이때는 외부상태에서 내부 상태로 바로 들어오거나 나갈 수 있고
    • Wrapping State로 Transition되면 State내에 위치한 Starting State에서부터 시작하게 된다
  • 그리고 [조건] 을 통해 조건부 Transition을 표현할 수 있다

Example

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image15.png

  • 일단 Planned에서
  • 최소수강인원보다 적으면 OpenNotEnoughStudent 상태고
  • 많아지면 OpenEnoughStudent 로 갔다가
  • 꽉 차거나 Enough한 상태에서 닫으면 Closed
  • 취소하거나 NotEnough한 상태에서 닫으면 Cancelled로 가는 다이어그램이고
  • 이걸 Open을 하나로 묶어 Nested State를 이용해 좀 더 간결하게 표현한 것이다

Activity Diagram

  • Activity Diagram은 상태 다이어그램과 유사하나 상태 다이어그램의 경우에는 Event가 발생하면 Transition이 Trigger되었지만 Activity Diagram의 경우에는 외부 Event가 아닌 Activity가 종료되는 것에 Transition이 Trigger되는 차이점이 있다
  • 그래서 State가 Activity로 바뀐다는 것 외에는 State Diagram의 문법을 그대로 사용한다
  • 그 외에 Decision Point라는게 있는데 이건 다이아몬드로 표현되어 하나 이상의 진입 트랜지션에 대해 두개 이상의 진출 트랜지션을 갖는 분기적인 Activity이다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image16.png

  • 이것처럼 다이아몬드와 [] 로 분기를 표현하게 되는데
  • 여기서 못보던거는 ^ 표시는 외부 객체를 나타내는 표시이다 - ^Class.method() 이래하면 외부에 있는 Class의 method()를 실행시키라는 메세지가 되는 것

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image17.png

  • 시퀀스 다이어그램에서는 위처럼 표현이 된다
  • 액티비티 다이어그램은 시퀀스 다이어그램에서의 세로바 하나의 작동 과정에 대해 그리게 된다

병행처리

  • 액티비티 다이어그램은 병행처리를 나타내는데 효과적이다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image18.png

  • Fork: 하나의 입력 트랜시션이 여러개의 출력 트랜지션으로 갈라지는 경우

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image19.png

  • Rendezvous : 여러개의 입력 트랜지션이 다 들어온 후에 여러개의 출력 트랜지션으로 갈라지는 경우

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image20.png

  • Join : 여러개의 입력 트랜지션이 하나의 출력 트랜지션으로 합쳐지는 경우

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image21.png

  • Fork와 Join이 표현된 예시다

%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A9%E1%86%AB07%20-%20%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8%20%E1%84%86%E1%85%A9%E1%84%83%E1%85%A6%E1%86%AF%E1%84%85%E1%85%B5%E1%86%BC%20bf72a6306f8d4799a0df07a54ced9215/image22.png

  • Swimlane 이라는 것은 말 그대로 수영장에서 레인 말하는건데
  • 같은 클래스와 관련된 액티비티끼리 하나의 Swimlane으로 묶은 것을 말한다

동적 모델링 프로세스

  • 보통 Sequence Diagram은 전체적으로 객체들이 상호작용하는 것을 시간순대로 표현한 것이기 때문에 거의 필수적으로 그리고
  • State Diagram은 객체 하나의 상태 변화를 나타내기 위해 그린다 - 근데 모든 객체가 아닌 중요하고 복잡하다고 판단되는 객체에 대해서만 그림
  • 그리고 Activity Diagram은 Operation하나의 상태 변화를 나타내기 위해 그린다 - 이것도 마찬가지로 중요하고 복잡한 Operation에만 그림
  • 모델링 과정을 보면
    1. 시나리오 준비
    2. 시나리오의 이벤트식별
    3. 시나리오별 시퀀스 다이어그램 작성
    4. 식별한 이벤트와 그에 따른 상태를 상태 다이어그램으로 녹여냄
    5. 검토
  • 과정을 겪게 됨

시나리오 준비

  • 생각해보면 유스케이스가 시나리오의 집합이기 때문에
  • 유스케이스 모델링의 결과를 갖다 쓰면 된다
  • 유스케이스에서 flow들이 각각의 시나리오가 되는 것

이벤트 식별

  • 시나리오는 이벤트의 연속이라는 걸 참고해서 식별하면 됨
  • 이벤트를 식별할때는 객체간 교환되는 정보들을 유심히 보면 알 수 있더라
  • 이벤트의 속성은 매소드의 매개변수의 형태로 나타나고, 이벤트가 발생했음을 알리기만 하는 매개변수가 없는 신호 이벤트가 있다
  • 그리고 시나리오의 이벤트를 식별할때는 외부 이벤트부터 시작하는 게 좋다
    • 뭔소린고 하니 사용자나 외부 장치 등과 상호작용하는 외부 이벤트를 먼저 찾고
    • 해당 이벤드가 내부 객체에 도달하는 지점에서부터 이벤트들을 식별해나가면 된다
    • 이벤트를 보내고 받는 지점을 잘 생각해서 이벤트를 할당하면 되고 - 할당이라는 말이 좀 이질적인데 그냥 보내고 받는 지점을 식별해내라 정도로 생각하면 될듯
    • 그리고 매개변수의 값만 다르고 비슷한 동작을 하는 경우에는 별도의 이벤트로 구성하지 말고 하나의 이벤트로 그룹화 해서 사용하면 된다

시퀀스 다이어그램 작성

  • 이렇게 순서화된 시나리오를 기반으로 하나의 시퀀스 다이어그램을 작성하면 된다

상태 다이어그램 작성

  • 일단 UC에서 Main flow부터 상태 다이어그램을 적기 시작한다
  • 그리고 그 Main flow에 대해 시퀀스 다이어그램에서 한 열을 쭉 따라가며 입출력 이벤트를 확인하고 그것으로부터 이벤트 이름(라벨)을 도출한다
    • 시퀀스 다이어그램에서 출력 이벤트는 다 지워주고 입력 이벤트만 남기면 그게 Transition이 됨
    • 한 열이 의미하는 바가 결국에는 하나의 객체이기 때문에 하나의 객체에 대해 상태 다이어그램을 작성하게 되는 셈
  • 그리고 그 이벤트들을 보고 반복되는 게 있다면 loop를 도입하라
    • 단, 무한루프를 방지하기 위해 루프를 구성하는 상태 중 적어도 하나는 루프를 빠져나가는 출력 전이가 있어야 됨
  • 이런 식으로 Main flow에 대한 상태 전이도를 그렸으면
  • Alternative flow에 대해서도 고려를 해 추가해준다
  • Alternative flow에서 분기하는 지점이 어느 상태인지 확인하고
  • 어느 지점에서 다시 결합할 것인지 고려하랜다
  • 그리고 타이밍이나 기타 오류 처리 등을 해주고
  • 검토를 한 후에
  • 중요한 객체에 대해 위 과정을 반복해 상태 다이어그램을 그려준다

상태 다이어그램 검토

  • 누락된 이벤트가 없는 지 확인해야 한다
    • 만약 이런일 이 일어났을 때 어떻게 작동하는가(what-if분석이랜다)
    • 이벤트들에 대한 송수신자를 다시 확인
  • 또한 선행 / 후행상태가 없는 것을 찾고 걔네가 시작 / 종료 상태인지 봐야한다 - 아니라면 문제가 있는 것
  • 그리고 경쟁조건(Race Condition)에서는 이벤트가 누락될 수 있기 때문에 경쟁조건이 없는지, 혹은 경쟁조건에서 누락된 이벤트가 없는지 명확하게 확인해야한다.