🔰超かんたん！初学者向けエラーのデバッグ 

>どうもaono1234と申します。記事がいいなと思ったらtwitterのフォローもお待ちしております‼
https://twitter.com/takeshi_program


皆さん、コーディングは進んでいますでしょうか？

私はというと…まだプログラミング初心者のため、簡単なコードを書くのでさえ
数時間と掛かってしまいます:arrow_heading_down:

注意深くコーディングしても必ずエラーが発生してしまうんですよ！何とかならんものか…:frowning2:

エラーといっても原因は様々です、


- <b>スペルミス
- <b>メソッドの使い方が正しくない
- <b>クラスの書き方がわかんない
etc



そんな超初心者な私でも<font color=red>**デバッグ機能なしでエラー発生箇所を絞り込める方法**</font>があります。
良かったら、ご覧ください。


# はじめに
本記事は以下の読者様が対象です。
<br>

* <b>プログラミング初心者

* <b>クラスや関数のなんとなくの流れが追える

* <b>何時間もコードとにらめっこしたけど解決できなかった




本記事ではRubyを題材に例題コードを作成しておりますが、考え方は他の言語でも適用可能です。



# 先に結論
デバッグ機能を使わなくても基本の考え方さえ押さえておけば
<font color=red>**出力メソッド**</font>だけで、どこで問題が起きているか特定できる！<br>

:::note warn
デバッグ機能が必要ないとは言ってないので勘違いしないでください。
初学者のために出力メソッドを使っているだけです。
:::

<b>ちなみに出力メソッドとは
* Ruby でいえば　`puts`や`p`
* JavaScript でいえば　`console.log`
* C++ でいえば　`printf`
* PHP でいえば　`echo`

などのメソッドのことです。
これだけでピンとこない方は以下の例題で説明します。


# 例題
下記は「桃太郎」というパーティの合計のアタックポイントを出力するコードです。

```ruby
class Momotaro

  def initialize(self, first_member, second_member, thired_member)
    @self = self
    @first_member = first_member
    @second_member = second_member
    @thired_member = thired_member
  end

  def self_attack_point
    if @self.empty?
      0
    else
      100
    end
  end
  
  def first_attack_point
    if @first_member.empty?
      0
    else
      100
    end
  end
  
  def second_attack_point
    if @second_member.empty?
      0
    else
      100
    end
  end
  
  def third_attack_point
    if @thired_member.empty?
      0
    else
      100
    end
  end

  def total_attack_point
    self_attack_point + first_attack_point + second_attack_point + third_attack_point
  end

end

#パーティの設定
party_setting = { position_a: true, position_b: true, position_c: true, position_d: true }
#party_setting = { position_a: false, position_b: false, position_c: false, position_d: false }だと出力結果が0ではなく100となってしまう。


#変数へ格納(↓は三項演算子を使った書き方ですifのようなものです)
a = party_setting[:position_a] ? "桃太郎" : "" #party_setting[:position_a]がtrueならばaに"桃太郎"を入れて、falseならば""を入れる。
b = party_setting[:position_b] ? "犬" : ""
c = party_setting[:position_c] ? "猿" : ""
d = party_setting[:position_d] ? "鳥" : " "

#アタックポイントの合計値出力
momotaro = Momotaro.new(a, b, c, d)
p momotaro.total_attack_point
#出力結果400
#パーティ設定をすべてfalseにした場合：出力結果100
```


↑のパーティ設定の箇所ですが
`position_a: true`の`true`は「有効/無効ボタン」と思ってください。
`true`であれば桃太郎がパーティに存在している
`false`であれば桃太郎がパーティに存在していない
もし`position_a: false`であれば桃太郎抜きのパーティ（犬、猿、鳥）のアタックポイントを出すという具合です。

:::note alert
このコードにはバグがあります!
:::

今`party_setting[:position_○○]` が全て`true`なので全員が有効となっております。
この時、アタックポイントは`100 + 100 + 100 + 100`で出力結果は<b>400</b>となります。

逆にすべての`party_setting[:position_○○]`を`false`にすると
出力結果は`0`になって欲しいです。
しかし出力結果は<b>100</b>というおかしな結果が出力されてしまいます。
これを解決していきます。


# 解決方法
問題が起きている場所を特定するのは
汚染（バグ、エラー）が発生した河川を下流から徐々に調べるようなイメージです。

まずは下流（出力に近いところ）から調べます。
（パーティ設定はすべて`false`に変えてください）
```ruby
#パーティの設定
party_setting = { position_a: false, position_b: false, position_c: false, position_d: false }
```
\
<br>
<b>①
```ruby
p momotaro.total_point #出力結果100
```
↑ここが一番下流である出力部です。
出力は100となってます。当たり前ですが、すでに汚染されてますね。
ではすこし上流のtotal_pointというメソッドの中を調べます。

<b>②
```ruby
  def total_attack_point
      puts self_attack_point    #self_attack_point=0
      puts first_attack_point   #first_attack_point=0
      puts second_attack_point #second_attack_point=0
      puts third_attack_point   #third_attack_point=100
    return (self_attack_point + first_attack_point + second_attack_point + third_attack_point)
  end
```
↑`puts`メソッドで各変数の中身を見てみると
`puts third_attack_point`だけ<b>100</b>と出力されています。
`third_attack_point`がどうやら悪さをしているようです。
`third_attack_point`を上流へ遡ります。

<b>③
```ruby
  def third_attack_point
    if @thired_member.empty?
      puts "a"        #出力されず!!!!
      return 0
    else
      puts "b"        #こっちが出力された!!!!
      atack_point =100
      return atack_point
    end
  end
```
↑ここで`if`でちゃんと狙い通り`return 0`のブロックを通っているか`putsメソッド`をコード内に挿入して確認します。
正常ならば `"a"`が出力されるのに`"b"`が出力されています。
なぜ`else`の方の処理が流れるのでしょうか？
`@thired_member.empty?`が`false`だからだと思いますが、念のため出力させて確認しましょう。

<b>④
```ruby
  def third_attack_point
    puts @thired_member.empty? #false
    if @thired_member.empty?
      return 0
```
↑やはり`false`が出力されました。

:::note warn
   @thired_member.empty?は@thired_memberの中が空であれば`true`を返します。そうでなければ`false`を返します。
:::

原因は`@thired_member`にありそうです。
`@thired_member`の中に値が入っているのでしょうか？
遡り確認します。
<b>⑤
```ruby
  def initialize(self, first_member, second_member, thired_member)
    @self = self
    @first_member = first_member
    @second_member = second_member
    @thired_member = thired_member
    puts @thired_member   #何も出力されず
  end
```
↑
<b>あれれ？</b>`@thired_member`には何も出力されません。何も値が入ってないなら`@thired_member.empty?`は`true`になるのですが…
なぜ`@thired_member`は「空ではない(`false`)」と判断されてしまうのでしょうか？


具体的な原因はまだ分かりませんが、この調査で範囲が絞れました。（調査済みの部分はコメントアウトしています。）
```ruby
class Momotaro

  def initialize(self, first_member, second_member, thired_member)
    @self = self
    @first_member = first_member
    @second_member = second_member
    @thired_member = thired_member
  end

  # def self_attack_point
  #   if @self.empty?
  #     0
  #   else
  #     100
  #   end
  # end

  # def first_attack_point
  #   if @first_member.empty?
  #     0
  #   else
  #     100
  #   end
  # end

  # def second_attack_point
  #   if @second_member.empty?
  #     0
  #   else
  #     100
  #   end
  # end

  # def third_attack_point
  #   if @thired_member.empty?
  #     0
  #   else
  #     100
  #   end
  # end

  # def total_attack_point
  #   self_attack_point + first_attack_point + second_attack_point + third_attack_point
  # end

end

#パーティの設定
party_setting = { position_a: false, position_b: false, position_c: false, position_d: false }

#変数へ格納
a = party_setting[:position_a] ? "桃太郎" : ""
b = party_setting[:position_b] ? "犬" : ""
c = party_setting[:position_c] ? "猿" : ""
d = party_setting[:position_d] ? "鳥" : " "

#アタックポイントの合計値出力
momotaro = Momotaro.new(a,b,c,d)
p momotaro.total_point
```
少し手詰まりなので、次は上流（入力部）から調べてみます。

<b>⑥
```ruby
#パーティの設定
party_setting = { position_a: false, position_b: false, position_c: false, position_d: false }
p party_setting
#{:position_a=>false, :position_b=>false, :position_c=>false, :position_d=>false}

```
ここはすべてfalseが出力されており、問題ありません。
となると、問題部分は以下の⑦と⑤の範囲まで絞れたということになります。

<b>⑦
```ruby
#変数へ格納
a = party_setting[:position_a] ? "桃太郎" : ""
b = party_setting[:position_b] ? "犬" : ""
c = party_setting[:position_c] ? "猿" : ""
d = party_setting[:position_d] ? "鳥" : " "
```
↑見るとなにか違和感に気付くのでないでしょうか？
`a`~`c`の行は3項演算の右側が`""`となっているのにdの行は`" "`となっています。

:::note success
原因はスペース（値）を間違って`@thired_member`に入れてしまったことだと分かりました！
スペースを削除したら正常に動作しました！！
:::


# おわりに
如何でしょうか？
イメージは掴めましたか？

すべてのバグをこの方法で解決できるとは思いませんが、
<b>「考える箇所」と「考えなくてよい箇所」を機械的に切り分けできるだけでも</b>
分析が楽になるのではないでしょうか？

これからも色々と記事を投稿したいと思っておりますので、
どうぞ、よろしくお願いします！　:smiley:

# 追記
デバッグするときはputs をpに書き直した方が
より詳しい変数の情報を見ることができます！

```ruby
test = gets #inputと入力してエンターキー押下
puts test #"input"が出力される
p test #"input/n"が出力される（制御文字も確認できる）
```

>参考URL
> https://qiita.com/nyaoo/items/f5d84581d3a301a9c22f