定数を使ってコードの可読性と保守性を向上させたいと思います。
定数を使うメリット
三目並べコードに定数を入れていく前に、メリットを考えてみます。
修正が楽になる
例えば以下のようなメールのメッセージを生成するコードがあったとします
def create_mail_text_a name
return <<~EOS
#{name}様
ご登録ありがとうございました。
...
以上、よろしくお願いします。
---------------------
社名: スーパモンキー株式会社
サイトURL: https://~
住所: xxx-ooo-xxx
電話番号: 000-0000-0000
---------------------
EOS
end
def create_mail_text_b name
return <<~EOS
#{name}様
本日はイベントにご参加いただきありがとうございました!
...
以上、よろしくお願いします。
---------------------
社名: スーパモンキー株式会社
サイトURL: https://~
住所: xxx-ooo-xxx
電話番号: 000-0000-0000
---------------------
EOS
end
def create_mail_text_c
return <<~EOS
本日のイベント情報です!
...
以上、よろしくお願いします。
---------------------
社名: スーパモンキー株式会社
サイトURL: https://~
住所: xxx-ooo-xxx
電話番号: 000-0000-0000
---------------------
EOS
end
...(この後にd, e, f, gと続いていく)
この時に不運な事にサイトURLが変わってしまったとします。
すると、全てのメール署名部分を書き直すという非常に面倒な作業が発生します。
例の場合だと1 枚のファイルなので簡単に書き直せるかもしれませんが、これが
大量のファイルに散らばっていると地獄を見ることになります(実際経験しました)
大量に修正するのが嫌なので、定数を定義して楽したいと思います。
SIGNATURE = <<~EOS
---------------------
社名: スーパモンキー株式会社
サイトURL: https://~
住所: xxx-ooo-xxx
電話番号: 000-0000-0000
---------------------
EOS
def create_mail_text_a name
return <<~EOS
#{name}様
ご登録ありがとうございました。
...
以上、よろしくお願いします。
#{SIGNATURE}
EOS
end
def create_mail_text_b name
return <<~EOS
#{name}様
本日はイベントにご参加いただきありがとうございました!
...
以上、よろしくお願いします。
#{SIGNATURE}
EOS
end
def create_mail_text_c
return <<~EOS
本日のイベント情報です!
...
以上、よろしくお願いします。
#{SIGNATURE}
EOS
end
...(この後にd, e, f, gと続いていく)
SIGNATUREを変えるだけで修正内容を全て適応できるので、楽できるわけです。
可読性が向上する
例えば、以下のようなコードがあったとします。
def can_downlod? stff_id
return [123, 113].include?(staff_id)
end
これだと、なんのこっちゃわかりません。
staff_idの123と113だけ特別な権限が与えられているのかなーくらいです。
定数にしてみます。
TANAKA = 123
YAMAMOTO = 113
SALE_TEAM_LEADER = [
TANAKA,
YAMAMOTO
]
def can_downlod? stff_id
return SALE_TEAM_LEADER.include?(staff_id)
end
田中と山本という社員が営業チームのリーダーでダウンロードが出来る
それ以外の社員は出来ない、ということを定数を使って表現しました
修正前よりは可読性が上がりました。
三目並べコードに定数を適用する
以下の数字に定数を適応していきたいと思います。
PLAYER1_PIECE= 1
PLAYER2_PIECE = 2
OPEN_SLOT = 0
今まで、数値を使っていたメソッドの処理を定数に置き換えてみます。
# 説明: ゲーム板の状態をコンソールに出力する
# 引数: board: ゲーム板, 3 x 3の二次元配列
# 戻り値: なし
def print_board(board)
puts ""
board.each do |row|
row.each do |e|
print " N " if OPEN_SLOT == e
print " o " if PLAYER1_PIECE == e
print " x " if PLAYER2_PIECE == e
end
puts ""
end
puts ""
end
...
# 説明: コマを配置する場所があるかどうかを判定する
# 引数: board: ゲーム板, 3 x 3の二次元配列
# 戻り値: コマを配置する場所がある => true
# コマを配置する場所がない => false
def can_plase_piece?(board)
board.any? { |row| row.any? { |a| OPEN_SLOT == a } }
end
...
# 説明: ゲームのmain部分
# このメソッドをコールするとゲームが始まる
# 引数: なし
# 戻り値: なし
def start
player = PLAYER1_PIECE
board = [
[OPEN_SLOT, OPEN_SLOT, OPEN_SLOT],
[OPEN_SLOT, OPEN_SLOT, OPEN_SLOT],
[OPEN_SLOT, OPEN_SLOT, OPEN_SLOT]
]
loop do
row, col = gets_piece_location()
place_piece(board, player, row, col)
print_board(board)
break if !continue?(player, board)
player = get_opponent_player(player)
end
print_result(board)
end
各メソッドの可読性が上がったのではないでしょうか。