오늘은 급하게 만드느라 따로 클래스를 분리해서 만들었던 RowStack에 대한 리팩터링을 진행했다.
기존 코드는 계산기의 마지막 행이 다른 행과 달리 버튼이 3개만 존재해야 하면서 문제가 생겼다.
처음엔 3개의 버튼을 처리하는 Stack을 따로 만든다는 것뿐이었다.
그러나 StakcView를 생성하는 클래스가 2개가 되자 하나의 반복문으로 처리할 수 없게 되었다.
3개의 버튼 타이틀을 담은 변수도 따로 선언해야 했고, 각 스택에 존재하는 버튼 배열에 대한 다형성을 해서 프로토콜도 만들어야 했다.
처음 클래스를 나누어 만들 땐 이렇게 코드를 복잡하게 만들 일이 될 거란 생각을 못했다.
이번 코드 덕분에 무조건 기능별로 클래스를 나누는 것이 옳은 게 아님을 깨닫게 되었다.
미래에도 거의 없을 재사용성을 위하기보다 4버튼과 3버튼을 하나의 클래스가 책임지는 것이 훨씬 나은 코드라 생각한다.
class MainStack: UIStackView {
/*
4버튼, 3버튼의 변수가 따로 정의되어있다.
리팩터링 후 합쳐지긴 했으나 나중엔 버튼 타이틀을 관리하는 열거형에서
메서드로 배열을 반환받도록 수정해야 한다.*/
private let buttonsArr: [[String]] = [
["C", "±", "%", "÷"],
["1", "2", "3", "+"],
["4", "5", "6", "-"],
["7", "8", "9", "×"],
]
private let zeroRowButtons: [String] = ["0", ".", "="]
//스택 생성 클래스가 나뉘어졌기 때문에 하나로 묶어줄 프로토콜이 필요했다.
private(set) var rows: [ButtonStackProtocol] = []
(...)
private func setButtonRow(buttonsArr: [[String]]){
for buttons in buttonsArr {
let buttonRow = RowStack(buttonTitle: buttons)
rows.append(buttonRow)
addArrangedSubview(buttonRow)
}
//반복문에서 끝나지 않고 추가로 중복되는 코드가 필요했다.
let zeroRow = ZeroRowStack(titles: zeroRowButtons)
rows.append(zeroRow)
addArrangedSubview(zeroRow)
}
}
선언되었던 2개의 스택뷰 클래스는 코드의 80%가 중복되었고 단순히 3개인 경우 레이아웃을 추가로 설정해주는 부분만이 달랐다.
때문에 두 클래스를 하나로 병합하는 과정은 정말 빠르게 끝났다.
private func setButtons(titles: [String]) {
for title in titles {
let button = CircleButton(title: title, alpha: buttonAlpha)
buttons.append(button)
addArrangedSubview(button)
}
if titles.count == 3 {
self.setThreeButtonsLayout(buttons: self.buttons)
}
}
private func setThreeButtonsLayout(buttons: [UIButton]) {
NSLayoutConstraint.activate(
buttons.enumerated().map { index, button in
button.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: index == 0 ? 0.5 : 0.25, constant: (-1 * spacingSize * (index == 0 ? 0.5 : 0.75))
)
}
)
}
위 코드에서 보듯 그냥 3버튼인 경우의 레이아웃 설정만 따로 해주면 되었다.
(3,4개의 버튼이 아닌 경우의 에러처리도 추가해야 하지만,,)
그래도 이번에 고민없이 나눠버린 클래스가 문제를 발생시켰기에
다음 프로젝트부터는 클래스 분리에 대해서도 더 고민해볼 수 있게 되었다.
파일 3개가 1개로 줄어들었다!!
진자 집념바