Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
What would be the best way to handle many instance variables handling state in a class?

My IDE says my game class has too many instance variables. I'm curious as to how it 'should' be? I could re-implement it into a hash or maybe a struct object. But I'm not sure that makes it any better. The variables are specific state that belong to the game. Would refactoring lead to some being memoized? Maybe some variables moved into a "rule-set" struct? What patterns apply to initializing multiple variables handling state?

class TonkGame
  def initialize
    @max_players = 5
    @min_players = 2
    @players = []
    @bet = 1
    @tonk = Game.new
    @face_up = []
    @turn = nil
    @over = false
    @round = 0
  end
# ...
end
@danielpclark

This comment has been minimized.

Copy link
Owner Author

@danielpclark danielpclark commented Dec 8, 2014

Just thinking out loud... I could have a GameTable object which contains no rules but would be a sensible object to hold players seated and cards in the center of the table.

A Player object could hold a default bet. Player already hold cards in hand.

turn, round , and over are specific game states. Possibly leave these alone?

min and max players could possibly go into a simple rule-set struct.

I seem to just be shuffling things around. Is that good? Many things to consider.

@danielpclark

This comment has been minimized.

Copy link
Owner Author

@danielpclark danielpclark commented Dec 8, 2014

player_limit = Struct.new(:min,:max,:players) {def playable?; (min..max) === players; end}.new(2,5)
player_limit.players = 1
player_limit.playable?
# => false
player_limit.players = 2
player_limit.playable?
# => true
player_limit.players = 6
player_limit.playable?
# => false

Maybe I should change this to the GameTable and actually "seat" Player instances within an Array in this struct.

@danielpclark

This comment has been minimized.

Copy link
Owner Author

@danielpclark danielpclark commented Dec 8, 2014

table = Struct.new(:min,:max,:players) {
  def playable?; (min..max) === Array(players).count; end
  def join(player); self.players = Array(self.players) << player; end
}.new(2,5)
table.join Player.new
table.join Player.new
table.playable?
# => true
@danielpclark

This comment has been minimized.

Copy link
Owner Author

@danielpclark danielpclark commented Dec 8, 2014

Table = Struct.new(:min,:max,:players,:face_up) {
  def playable?; (min..max) === Array(players).count; end
  def join(player); self.players = Array(players) << player; end
  def discard(card); self.face_up = Array(face_up) << card; end
  def discard?; Array(face_up).last; end
}
class TonkGame
  def initialize
    @table = Table.new(2,5)
    @bet = 1
    @tonk = Game.new
    @turn = nil
    @over = false
    @round = 0
  end
# ...
end

This frees up 4 to 1.

@danielpclark

This comment has been minimized.

Copy link
Owner Author

@danielpclark danielpclark commented Dec 8, 2014

I'm thinking of creating an Object that behaves similar to what Enumerable does for Ruby. I'll call it Rotation. It can handle player turn and table round. Implemented with cycling on table.players object using "Count iteration on the Enumerable cycle" for iteration counting. That will extract two instance variables out to one object which will be in charge of all game rotation features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment