Elixirチートシートを作ろう、番外編その６ hexdoc見てたら、おや？デバッグ方法、こんなにあるの、その２？


# 1. OverView

どもども、うん、アドベントカレンダーの完走賞狙いなんだ、すまない。

さて、hexdocにあるデバッグ方法を順を追って調べようと言う話題です。

https://hexdocs.pm/elixir/debugging.html

IO.inspect/2
dbg/2
Pry
Breakpoints
Observer
Other tools and community

順を追ってPryを…と思ったけど、これ、コードの変更が必要ですし。
すごい良い解説がネットにあふれてるので、お前書く必要ある？と言われると自信がない。
なので、次、Breakpointsに行きたいと思います。

え？Observer...起動したけど、理解が追いつかんかったｗ

# 2. break!
## 2.1 hexdocで確認

さて、ブレークポイントが設定出来るくらいで、特に面白くも無かろうと思ってたんですが、
h()を見てたら、意外と機能が豊富なので改心しました。

```
  • break!/2        - sets a breakpoint at Module.function/arity
  • breaks/0        - prints all breakpoints to the terminal
  • c/0             - a shortcut for continue/0
  • continue/0      - continues execution of the current process
  • n/0             - a shortcut for next/0
  • next/0          - goes to the next line of the current breakpoint
  • remove_breaks/0 - removes all breakpoints and instrumentation from all
    modules
  • whereami/1      - prints the current location and stacktrace in a pry
    session
```

作業の流れは、
1. ブレークポイントを決めて、break!/2 でブレークポイントを設定します。


break! Example.double_sum/2で関数に入るところで止まる様にしております。


```
(base) C:\Users\nanbu\example>iex.bat -S mix
Erlang/OTP 27 [erts-15.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.18.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> break! Example.double_sum/2
1
```

そして、モジュールの実行です。
```
iex(2)>  Example.double_sum( 2, 4 )
Break reached: Example.double_sum/2 (lib/example.ex:3)

    1: defmodule Example do
    2:   def double_sum(x, y) do
    3:     hard_work(x, y)
    4:   end
    5:
    6:   defp hard_work(x, y) do

iex(3)>
```
プログラムが実行され、double_sumで止まっている事がわかりました。
さて、いろんなコマンドを使ってみましょう。

2. whereami
自分の位置やスタックとレースを表示してくれます。
```
iex(3)> whereami
Location: lib/example.ex:3

    1: defmodule Example do
    2:   def double_sum(x, y) do
    3:     hard_work(x, y)
    4:   end
    5:

    (example 0.1.0) Example.double_sum/2
    (elixir 1.18.0) lib/module/parallel_checker.ex:120: Module.ParallelChecker.verify/1

```

3. Breakpointの操作

プログラムの実行の前に、remove_breaksとbreaksを紹介しましょう。

breaksはbreak pointの一覧を表示します。
remove_breaksはbreak pointを削除します。

以下、 break!でExample.double_sum/2でbreak pointを三回分設定、
breksで確認後、remove_breaksでbreak pointを削除しています。

```
iex(19)> break!(Example.double_sum/2, 3)
1
iex(20)> breaks

 ID   Module.function/arity   Pending stops
---- ----------------------- ---------------
 1    Example.double_sum/2    3

iex(21)> remove_breaks
:ok
iex(22)> breaks
No breakpoints set
iex(23)>
```

4. プログラムの実行を継続

nextとcontinueがあります。
nextは一行だけ実行、次の行に移動します。continueは、そのまま処理を続けます。


next: 次の行を実行し、次のブレークポイントまたは次の行で停止します。
continue: プログラムの実行を再開し、次のブレークポイントで停止します。
nextはn, continueはcとリンクが定義されてます。
次の関数に入る、step-inがないみたいですねぇ、まぁ、以下の様にブレークポイントを設定すりゃいいだけだけど

```
iex(9)> breaks

 ID   Module.function/arity   Pending stops
---- ----------------------- ---------------
 1    Example.double_sum/2    2
 2    Example.hard_work/2     1

iex(10)> Example.double_sum( 2, 4 )
Break reached: Example.double_sum/2 (lib/example.ex:3)

    1: defmodule Example do
    2:   def double_sum(x, y) do
    3:     hard_work(x, y)
    4:   end
    5:
    6:   defp hard_work(x, y) do

iex(11)> next
Break reached: Example.hard_work/2 (lib/example.ex:7)

    4:   end
    5:
    6:   defp hard_work(x, y) do
    7:     x = 2 * x
    8:     y = 2 * y
    9:
   10:     x + y

```

nextを実行していくと、どんどん行が進むのがおわかりでしょうか？
```
iex(11)> next
Break reached: Example.hard_work/2 (lib/example.ex:7)

    4:   end
    5:
    6:   defp hard_work(x, y) do
    7:     x = 2 * x
    8:     y = 2 * y
    9:
   10:     x + y

iex(12)> next
Break reached: Example.hard_work/2 (lib/example.ex:8)

    5:
    6:   defp hard_work(x, y) do
    7:     x = 2 * x
    8:     y = 2 * y
    9:
   10:     x + y
   11:   end

iex(13)> next
Break reached: Example.hard_work/2 (lib/example.ex:10)

    7:     x = 2 * x
    8:     y = 2 * y
    9:
   10:     x + y
   11:   end
   12: end
```

こんな感じで、ゆっくりとデバッグが出来ます。

5. 変数を調べるのは、はい、binding()で

昨日の今日なので、ハイ、binding()ですね。
以下の様に、ローカル変数xとyが表示されるのがわかるでしょうか？

```
iex(14)> binding()
[x: 4, y: 8]
iex(15)>
```

以上です。
意外と便利ですね。