# 定数による改善

定数を使ってコードの可読性と保守性を向上させたいと思います。

## 定数を使うメリット

三目並べコードに定数を入れていく前に、メリットを考えてみます。



### 修正が楽になる

例えば以下のようなメールのメッセージを生成するコードがあったとします

```ruby
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 枚のファイルなので簡単に書き直せるかもしれませんが、これが

大量のファイルに散らばっていると地獄を見ることになります（実際経験しました）

大量に修正するのが嫌なので、定数を定義して楽したいと思います。

```ruby
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を変えるだけで修正内容を全て適応できるので、楽できるわけです。

### 可読性が向上する

例えば、以下のようなコードがあったとします。

```ruby
def can_downlod? stff_id
  return [123, 113].include?(staff_id)
end
```

これだと、なんのこっちゃわかりません。

staff\_idの123と113だけ特別な権限が与えられているのかなーくらいです。

定数にしてみます。

```ruby
TANAKA = 123
YAMAMOTO = 113

SALE_TEAM_LEADER = [
  TANAKA,
  YAMAMOTO
]

def can_downlod? stff_id
  return SALE_TEAM_LEADER.include?(staff_id)
end
```

田中と山本という社員が営業チームのリーダーでダウンロードが出来る

それ以外の社員は出来ない、ということを定数を使って表現しました

修正前よりは可読性が上がりました。



{% hint style="info" %}
**課題コーナー**

&#x20;現状のコードに定数を適用させる
{% endhint %}

## 三目並べコードに定数を適用する

以下の数字に定数を適応していきたいと思います。

* プレイヤー1を表す数値の1
* プレイヤー2を表す数値の2
* 空きマスを表す数値の0

```ruby
PLAYER1_PIECE= 1
PLAYER2_PIECE = 2
OPEN_SLOT = 0
```

今まで、数値を使っていたメソッドの処理を定数に置き換えてみます。

```ruby
# 説明: ゲーム板の状態をコンソールに出力する
# 引数: 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
```

各メソッドの可読性が上がったのではないでしょうか。
