Lucas P.
Lucas P.

Reputation: 4532

Computed or Stored Property?

So, I'm porting my Android app to iOS and I'm getting my feet wet with Swift (3).

I understand the concept of Computed properties and I'm trying to use them as much as I can, however it got me thinking that maybe I'm overdoing it and this will have a performance impact on my app.

So my scenario: I have a class with two Strings, one of them is my username that is global thought my app and the other is the opponent's username. So my code is something like this:

class Game {
    let player: String
    let opponent: String
    var iAmPlayer: Bool {
        return player.caseInsensitiveCompare(GlobalUsername) == .orderedSame
    }

    init(player: String, opponent: String) {
        self.player = player
        self.opponent = opponent
    }
}

I check my iAmPlayer boolean quite often, to see if the user started the game or not, especially when ordering the game objects. In java, I just have a boolean variable that I set when I initialise my object. I was wondering, is it better if I just use a Stored property here instead of what I'm doing? Are computed properties optimised, or the calculation is taking place every single time I try to access the iAmPlayer var?

P.S.: Once the Game object is created, player and opponent don't change. (thus the let)

Upvotes: 1

Views: 973

Answers (1)

muescha
muescha

Reputation: 1539

thx to other comments on below the question i uset Usermanager.instance.username instead of GlobalUsername

1.Solution: move calculation to Init

  • pro: no changes to any other code
  • con: still has a reference to the UserManager

Code:

class Game {
    let playerName: String
    let opponentName: String
    var isCurrentUser: Bool

    init(playerName: String, opponentName: String) {
        self.playerName = playerName
        self.opponentName = opponentName
        self.isCurrentUser = playerName.caseInsensitiveCompare(UserManager.instance.currentUserName) == .orderedSame
    }
}

// Create Game object

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName)

2. Solution: give the current userName to the init

  • pro: no implicit out connections - decoupling of object
  • pro: testable without to set the Usermanager
  • con: you have to change the creation of Game init

Code:

class Game {
    let playerName: String
    let opponentName: String
    var isCurrentUser: Bool

    init(playerName: String, opponentName: String, currentUserName: String) {
        self.playerName = playerName
        self.opponentName = opponentName
        self.isCurrentUser = playerName.caseInsensitiveCompare(currentUserName) == .orderedSame
    }
}

// Create Game object

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName, 
    currentUserName: UserManager.instance.currentUserName)

3. Solution: move calculation of the bool outside of creation

  • pro: no implicit out connections - decoupling of object
  • pro: testable without to set the Usermanager
  • pro: change logic of calculation for "isCurrentUser" without changing the Game object
  • con: you have to change the creation of Game init

Code:

class Game {
    let playerName: String
    let opponentName: String
    var isCurrentUser: Bool

    init(playerName: String, opponentName: String, isCurrentUser: Bool) {
        self.playerName = playerName
        self.opponentName = opponentName
        self.isCurrentUser = isCurrentUser
    }
}

// Create Game object

var currentUserName = UserManager.instance.currentUserName
var isCurrentUser = dameData.playerName.caseInsensitiveCompare(currentUserName) == .orderedSame

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName, 
    isCurrentUser: isCurrentUser)


// Create Game object

var isCurrentUser = UserManager.instance.isCurrentUser(gameData.playerName)

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName, 
    isCurrentUser: isCurrentUser)

Upvotes: 2

Related Questions