-
Notifications
You must be signed in to change notification settings - Fork 0
[week05] UML
실험 주제: 작성된 UML을 바탕으로 한 코드를 작성해봅시다.
제공된 클래스 다이어그램 을 해석해 타입간의 관계를 파악하여 타입을 코드로 작성하자. 제공된 시퀀스 다이어그램 을 해석해 객체간의 소통 방식을 확인하여, 타입의 인스턴스를 생성하고, 메서드를 호출해보자
소프트웨어 시스템을 그래픽으로 표현하는 표준된 일반적인 방법
-
U/M/L
- Unified: 95년 이전에는 파편화되어있던 방법들이 하나로 합쳐짐
- Modeling: 일반화된 특징들중 공통된 성질만을 추출하여 추상화 하는 것 / 추상화 : 사람이 인식할 수 있는 객체 중 보고 싶은 것만 강조하는 것
- Language: 의사소통을 하기위해 구조화된 방법 - 누구랑? ex) 컴퓨터와 사람
- 다이러그램은 구조적 다이어그램, 행위적 다이어그램으로 나뉨 - 이 중 class다이어그램(구조적 다이어그램), sequence다이어그램(행위적 다이어그램)
- 이름/ 속성/ 기능
- static : 메소드에 밑줄
- { readOnly } : final키워드를 사용하는 상수
- << >> : 길러멧, enum case에 사용
- + : public
- - : private
- class/ struct : 색상으로 구별하기
- enum case : case 표시하기
- typealias → 명시하기
부모 클래스와 자식 클래스 간의 상속 관계 (UIViewController ← MainViewController/StockViewController)
여러개의 범주가 있을 때 각각의 범주 내 공통점을 찾아서 공통 범주로 만드는 것
protocol (Stroybodable ← StockViewController 프로토콜이 상위)
명세 정의만 있는 메서드를 오버라이딩
어떤 클래스가 어떤 클래스를 참조 하는지 (MainView →1 StockView) → 함수의 시작과 끝에만 연관이 있는 것 / 짧게 연관있으니까 점선, 잠깐 의존할게 언제든! / Method
return값은 의존관계 : 주체가 어떠한 행위를 하는 데 대상이 필요하다면 의존이다.
행동을 하는 데 필요해서 의존한다
scope내에서 사용
-
<<create>>
: 생성 -
<<local>>
: initialize할때 -
<<parameter>>
: 매개변수와 반환값
다른 객체의 참조를 가지는 프로퍼티.
클래스의 처음부터 끝을 함께 / 뭔가 계속 연관되어 있는 것 길게 연관되어 있으니까 실선
모든 관계는 연관관계로 표현할 수 있다? - 연관은 포괄적인 표현이다 → 포괄적이기때문에 효율적이지 못하다
연관관계 중에서 의존하는 특정 관계가 있다고 생각을 해야한다!!
방향성에 대한 개념을 중점적으로 생각해라! 사람은 주소를 아는데 주소는 사람을 알 필요가 없다
MainView → FruitStore : 방향성이 있는 연관
두 관계 모두 한 클래스가 다른 클래스의 기능을 사용할 때를 나타냄.
→ 1 : 1:1 대응 / 1… : 1:다 대응관계 / 0… : optional / 0…* : 배열이면 이렇게 표시!
사용하지 않는 것이 좋다. Association과 비슷하기 때문
프로퍼티에 존재하는 값들과 컨테이너가 서로 다른 생명주기를 가질때
프로퍼티에 존재하는 값들과 컨테이너가 서로 생명주기가 같을 때!!
클래스 내에서 생성된 인스턴스가 클래스와 함께 생명주기를 같이 하는 경우(MainController - JuiceMaker)
얕은 복사의 경우 : 얕은 복사란 클래스의 인스턴스를 복사하지만 같은 주소를 바라보는 경우 → 구성관계라고 보기 힘들다.
깊은 복사의 경우 : 값 타입 복사를 한 경우 → 구성관계라고 할 수 있다.
- 사다리타기처럼 타고 내려오는 순서로 읽으면 된다.
-
단일 메시지에 대해서 조건을 명시할 수 있는 방법이다. 조건을 명시 -> [조건] 처리메시지
-
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 : 참조. 외부에서 정의된 시퀀스 다이어그램을 포함
- 전역에서 if 구문으로 구현 -> Person을 부르는 누군가가 존재해야한다.
예시 코드
if CoffeeMenu.americano.price <= person.money {
person.buy(.americano, at: coffeeShop)
} else {
print("잔액이 부족합니다.")
}
- 함수 내에서 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("잔액이 부족합니다.")
}
}
}
- 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)원 남음")
}
}