## ๐๏ธ ํ๋ก์ ํธ ํ์ผ ๊ตฌ์กฐ
enum | ์ญํ |
---|---|
Operator | Character , CalculateItem , CaseIterable ์ ์ฑํํ์๊ณ , ๊ฐ ์ฐ์ฐ์ case ๋ฐ ๊ฐ ์ฐ์ฐ์๊ฐ ๋ค์ด์์ ๋ ๊ทธ์ ๋ง๋ ์ฐ์ฐ์ ํ ์ ์๋๋ก calculate ๋ฉ์๋๋ฅผ ์ ์ |
ExpressionParser | String ํํ์ ์ซ์ ๋ฐฐ์ด์ ๋ฐํํ๋ componentsByOperators ์ ์ฐ์ฐ์ ๋ฐฐ์ด์ ๋ฐํํ๋ extractOperators ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ input ๊ฐ์ ํ์ฑํ๊ณ , ๊ทธ ๊ฐ์ ํตํด Formula ๋ฅผ ๊ตฌ์ฑํ์ฌ ๋ฐํํ๋ ๊ธฐ๋ฅ |
struct | ์ญํ |
---|---|
Formula | Double ํ์
์ CalculateItemQueue ๋ฅผ ๊ฐ๋ operands์ Operator ํ์
์ CalculateItemQueue ๋ฅผ ๊ฐ๋ operators๋ฅผ ํ๋กํผํฐ๋ก ์ผ์ ๊ตฌ์กฐ์ฒด. result ๋ฉ์๋๋ฅผ ํตํด ๊ฐ ItemQueue์์ ๊ฐ์ dequeueํ์ฌ ๊ฒฐ๊ณผ๊ฐ์ Double๋ก ๋ฐํ |
CalculatorItemQueue | ์ ๋ค๋ฆญ ํ์ ์ ๋ฐฐ์ด์ queue๋ก ๊ฐ์ง๋ฉฐ, ์ธ์๋ก ๋ฐ์ ์ด๋ ํ ํ์ ์ ๋ฐฐ์ด๋ init์์ enqueue ๊ณผ์ ์ ํตํด ํด๋น ํ์ ์ queue๋ฅผ ์์ฑ. queue์ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋ฅ์ธ enqueue์ dequeue, ๊ทธ๋ฆฌ๊ณ ํ๋ฅผ ๋น์ฐ๋ allClear ๋ฉ์๋๋ฅผ ํฌํจ |
protocol | ์ญํ |
---|---|
CalculateItem | Operator , Double ์์ CalculateItem ๋ฅผ ์ฑํํ์ฌ CalculateItemQueue์ ์์๋ก ์ฌ์ฉ๋ ์ ์๋๋ก ์์ฑ |
extension | ์ญํ |
---|---|
Operator | ์ฐ์ฐ์๋ฅผ ์ด๊ฑฐํ์ผ๋ก ์ ์. calculate ๋ฉ์๋์์ private ํ์ ์ add, substract, divide, multiply ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ๊ตฌํ. ์๋ํ๋ ์ฐ์ฐ ๋ฉ์๋๋ค์ ์ด๋ฆ๊ณผ ๋์ผํ ๊ณ์ฐํด์ Double๊ฐ์ผ๋ก ๋ฐํ |
Double | CalculateItemQueue ์ ์์๋ก ์ฌ์ฉ๋๋๋ก CalculateItem ์ ์ฑํ |
function | ์ญํ |
---|---|
allClear | ์ ๋ ฅ๋ฐ์๋ ๋ด์ฉ๋ค์ ์ด๊ธฐํ |
clearEntry | ์
๋ ฅ๋ฐ์ ์ซ์ ํน์ ์์์ ์ ์ ๊ฑฐ (๋จ, ๊ฒฐ๊ณผ๊ฐ์ ์ญ์ ๋ถ๊ฐ) |
changeSign | ์ ๋ ฅ๋ฐ์ ์ซ์์ ๋ถํธ๋ฅผ ๋ณ๊ฒฝ, ์์๋ผ๋ฉด ์์๋ก ๋ณํ์ ํ๊ณ ์์๋ผ๋ฉด ์์๋ก ๋ณํ |
addDecimalPoint | ์
๋ ฅ๋ฐ์ ์ซ์์ ์์์ ์ ๋ถ์ฌ (๋จ, ์ด๋ฏธ ์ ๋ ฅ๋ฐ์๋ค๋ฉด ์ ๋ ฅ ๋ถ๊ฐ) |
addOperand | ๊ณ์ฐํ๊ณ ์ ํ๋ ์ซ์๋ฅผ ์ ๋ ฅ |
addOperator | ๊ณ์ฐํ๊ณ ์ ํ๋ ์ฐ์ฐ์๋ฅผ ์ ๋ ฅ, ์ซ์๋ฅผ ์ ๋ ฅ๋ฐ์ ์ํ๊ฐ ์๋๋ผ๋ฉด ๊ธฐ์กด์ ์ฐ์ฐ์๋ฅผ ๋ณ๊ฒฝ |
calculateResult | ๊ณ์ฐ์ ํ๊ณ ์ ์ถ๊ฐํ ์๋ค์ ๊ณ์ฐํ์ฌ ๋ฐํ |
addFormulaStackView | ์
๋ ฅ๋ operand ์ operator ๋ก UILabel ์ ์์ฑํ๊ณ , Stack์ addArrangedSubView ๋ฅผ ํตํด ๋ด์ ํ ScrollView ์์ ๋ณผ ์ ์๋๋ก ์ถ๊ฐ |
formattingNumber | NumberFormatter() ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํจ์๋ก, formatter ์ค์ ์ ํตํด ์์์ ์๋ฆฌ์ 20, numberStyle = .decimal ์ ํตํด ์ฒ๋จ์ ๊ตฌ๋ถ ํ์๋ฅผ ํ ์ ์๋๋ก ํจ |
convertOperand | ์ ์๋ถ๋ฅผ ์ฒ๋จ์ ๊ตฌ๋ถ ํ์ ํ๋ฉด์ ์์๋ถ๊ฐ '0'์ด๋ '00'์ด์ด๋ ๊ฐ์ด ํ๋ฉด์ ๋ณด์ผ ์ ์๋๋ก operand๋ฅผ ์ ์๋ถ์ ์์๋ถ๋ก ๋๋์ด ์ ์๋ถ๋ Formatting ์งํ, ์์๋ถ๋ ๊ทธ ๊ฒฐ๊ณผ์ ๋ง๋ถ์ด๋ ์์ผ๋ก operand๋ฅผ convert |
isInitialOperand | enteredOperand๊ฐ ์ด๊ธฐ๊ฐ์ธ '0'์ธ์ง ํ์ธ |
PR #13 | Step1 - Queue ํ์ ๊ตฌํ
- Queueํ์ ์ผ๋ก ๊ตฌํ์ ํ๊ธฐ ์ํด์ enqueue, dequeue๋ฅผ ํ์ ๊ตฌํ
- Queue์ ์์์์ ์ฌ์ฉ๋ ํ์ ์ CalculateItem์ผ๋ก ์ฑํ
PR #21 | Step2 - ๊ณ์ฐ ํ์ ๋ฐ ์ฃผ๋ณ ํ์ ๊ตฌํ
- UML์ ๋ง๊ฒ ๊ฐ ๊ตฌ์ฑ์์ ๊ตฌํ
- CalculateItem ํ๋กํ ์ฝ์ ์ฑํํ๋
extension Double
,Enum Operator
๊ตฌํ - input๊ฐ์ ํ์ฑํ๋ ์ญํ ์
parse
์, ์ซ์์ ์ฐ์ฐ์ ๋ฐฐ์ด์ ๋ฐํํcomponentsByOperators
,extractOperators
๊ตฌํ - ๋ ๊ฐ์
CalculateItemQueue
๋ฅผ ๊ฐ๋struct Formula
๊ตฌํ
- CalculateItem ํ๋กํ ์ฝ์ ์ฑํํ๋
- ์ฌ์ฉ์์ ํฐ์น ์ด๋ฒคํธ๋ฅผ ์์ ํ์ฌ ๊ทธ ์ด๋ฒคํธ๋ก ๋ฐ์ํ๋ ์ซ์์ ์ฐ์ฐ์์ ์ฐ์ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ด๊ธฐ ์ํด ๊ฐ ๋ฒํผ์ ์ฐ๊ฒฐํ๊ณ , ํฐ์น ์ด๋ฒคํธ ์์ ์ ์คํํ ๊ธฐ๋ฅ์ ์์ฑํ์์ต๋๋ค.
์ ๋ ฅ๋ ๋ด์ฉ์ ๊ฒฐ๊ณผ๊ฐ ์์ชฝ ๊ณต๊ฐ์ ์คํฌ๋กค์ด ๊ฐ๋ฅํ๋๋ก stack์ฒ๋ฆฌํ์๊ณ , ๊ทธ ๋ด์ญ์ด ์๋จ ๊ณต๊ฐ์ ๋์ด ์ด์ด์ง๋ ๊ฒฝ์ฐ์๋ ์คํฌ๋กค์ด ํ๋จ์ผ๋ก ์๋์ผ๋ก ์ด๋ํ์ฌ ์ต๊ทผ ๋ด์ญ์ ๋ณผ ์ ์๋๋ก ํ์์ต๋๋ค.
์ ๋ค๋ฆญ ํ์์ ํจ์๋ ํจ์ ์ด๋ฆ ๋ค์ ๊บฝ์ ๊ดํธ์์ ์๋ฆฌ ํ์์ ํ์(the placeholder type name) <T>
๊ฐ ๋ค์ด์ต๋๋ค.
func makeQueue<T>(from elements: Array<T>) -> CalculateItemQueue<T> {
ํจ์์ ์ ๋ค๋ฆญ ๋ฒ์ ์์๋ ์ค์ ํ์ ์ด๋ฆ(์: Int
, String
๋๋ Double
) ๋์ ์๋ฆฌ ํ์์ ํ์ ์ด๋ฆ(์ด ๊ฒฝ์ฐ T
๋ผ๊ณ ํจ)์ ์ฌ์ฉํฉ๋๋ค. ์๋ฆฌ ํ์์ ์ ํ ์ด๋ฆ์ T๊ฐ ๋ฌด์์ด์ด์ผ ํ๋์ง์ ๋ํด ์๋ฌด ๋ง๋ ํ์ง ์์ง๋ง T
๊ฐ ๋ํ๋ด๋ ๊ฒ์ด ๋ฌด์์ด๋ a
์ b
๋ชจ๋ ๋์ผํ ์ ํ T
์ฌ์ผ ํ๋ค๊ณ ๋งํฉ๋๋ค
์ฐธ๊ณ : ๊ณต์ ๋ฌธ์
Type Methods
์ค์ Object๋ฅผ ์์ฑํ ํ์ ์์ด ๋ด๋ถ์ (ํ๋กํผํฐ), ๋ฉ์๋์ ์ ๊ทผํ๊ธฐ ์ํด์ ์ฌ์ฉ
enum ExpressionParser {
static func parse(from input: String) -> Formula {
// ...
let operatorQueue: CalculateItemQueue<Operator> = makeQueue(from: operators)
}
static func makeQueue<T>(from elements: Array<T>) -> CalculateItemQueue<T> {
// ...
}
}
ExpressionParser.parse(from: "+13-7+12*5+9")
ํ์ ๋ฉ์๋์ ๋ณธ๋ฌธ ๋ด์์ ์ฌ์ฉํ๋ ์ ๊ทํ๋์ง ์์ ๋ฉ์๋ ๋ฐ ์์ฑ ์ด๋ฆ์ ๋ค๋ฅธ ํ์ ์์ค ๋ฉ์๋ ๋ฐ ์์ฑ์ ์ฐธ์กฐํฉ๋๋ค. ํ์ ๋ฉ์๋๋ ํ์ ์ด๋ฆ์ ์ ๋์ฌ๋ก ์ถ๊ฐํ ํ์ ์์ด ๋ค๋ฅธ ํ์ ๋ฉ์๋์ ์ด๋ฆ์ผ๋ก ๋ค๋ฅธ ํ์ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ๊ตฌ์กฐ ๋ฐ ์ด๊ฑฐํ์ ํ์ ๋ฉ์๋๋ ํ์ ์ด๋ฆ ์ ๋์ฌ ์์ด ํ์ ์์ฑ์ ์ด๋ฆ์ ์ฌ์ฉํ์ฌ ํ์ ์์ฑ์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
์ฐธ๊ณ : ๊ณต์ ๋ฌธ์
์ํ์ค์ ๊ฐ ์์๋ก ์ง์ ๋ ๋ณํ์์ nil
์ด ์๋ ๊ฒฐ๊ณผ์ ๋ฐฐ์ด์ ๋ฐํํ๋ compactMap์ ์ด์ฉํด์ ๊ฐ๋ตํด์ง ์ฝ๋๋ก Double ํ์
์ ๊ฐ๋ค์ ์ป์ ์ ์์์ต๋๋ค.
let splittedStringArray = "+13-7+12*5+9".components(separatedBy: "+-*/")
let doubleArray= splittedStringArray.compactMap { Double($0) }
์ฐธ๊ณ : ๊ณต์ ๋ฌธ์
๊ฒ์ ์์ ์ ์ฌ์ฉํ ์ ๋์ฝ๋ ๋ฌธ์ ๊ฐ ์ธํธ. ๋ณธ ํ๋ก์ ํธ์์๋ String ๋ด์์ Operator Character๋ฅผ CharacterSet์ผ๋ก ๋ง๋ค์ด ๊ฒ์์์ ์ ์งํํ์ต๋๋ค.
static func componentsByOperators(from input: String) -> [String] {
let operators: String = String(Operator.allCases.map { $0.rawValue })
let operatorSet: CharacterSet = CharacterSet(charactersIn: operators)
return input.components(separatedBy: operatorSet)
}
์ฐธ๊ณ : ๊ณต์ ๋ฌธ์
์คํฌ๋กค ๋ทฐ ๊ตฌ์กฐ๋ฅผ ๋ณด๋ ์ฐ์ฐ๋ด์ญ์ด ๋ด๊ธด ์คํ๋ค์ ๋ด์ ์คํ์ด ์๋ ๊ตฌ์กฐ์ฌ์ (ScrollView > StackView > StackView/StackView) ๊ทธ ๊ตฌ์กฐ์ ๋ง๊ฒ ์ฐ์ฐ์์ ์ซ์๋ฅผ ๋ด์ Label์ ์์ฑํ ํ, StackView์ ๋ด์ ์ฐ์ฐ๋ด์ญ์ด ๋ด๊ธด ์คํ๋ค์ ๋ด์ ์คํ์ ์ถ๊ฐํ๋ ๋ฐฉ์์ ์ฌ์ฉํ์ต๋๋ค.
private func addFormulaStackView(`operator`: String, operand: String) {
let formulaStackView = UIStackView()
let enteredOperatorLabel = UILabel()
let enteredOperandLabel = UILabel()
//...
formulaStackView.addArrangedSubview(enteredOperatorLabel)
formulaStackView.addArrangedSubview(enteredOperandLabel)
formulaStackViews.addArrangedSubview(formulaStackView)
}
์ฐธ๊ณ 1 : ๊ณต์ ๋ฌธ์ ์ฐธ๊ณ 2 : ๊ณต์ ๋ฌธ์
์์์ ์๋ 20์๋ฆฌ ํ์, ์ ์๋ถ ์ฒ๋จ์ ํ์๋ฅผ ์ํด NumberFormatter
๋ฅผ ์ด์ฉํ์์ต๋๋ค.
numberStyle = .decimal
์ ํตํด ์ฒ๋จ์ ํ์๋ฅผ ํ ์ ์์๊ณ , maximumFractionDigits = 20
์ ํตํด ์ต๋ ์์์ ์๋ฆฌ๋ฅผ 20์ผ๋ก ์ค์ ํ ์ ์์์ต๋๋ค.
private func formattingNumber(_ number: String) -> String {
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 20
formatter.numberStyle = .decimal
return formatter.string(for: Double(number)) ?? number
}
์ฐธ๊ณ : ๊ณต์ ๋ฌธ์
- [Step 1] ์ ๋ํ
์คํธ ์
XCTAssertEqual
์ ์ฌ์ฉํ ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ queue์ ๋ค์ด๊ฐ๋ Item์Equatable
ํ๋กํ ์ฝ์ ์ฑํํ์ฌ ํด๊ฒฐํ์์ต๋๋ค - [Step 1] Unit Test๋ฅผ ์งํํ๋ฉด์ dequeue๋ฅผ ์ฌ์ฉํ๋ฉด
isEmpty
๊ฐ false์ธ ์ํฉ์์๋ ๋ฌธ์ ๊ฐ ๋์ง ์์ง๋ง true์ผ ๋๋ warning์ด ๋ฐ์ํ์ฌ @discardableResult๋ฅผ ์ฌ์ฉํ์ฌ ํด๊ฒฐํ์์ต๋๋ค. - [Step 2] UML์์ ์๊ตฌํ split์์๋ Character๋ฅผ target์ผ๋ก ํ๊ธฐ์๋ ์ํ๋ ๊ฒฐ๊ณผ๊ฐ ๋์ค์ง ์์
components(separatedBy: CharacterSet)
๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ๋ถ์์ ๋ง์ถฐ ๋ฌธ์์ด๋ก ๋ฐํํ์์ต๋๋ค. - [Step 3] AC์ ๋ฒํผ์ ๊ฒฝ์ฐ, scrollView๋ด์ ์กด์ฌํ๋ subViews์ ๊ฐ์ฒด๋ค์ ์ญ์ ํ๊ธฐ ์ํด์
removeArrangedSubview
์ ์ฌ์ฉํ์์ผ๋ ์ญ์ ๋์ง ์์์ต๋๋ค. ํด๊ฒฐํ๊ธฐ ์ํด์removeFromSuperview
๋ ์ฌ์ฉ์ ํ์ฌ์ ๋ด๋ถ์ ์กด์ฌํ๋ subViews๋ฅผ ์ญ์ ํ์์ต๋๋ค.