안녕하세요 라자냐 @wonhee009
**탑킴, 허황** 입니다😊
STEP 1 구현이 끝나 PR 드립니다😁
잘 부탁드립니다🤩
### STEP 1 UML

### 구현 내용
- 과일의 종류를 표현하는 FruitType 타입 정의
- 딸기, 바나나, 파인애플, 키위, 망고
- 과일의 재고를 관리하는 FruitStore 타입 정의
- 각 과일의 초기 재고 : 10개
- 각 과일의 수량 n개를 변경하는 기능
- 과일 쥬스를 제조하는 JuiceRecipes 타입 정의
- 딸기쥬스 : 딸기 16개 소모
- 바나나쥬스 : 바나나 2개 소모
- 키위쥬스 : 키위 3개 소모
- 파인애플 쥬스 : 파인애플 2개 소모
- 딸바쥬스 : 딸기 10개 + 바나나 1개 소모
- 망고 쥬스 : 망고 3개 소모
- 망고키위 쥬스 : 망고 2개 + 키위 1개 소모
- FruitStore 과일을 사용해 과일쥬스를 제조하는 JuiceMaker 타입 정의
- 과일의 재고가 부족하면 과일쥬스를 제조 불가
### 고민했던 점
- 확장에 용의한 코드
> 쥬스의 종류를 구현할 때 처음에는 열거형으로 구현했지만, 나중에 쥬스가 추가 될 경우 열거형을 수정해야하기 때문에 쥬스 별로 RecipeProtocol 프로토콜을 채택한 struct를 구현했습니다.
> struct로 구현할 경우 쥬스가 추가될 때마다 새로운 쥬스 타입을 생성해주면 되기 때문에 확장에 용의한 코드라 판단하고 진행했습니다.
> 라자냐의 생각이 궁금합니다🧐
- FruitStore 타입 struct VS class
> struct로 구현 할 경우 immutable하게 값을 사용 할 수 있을 것이라 판단하여, 진행 하였으나, 테스트 코드 작성 시 이로 인해 오히려 혼선이 생기게 되어 class로 전환 하게 되었습니다.

### 조언을 얻고 싶은 부분
- 테스트 파일의 위치
> Unit Test를 진행할 때 Tests 타겟을 추가하고 그 하위에 Unit Test 파일을 생성해서 사용하게 되는데 Unit Test 파일과 프로덕션 코드가 한 그룹에 있는게 어떤 프로덕션 코드가 테스트 진행되었는지 명확하게 알 수 있는 것 같습니다.
> Unit test 파일을 위 상황 같이 배치해도 괜찮을까요??
> 배치하게 된다면 Tests 타겟은 추가하지 않고 Unit test 파일만 생성해서 테스트를 진행해도 괜찮은지 궁금합니다🧐
> 예시) 킥스타터 github 참고 이미지 [링크](https://github.com/kickstarter/ios-oss/tree/main/Kickstarter-iOS/DataSources)
> 
- 문서화 주석
> 함수의 로직을 문서화 주석으로 남겨도 괜찮은지 궁금합니다🧐
> 부연설명 드리자면 과일의 개수가 부족한지 확인하는 메서드 내부에서 Dictionary 메서드 중 [merging](https://developer.apple.com/documentation/swift/dictionary/3127173-merging)을 사용했습니다.
> merging을 사용해서 두 딕셔너리의 value의 차이를 구하고
> filter를 이용해서 value가 음수인 key의 개수를 구하고
> value가 음수인 key의 개수가 0보다 크다면 .failure를 반환
> 하게 구현했는데 이러한 로직은 코드를 보고 파악하는 것 보다 문서화 주석을 사용하는게 다른 사람이나, 본인이 봤을 때 코드를 파악하기 수월하겠다고 생각했습니다.
- Result 타입 캐스팅
> Result<Void, Error> <-> Result<Void, CustomError> 사이의 캐스팅이 불가능 한 이유가 궁금 합니다.
> CustomError는 Error 프로토콜을 채택 하고 있습니다.
> 오류 문구 : Cannot convert return expression of type 'Result<Void, CustomError>' to return type 'Result<Void, Error>'
--------------------
## 리뷰 답변
### 확장에 용이한 코드
해당 부분은 확장보다는 유지보수 면에서 좀 더 의미가 있지 않나?라는 생각이 들었습니다.
주스가 추가 되었을때 열거형을 수정(케이스 추가)하는 부분이나 주스 struct를 추가하는 부분이나 저는 비용이 비슷한거 같거든요.
물론, 주스별로 뭔가 다른 기능이 추가되는거라면 확장면에서는 좀 더 좋은 코드라고 생각합니다.
그럼 과일에 대해서는 열거형을 채택하신 이유는 무엇일까용?.?🤔
> 코드에 통일성을 유지하려면 과일도 별도의 타입으로 생성하는게 맞다고 판단됩니다😭
> 라자냐께서 말씀해주신 과일도 별도의 타입으로 생성할 고민해봤지만,
> 열거형을 사용하게되면 FruitStore 타입의 Inventory 프로퍼티의 타입이 [FruitType: Int]을 사용하기 때문에 과일의 초기수량을 넣어줄 때 `CaseIterable`를 채택한 열거형을 사용하면 간편하게 초기수량을 넣어줄 수 있다고 판단해서 열거형을 사용했습니다.
### Result 타입 캐스팅
현재 FruitStoreError에서는 Error를 채택하지 않는거로 보이는데용?.?
> FruitStoreError는 LocalizedError를 채택하며 이는 Error를 상속 받습니다.
> JuiceMaker의 make 함수를 소스 1과 같이 작성하고 싶었는데요.
> 캐스팅이 안되는 문제로 소스 2와 같이 작성되었습니다. 이유가 무엇일까요?
소스 1
```swift=
mutating func make(with recipe: RecipeProtocol) -> Result<Void, Error> {
return fruitStore.use(of: recipe.items) // return type Result<Void, FruitStoreError>
}
```
소스 2
```swift=
mutating func make(with recipe: RecipeProtocol) -> Result<Void, Error> {
let result = fruitStore.use(of: recipe.items)
switch result {
case .success():
return .success(Void())
case .failure(let error):
return .failure(error)
}
}
```
의존성을 줄이고 테스트가 쉬운 구조를 만들기 위해 작성 했습니다.
예를 들면 FruitStoreMock을 주입하는 경우 입니다.