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