# 은행창구 매니저
## 프로젝트 소개 💰
> 은행을 방문한 고객들의 업무를 여러명의 은행원이 동시에 처리하도록 구현한 앱
>
> 프로젝트 기간: 2023.03.06 - 2023.03.17
## 목차 :book:
| <center>순서</center> |
|---|
| [팀원 👀](#팀원-👀) |
| [프로젝트 구조 🚧](#프로젝트-구조-🚧)|
| [타임라인 ⏰](#타임라인-⏰) |
| [실행화면 🎬](#실행화면-🎬) |
| [트러블슈팅 🚀](#트러블슈팅-🚀) |
| [Reference 📑](#Reference-📑) |
## 팀원 👀
|<center>[kokkilE](https://github.com/kokkilE)</center>| <center> [vetto](https://github.com/gzzjk159)</center> |
|--- | --- |
|<img width="200" src=https://i.imgur.com/4I8bNFT.png>|<img width="200" src=https://cdn.discordapp.com/attachments/535779947118329866/1055718870951940146/1671110054020-0.jpg> |
## 프로젝트 구조 🚧
<details> <summary><big>Class Diagram 🗺</big></summary>
<img src= "https://i.imgur.com/AweJ1PX.png" width=1000>
</details>
</br>
<details><summary><big>File Tree 🌲</big></summary>
```swift
BankManagerConsoleApp
├── BankManagerConsoleApp
│ ├── BankManager.swift
│ ├── Bank.swift
│ ├── BankClient.swift
│ ├── Banker.swift
│ ├── LinkedList.swift
│ ├── Node.swift
│ ├── Queue.swift
│ └── main.swift
└── QueueTests
└── QueueTests.swift
```
</details>
</br>
## 타임라인 ⏰
| <center>STEP | <center>날짜 | <center>타임라인 |
| ----- | -------------- | --- |
| STEP1 | **2023.03.06** | - Node, LinkedList 타입 구현 </br> - queue 구현 </br> - QueueTests 구현 |
| STEP2 | **2023.03.07** | - Bank, BankTeller, BankCustomer 구현 </br> - BankCustomer BankClient로 네이밍 수정 </br> - BankClient 타입 변경 </br> - BankTeller requiredtime 프로퍼티 추가 |
| STEP2 | **2023.03.08** | - Int, Double Extension 생성 </br> - NumberFormatter 적용 함수 생성 |
| STEP2 | **2023.03.10** | - BankTeller Banker로 네이밍 수정 </br> - 타입의 프로퍼티에 타입 명시 </br> - bank타입 변경 </br>- NumberFormatter 적용 삭제 |
</br>
## 실행화면 🎬
|<center>은행 개점 후 <br> 업무 처리</center>|<center>종료</center>|
| -- | -- |
|<img src="https://i.imgur.com/i6TDiV0.gif" width=300>|<img src="https://i.imgur.com/SQrlnjO.gif" width=300>|
</br>
## 트러블슈팅 🚀
### 1️⃣ Unit Test의 타겟 import 에러
UIApp 환경에서 테스트하던것과 마찬가지로 `@testable import`로 테스트 대상의 타겟을 `import`해서 시험하고자 했으나, 다음과 같은 에러가 발생했다.
<img src="https://i.imgur.com/7N4TEtM.png" width=600>
`BankManagerConsoleApp` 타겟을 인식하지 못하는 것으로 보여 타겟 설정에서 여러 시행착오를 해봤으나 결국 해결하지 못하고, 다음과 같이 테스트 대상 파일에서 Target Membership을 추가하는 방법으로 테스트했다.
<img src="https://i.imgur.com/hY2vjsj.png" width=180>
그러나 위 방법은 번거로울 뿐더러 같은 프로젝트 내에 있는 타겟을 인식하지 못하는것은 부자연스럽게 느껴져서, 해결 방법을 찾고 있다.
### 2️⃣ struct, class 타입
타입을 결정할 때 `상속이 필요한지`, `참조 타입의 identifier 특성이 필요한지`를 우선적으로 고려하여, `Node`를 제외한 모든 타입을 struct로 구현했다.
하지만 Bank 타입 내에서는 mutating이 자주 일어나서 프로퍼티의 CoW 장점이 희미해진다는 점을 고려했고,
``` swift
struct Bank {
private var banker: [Banker] = .init()
private var clientQueue: Queue<BankClient> = .init()
private var numberOfClient: Int = 0
mutating func openBank() { ... }
private mutating func setupClient() { ... }
private mutating func assignClientsToBankTeller() { ... }
private mutating func closeBank() { ... }
private func printClosingMessage() { ... }
private mutating func clearNumberOfClient() { ... }
}
```
BankManager 내 bank 프로퍼티가 variable 됨으로써 변경될 수 있는 점을 고려했다.
``` swift
struct BankManager {
// BankManager가 bank를 직접적으로 수정 가능하다.
private var bank: Bank = .init()
mutating func startBankManager() { ... }
private func printBankMenu() { ... }
}
}
```
위 두가지 이유로 bank타입을 struct에서 class로 수정하였다.
</br>
### NumberFormat vs String(format:)
총 걸린 시간의 소수점 둘째자리까지 출력하기 위해서 NumberFormatter랑 String(format:) 두 가지 방법을 고민하였다.
- NumberFormatter은 수가 커졌을 때 출력되는 수를 한 눈에 보기 편하다는 장점이 있었지만 수가 작으면 굳이 NumberFormatter를 사용할 이유가 없다는 것과 NumberFormatter가 호출되어 약간의 메모리 낭비가 있다는 단점이 있다.
- String(format:)은 비교적 간단한 로직으로 작성할 수 있는 장점이 있지만 큰 수를 표시하는데는 한 눈에 알아 보기 힘들다는 단점이 있다.
처음에는 큰 수까지 고려하여 NumberFormatter로 작성하였지만 이번 프로젝트에서 1000단위가 넘어가는 큰 수가 나오지 않는 점과 NumberFormatter를 사용할때 format이 실패했을 때를 대비해 바인딩을 해야한다는 점에서 NumberFormatter 사용을 없애고 String(format:)으로 코드를 수정하였다.
## Reference 📑
- [How do I unittest a command line application?](https://developer.apple.com/forums/thread/52211)
- [WWDC2016](https://developer.apple.com/videos/play/wwdc2016/416/)
- [choosing-between-structures-and-classes](https://developer.apple.com/documentation/swift/choosing-between-structures-and-classes#Use-Structures-When-You-Dont-Control-Identity)