State 관리 관련된 질문 입니다

Intro App Dev 21 Final Project

Rock, Paper, Sissors 코드는 아래와 같습니다.

var current_status:GameState = .start 라 해 놓고

initiateElement() 에서
current_status = .start
gameStateLabel.text = current_status.description

라고 관리하고

func play() 안에서는 gameResult 를 이용해서 state 관리하는게 좋은 코드 같지 않습니다.

State 관리 어떻게 하는 게 좋은 코드인가요?
Swift의 특징을 잘 살리는 법?

//
//  ViewController.swift
//  RPS
//
//  Created by sel2 on 2021/03/14.
//

import UIKit

class ViewController: UIViewController {


@IBOutlet weak var robotsDecisionLabel: UILabel!
@IBOutlet weak var gameStateLabel: UILabel!

@IBOutlet weak var rockBtn: UIButton!
@IBOutlet weak var sissorsBtn: UIButton!
@IBOutlet weak var paperBtn: UIButton!
@IBOutlet weak var playAgainBtn: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    initiateElement()
}

var current_status:GameState = .start

func initiateElement() {
    robotsDecisionLabel.text = "🤖"
    
    current_status = .start
    gameStateLabel.text = current_status.description //디버깅 중...
    rockBtn.isHidden = false
    sissorsBtn.isHidden = false
    paperBtn.isHidden = false
    rockBtn.isEnabled = true
    sissorsBtn.isEnabled = true
    paperBtn.isEnabled = true
    playAgainBtn.isHidden = true
}

func play(_ userTurn: Sign) {
    rockBtn.isEnabled = false
    sissorsBtn.isEnabled = false
    paperBtn.isEnabled = false
    let opponent_value = randomSign()
    robotsDecisionLabel.text = opponent_value.emoji
    let gameResult = userTurn.match(opponent_value)
    gameStateLabel.text = gameResult.description
    playAgainBtn.isHidden = false
    
    switch userTurn {
    case .rock:
        rockBtn.isHidden = false
        sissorsBtn.isHidden = true
        paperBtn.isHidden = true
    case .sissors:
        rockBtn.isHidden = true
        sissorsBtn.isHidden = false
        paperBtn.isHidden = true
    case .paper:
        rockBtn.isHidden = true
        sissorsBtn.isHidden = true
        paperBtn.isHidden = false
    }
}

@IBAction func rockSelected(_ sender: Any) {
    play(Sign.rock)
}

@IBAction func sissorsSelected(_ sender: Any) {
    play(Sign.sissors)
}

@IBAction func paperSelected(_ sender: Any) {
    play(Sign.paper)
}

@IBAction func playAgain(_ sender: Any) {
    initiateElement()
}
}
좋아요 1

샘플 코드를 살펴봐야 하는 주제라서 답글을 미뤄뒀는데, 글 쓰는데 생각보다 더 오래걸렸네요.

위 코드에서, GameState enum은 start, win, lose, draw 값을 가지고,
userTurn.match() 함수는 GameState를 리턴합니다.

코드를 살펴보니, sel 2 님의 생각하신 게 맞습니다.
그래서 var current_status 를 이미 만들어 놓고
userTurn.match() 함수의 결과를 current_status 로 바로 받지 않고 gameResult 라는 걸로 받아서 사용할 필요가 없어요.

그래서, var current_status:GameState = .start 부분은 없애는 게 좋은 코드일 듯 합니다.

참고로, Swift 는 함수형으로 사용할 수 있는 언어이고
함수형 코드는 상태값을 저장하지 않고, 기능의 연결로 문제를 해결하는 걸 좋은 코드로 보고 있습니다.

그래서 가능한 상태 저장을 하지 않는 방향으로 코딩을 하시고 ,
어쩔 수 없이 상태 저장을 한다면, var가 아닌 let을 쓰는 것을 추천드립니다.

하지만 저도 OOP 세대라… 쉽지가 않네요. :stuck_out_tongue_closed_eyes:

좋아요 1

답변 감사합니다.

Swift 에서 좋은 코딩 습관을 기르기 위해 참조할 만한 블로그 추천 좀 부탁 드립니다.

좋아요 1

위 동영상에서 설명한 책이 함수형으로 Swift 를 사용하는 데 도움이 됩니다.

링크를 누르면 책 설명 부로 바로 가도록 되어 있어요.