Skip to content

[week05] UML

serena edited this page May 28, 2023 · 12 revisions

5주차 토요스터디 / 주제: UML / (23.05.27)

🔎 실험

실험 주제: 작성된 UML을 바탕으로 한 코드를 작성해봅시다.

📝 Todo

제공된 클래스 다이어그램 을 해석해 타입간의 관계를 파악하여 타입을 코드로 작성하자. 제공된 시퀀스 다이어그램 을 해석해 객체간의 소통 방식을 확인하여, 타입의 인스턴스를 생성하고, 메서드를 호출해보자

✏️ 새로 배운 내용

🔥 UML 통합 모델링 언어

소프트웨어 시스템을 그래픽으로 표현하는 표준된 일반적인 방법

  • U/M/L
    • Unified: 95년 이전에는 파편화되어있던 방법들이 하나로 합쳐짐
    • Modeling: 일반화된 특징들중 공통된 성질만을 추출하여 추상화 하는 것 / 추상화 : 사람이 인식할 수 있는 객체 중 보고 싶은 것만 강조하는 것
    • Language: 의사소통을 하기위해 구조화된 방법 - 누구랑? ex) 컴퓨터와 사람
  • 다이러그램은 구조적 다이어그램, 행위적 다이어그램으로 나뉨 - 이 중 class다이어그램(구조적 다이어그램), sequence다이어그램(행위적 다이어그램)



클래스다이어그램 : 한 타입의 특징과 서로 다른 타입 간의 관계를 파악하기 위해 사용

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-25%20%EC%98%A4%EC%A0%84%209 32 18
  • 이름/ 속성/ 기능
  • static : 메소드에 밑줄
  • { readOnly } : final키워드를 사용하는 상수
  • << >> : 길러멧, enum case에 사용
  • + : public
  • - : private
  • class/ struct : 색상으로 구별하기
  • enum case : case 표시하기
  • typealias → 명시하기

화살표 의미

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-25%20%EC%98%A4%EC%A0%84%209 34 35

일반화(Generalization)

부모 클래스와 자식 클래스 간의 상속 관계 (UIViewController ← MainViewController/StockViewController)

여러개의 범주가 있을 때 각각의 범주 내 공통점을 찾아서 공통 범주로 만드는 것

실체화(Realization)

protocol (Stroybodable ← StockViewController 프로토콜이 상위)

명세 정의만 있는 메서드를 오버라이딩

의존(Dependency)

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-25%20%EC%98%A4%EC%A0%84%209 50 22

어떤 클래스가 어떤 클래스를 참조 하는지 (MainView →1 StockView) → 함수의 시작과 끝에만 연관이 있는 것 / 짧게 연관있으니까 점선, 잠깐 의존할게 언제든! / Method

return값은 의존관계 : 주체가 어떠한 행위를 하는 데 대상이 필요하다면 의존이다.

행동을 하는 데 필요해서 의존한다

scope내에서 사용

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-28%20%EC%98%A4%ED%9B%84%2012 41 47
  • <<create>> : 생성
  • <<local>> : initialize할때
  • <<parameter>> : 매개변수와 반환값

연관(Association), 방향성 있는 연관 (FruitStore → Juicemaker)

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-25%20%EC%98%A4%EC%A0%84%209 40 00

다른 객체의 참조를 가지는 프로퍼티.

클래스의 처음부터 끝을 함께 / 뭔가 계속 연관되어 있는 것 길게 연관되어 있으니까 실선

모든 관계는 연관관계로 표현할 수 있다? - 연관은 포괄적인 표현이다 → 포괄적이기때문에 효율적이지 못하다

연관관계 중에서 의존하는 특정 관계가 있다고 생각을 해야한다!!

방향성에 대한 개념을 중점적으로 생각해라! 사람은 주소를 아는데 주소는 사람을 알 필요가 없다

MainView → FruitStore : 방향성이 있는 연관

연관관계와 의존관계의 공통점

두 관계 모두 한 클래스가 다른 클래스의 기능을 사용할 때를 나타냄.

연관관계와 의존관계 차이점

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-25%20%EC%98%A4%EC%A0%84%209 47 40

→ 1 : 1:1 대응 / 1… : 1:다 대응관계 / 0… : optional / 0…* : 배열이면 이렇게 표시!

집합(Aggregation)

사용하지 않는 것이 좋다. Association과 비슷하기 때문

프로퍼티에 존재하는 값들과 컨테이너가 서로 다른 생명주기를 가질때

합성(Compostion)

프로퍼티에 존재하는 값들과 컨테이너가 서로 생명주기가 같을 때!!

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-25%20%EC%98%A4%EC%A0%84%209 54 15

구성관계(Composition)

클래스 내에서 생성된 인스턴스가 클래스와 함께 생명주기를 같이 하는 경우(MainController - JuiceMaker)

얕은 복사의 경우 : 얕은 복사란 클래스의 인스턴스를 복사하지만 같은 주소를 바라보는 경우 → 구성관계라고 보기 힘들다.

%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202023-05-28%20%EC%98%A4%ED%9B%84%2012 59 47

깊은 복사의 경우 : 값 타입 복사를 한 경우 → 구성관계라고 할 수 있다.

시퀀스 다이어그램

  • 사다리타기처럼 타고 내려오는 순서로 읽으면 된다.

guard

  • 단일 메시지에 대해서 조건을 명시할 수 있는 방법이다. 조건을 명시 -> [조건] 처리메시지



프래그먼트(Fragment)

  • guard가 한 메시지에 대해서 조건을 명시했다면, sequnce fragments는 범위로 조건을 명시할 수 있다. 즉, 특정 부분에 대해서 일정 부분의 메시지를 반복하던지 조건을 명시하던지 할때는 sequence fragments가 명확할 수 있다. 프래그먼트에는 대안(alt), 옵션(opt), 반복(loop),병렬(Par), 참조(Ref)가 있다.

  • alt : alternative의 약자이다. 대안이 있는 조건문이다. alt는 조건문인 if/else문을 Guard를 사용해 표현할 수 있다. 아래는 가격이 10000원 이상이면 배송비를 무료로 처리하고 그렇지 않으면 배송비를 유료로 사용하는 것을 표현한 예시입니다.



  • opt : option의 약자이다. opt는 조건문인 if문을 Guard를 사용해 표현할 수 있다.아래는 가격이 10000원 이상이라면 배송비를 무료로 처리하고 고객이 추가 할인 쿠폰을 요청한 다음 쿠폰을 제공하는 예시입니다. 만약 가격이 10000원 미만이라면 해당 로직을 타지 않습니다.



  • loop : for, while과 같은 반복문을 표현한다. 반복문을 실행하고 그 하위 조건으로 처리를 하는 예시입니다.



  • Par : 병렬처리(parallel), 분리된 몇 개의 상호작용이 동시에



  • Ref : 참조. 외부에서 정의된 시퀀스 다이어그램을 포함



  1. 전역에서 if 구문으로 구현 -> Person을 부르는 누군가가 존재해야한다.
예시 코드
if CoffeeMenu.americano.price <= person.money {
    person.buy(.americano, at: coffeeShop)
} else {
    print("잔액이 부족합니다.")
}
  1. 함수 내에서 if 구문으로 구현 -> self.money이기 때문에 함수내에 if 구문 존재. else의 print문도 Person에서 하는 것으로 그려진 것 같기 때문
예시 코드
class Person {
    let name: String
    var money: Int
    var coffee: Coffee?
    
    init(name: String, money: Int) {
        self.name = name
        self.money = money
    }
    
    func buy(_ menu: CoffeeMenu, at shop: CoffeeShop) {
        if menu.price <= money {
            coffee = shop.order(menu)
            money -= menu.price
        } else {
            print("잔액이 부족합니다.")
        }
    }
}
  1. guard 구문으로 함수 내에서 구현
예시 코드
class Person {
    var name: String
    var money: Int
    var coffee: Coffee?
    
    init(name: String, money: Int) {
        self.name = name
        self.money = money
    }
    
    func buy(_ menu: CoffeeMenu, at shop: CafeShop) {
        let coffeePrice = menu.price
        
        guard money >= coffeePrice else {
            print("\(name)은 돈이 부족하다")
            return
        }
   
        shop.order(menu)
        coffee = Coffee(kind: menu)
        money -= coffeePrice
        print("\(name)\(menu)를 주문 했다. \(coffeePrice)금액 차감 남은돈은 \(money)원 남음")
    }
}

📚 참고 링크