---
# System prepended metadata

title: 2-1조 쥬스메이커 그라운드 룰

---

# 2-1조 쥬스메이커 그라운드 룰

## 리뷰어
- Gundy(건디)
<br>

## 팀원
- idinaloq (이디나로크)
- Hemg(햄지)

## 규칙
- 매일 아침 10시 30분에 모이기
- 늦기 30분전에 연락하기

<br>

## 짝프로그래밍 규칙
- 교대하기 전 자신이 작성한 코드 설명하고 다음 프로그래밍 방향 토의하기
- 
<br>

## 스크럼
- 금일 진행 사항 공유하기(오늘의 할일)
- 모르는 부분, 궁금한 부분 물어보기
<br>

## 프로젝트 규칙

### 브랜치 이름 규칙
- 공동 작업 브랜치의 경우: setp0, step1, step2...
- 개인 작업(테스트용) 브랜치의 경우: step0_name step1_name...

### 커밋 메시지 규칙
- 카르마 스타일 컨벤션 커밋메시지 
- TYPE: 설명 
- TYPE = feat, fix, docs, style, refactor, test, chore
### 트러블 슈팅 작성
- 해결할 때 어려웠던 부분이 있으면 별도의 브랜치를 만들거나 코드 내용 남겨놓기
- 
### 네이밍 컨벤션
- swift 공식 문서 참고
<br>




## 고민했던점
- 주스를 주문할때에 재고를 파악하고 부족시 에러 호출
- 이후 재고 감소 하는 방법에 대해서 고민을 했습니다.
- 간단하게? 쥬스 종류마다 함수를 만들어 진행을 할 수도 있지 었지만 너무 많은 함수 사용이 될꺼같아 하나의 함수로 처리 하기 위해서 고민을 했으면 최종적으로 에러를 던지는 함수와 재고를 체크하는 함수 2가지를 진행 하게되었습니다.
- 처음 함수 생성에 있어 하나의 함수에서 2개의 함수 역활이 같이 넣었으며 이후 함수분리 진행하여 완료 했습니다.
```swift
func removeFruit(_ juice: String) {
        switch juice {
        case "딸기주스":
            self.strawBerry -= 16
        case "바나나주스":
            self.banana -= 2
        case "키위주스":
            self.kiwi -= 3
        case "파인애플주스":
            self.pineApple -= 2
        case "딸바주스":
            self.strawBerry -= 10
            self.banana -= 1
        case "망고주스":
            self.mango -= 3
        case "망고키위주스":
            self.mango -= 2
            self.kiwi -= 1
        default:
            print("")
        }
    }
```

```swift
 private func checkFruitStock(_ juiceName: String) throws {
        switch juiceName {
        case "딸기주스":
            guard fruitStore.strawBerry > 16 else {
                throw FruitStoreError.countError
            }
        case "바나나주스":
            guard fruitStore.banana > 2 else {
                throw FruitStoreError.countError
            }
        case "키위주스":
            guard fruitStore.kiwi > 3 else {
                throw FruitStoreError.countError
            }
        case "파인애플주스":
            guard fruitStore.pineApple > 2 else {
                throw FruitStoreError.countError
            }
        case "딸바주스":
            guard fruitStore.strawBerry > 10, fruitStore.banana > 1 else {
                throw FruitStoreError.countError
            }
        case "망고주스":
            guard fruitStore.mango > 3 else {
                throw FruitStoreError.countError
            }
        case "망고키위주스":
            guard fruitStore.mango > 2, fruitStore.kiwi > 1 else {
                throw FruitStoreError.countError
            }
        default:
            print("없는 주스입니다.")
        }
    }
```



## 조언을 얻고 싶은 부분
```swift
func start(_ juiceName: String) {
        do {
            try makeJuice("딸기주스")
        } catch FruitStoreError.countError {
            print("재고가 부족합니다.")
        } catch {
            print(error)
        }
    }
    
    private func makeJuice(_ juiceName: String) throws {
        try checkFruitStock(juiceName)
        fruitStore.removeFruit(juiceName)
    }
    
```
- 현 상황 makeJuice의 함수 상황입니다. try를 진행하면 checkFruitStock 함수를 진행하여 아닐시 에러를 던지고 있는데요. 이부분 사용이 괜찮은지에 대해서 알고 싶습니다.

- 만약에 변형을 하게 된다면 아래와 같은 코드를 생각할수있을꺼같습니다. 그러나 지금 했던 코드와는 다르지 않을꺼 같다는 생각이 들어 조언을 듣고 싶습니다.
```swift
private func makeJuice(_ juiceName: String) {
    do {
        try checkFruitStock(juiceName)
        fruitStore.removeFruit(juiceName)
    } catch FruitStoreError.countError {
        print("재고가 부족합니다.")
    } catch {
        print(error)
    }
}
```

- 그리고 현재 JuiceMaker에서 checkFruitStock으로 재고를 검사하는데, 이 재고를 검사하는 부분이 FruitStore에 들어가는게 적절할지 알고 싶습니다.








### STPE1 피드백 코멘트
- 현재 리드미에 있는것 GroundRule 파일 생성 해서 이동하기
- 과일 수량 네이밍 -> 이런식으로 strawberryQuantity ??
- addStoredFruit(_ fruit: String, _ stock: Int) 네이밍 부터 해서 파라미터 명이 어색하다




## STEP2 PR
- 네비게이션 바 버튼으로 화면 전환 문제
```swift 
let changeStockViewController = changeStockViewController()
self.present(changeStockViewController, animated: true)
```
- 이렇게 기본적으로 뷰컨을 생성한 후에 화면 전환을 진행 했었습니다. 그러나 스토리보드에 만들어진것과는 다른 화면이 나타나서 고민을 하게 되었고 뷰컨을 생성한후에 접근하는것이 잘못됬으며 스토리보드에 접근해야하는것을 알게 되었습니다.
```swift 
  guard let changeStockViewController = self.storyboard?.instantiateViewController(withIdentifier: "ChangeStockViewController") else { return }
```
- 이렇게 하여 스토리보드ID에 맞는 화면에 접근 할 수 있었습니다.







## STEP2 코멘트

#### 이 ChangeStockViewController는 상속될 일이 있을까요?
- UIViewContorller를 상속받아서 UI화면을 구현하기 위해서 필요로 합니다. 버튼을 추가하여하며 화면전환을 진행하기 위해 UIViewContorller를 상속 받게 했습니다.

#### ViewController는 이 타입이 수행하는 일에 대한 적절한 네이밍이 아닌 것 같습니다.

- 또한 마찬가지로 상속될 일이 없다면 Preventing Overrides 해주는 것이 좋겠습니다.
- final 진행하여 상속 불가능하게 진행한다.


- 외부 에서 stock의 재고를 접근하여 수정할수있기때문에 그걸 방지하기 위해서 접근제어를 걸고 반환값을 받아서 활용할수있게 진행했습니다.


- push로 화면을 이동하게되면 네비게이션 도움을 받아 네비바가 보이지만 프레젠트로 화면을 추가할 경우에는 네비바가 나타지않아 루뜨뷰를 만들어서 네비바 도움을 받을수있도록 진행했씁니다.


싱글톤 이유?
- 명확하게 과일의 재고 값이 JuiceMaker, ChangeStockView 에서 같은 인스턴스를 사용하기도하며 재고값을 명확하게 표시하고 싶어서 사용했습니다. 
- `class` 타입은 꼭 싱글톤이 아니여도 된다고 생각하며 userName 같은 많은 화면에서 필요로 할때 쓰일꺼같습니다.














# 🥤🧃쥬스 메이커

## 📖 목차
1. [소개](#-소개)
2. [팀원](#-팀원)
3. [타임라인](#-타임라인)
4. [시각화된 프로젝트 구조](#-시각화된-프로젝트-구조)
5. [실행 화면](#-실행-화면)
6. [트러블 슈팅](#-트러블-슈팅)
7. [참고 링크](#-참고-링크)
8. [팀 회고](#-팀-회고)

---

## 🍀 소개

`idinaloq`와 `Hemg` 팀이 만든 쥬스 메이커 프로젝트 입니다.
- 쥬스메이커는 원하는 맛의 쥬스를 만들고, 해당하는 쥬스에 필요한 과일을 감소시키거나, 과일 재고를 증가시키는 기능을 가지고 있습니다. (STEP1)
- 주요 개념: `Initialization` ,  `Access Control`, `Nested Types` , `Type Casting` , `Error Handling`

---

## 👨‍💻 팀원

| idinaloq | Hemg |
| :---: | :---: |
| <Img src = "https://user-images.githubusercontent.com/109963294/235301015-b81055d2-8618-433c-b680-58b6a38047d9.png" width = "250" height="300"/> | <Img src="https://user-images.githubusercontent.com/101572902/235090676-acefc28d-a358-486b-b9a6-f9c84c52ae9c.jpeg" width="250" height="300"> |
|[Github Profile](https://github.com/idinaloq) |[Github Profile](https://github.com/hemg2)|


---

## 👀 시각화된 프로젝트 구조

| 쥬스메이커 |
|:--:|
추후 추가 예정입니다.




## 💻 실행 화면

|쥬스 주문 | | 
|:--:|:--:|
||
아직 실행화면이없어 추후 추가 예정입니다.

---


## ⏰ 타임라인

| 날짜 | 내용 |
| --- | --- |
| 2023.05.08. | 팀 룰, 쥬스메이커 구현 고민 |
| 2023.05.09. | PR진행 및 PR 대한 피드백 반영 추가 피드백 진행 |
| 2023.05.10. | PR 대한 피드백 반영 |
| 2023.05.11. | PR진행 및 PR 대한 피드백 반영 |
| 2023.05.12. | 피드백 코멘트 작성 및 README 작성 |

---

# 트러블 슈팅

## 저장 프로퍼티의 활용성
- 기존 과일 재고에 대해 저장 하기 위해 저장 프로퍼티를 사용하여 하나의 저장 프로퍼티에 하나의 값을 저장 하여 진행 했었는데 이부분에 있어 조금더 효율적으로 진행하고자 하여 Int -> Dictionary로 변경하여 재고를 저장 하게 되었습니다.
```swift 
class FruitStore {
var strawBerry = 10
var banana = 10
var pineApple = 10
var kiwi = 10
var mango = 10
}
```

```swift
 var stock: [Fruit: Int] = [
        .strawBerry: 10,
        .banana: 10,
        .pineApple: 10,
        .kiwi: 10,
        .mango: 10
    ]
```


## 타입변경
- 기존 Juice 타입에서 Juice 주문시에 주문에 맞게 재고를 깍는 개념으로 decreaseStock() 를 실행 시키는 함수였습니다. 하지만 이렇게하게 되면 FruitStore에서 Juice까지 알아야 하기에 문제점이 발생 할 수있기에 타입을 변경 했어야 했습니다.
```swift
func decreaseStock(with juice: Juice) {
        let recipe: [Fruit: Int] = juice.recipe
        for (fruit, quantity) in recipe {
            if let stock = self.stock[fruit] {
                self.stock[fruit] = stock - quantity
            }
        }
    }
```
- 기존 Juice 타입에서 -> Fruit 타입으로 변경 하여 decreaseStock() 함수를 재구현 했습니다.

```swift
 func decreaseStock(with fruits: [Fruit: Int]) {
        for (fruit, quantity) in fruits {
            if let stock = self.stock[fruit] {
                self.stock[fruit] = stock - quantity
            }
        }
    }
```

---

## 📚 참고 링크

- [🍎Apple Docs: Initialization](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization//)
- [🍎Apple Docs: Access Control](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/accesscontrol/)
- [🍎Apple Docs: Nested Types](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/nestedtypes/)
- [🍎Apple Docs: Type Casting](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/typecasting/)
- [🍎Apple Docs: Error Handling](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling/)
- [🍎Apple Docs: API Design Guidelines](https://www.swift.org/documentation/api-design-guidelines/)
---

# 팀 회고
- 프로젝트 종료시에 추가 진행예정 입니다.
## 우리팀이 잘한 점
- 
## 우리팀 개선할 점
- 
## 서로에게 좋았던 점 피드백
- 
## 서로에게 아쉬웠던 점 피드백
- 