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