はじめまして。ベトナム人のクアンと申します。
2020年2月来日してアクトインディで働いています。ブログ初投稿です! どうぞよろしくお願いいたします。
自己紹介
2019年にベトナムのハノイ工科大学を卒業しました。学生時代のインターンではPHPをやっていましたが、今はRubyやJSのコードを書いています。最初に担当したのは「海と日本PROJECT」のお魚パズルのゲームをJSで実装することでした。面白かったです。
では、本日のメインテーマを始めましょう。
ラバーダックデバッグとは?
ラバーダックデバッグはデバッグの方法です。この手法はThe Pragmatic Programmerという本で紹介されました。
手法は簡単です。コードを1行ずつラバーダック人形に説明します。
なぜラバーダックデバッグを使う?
外国人の新卒として、3つの問題を抱えています
いこーよは10年以上メンテナンスされているプロダクトなので、ソースコードが複雑になっていてわかりにくいところがあります。
プログラミングを知らない人に説明するとき、技術的な話をすると、その人はあまり分かりません。
他のエンジニアに説明するとき、自分の理解している内容を説明できない
とても大変ですよ!
ですから、理解してもらえるよう説明できるようになるためには、練習するしかありません。
説明を練習する時、常に他の人に聞いてもらえるわけではありません。 一人で相手を想像して練習するの場合、相手は自分ですから、自信があると思うことは全て正しそうと思えます。ですから、問題に気づきにくいです。そして、練習でも緊張してしまうことも、悪いところに気づけなくなります。 ですから、ラバーダックのような具体的な物があるほうがいいです。
ラバーダックデバッグの例
例えば、このFizzBuzz
のメソッドをラバーダッグデバッグしてみてください
# lib/fizz_buzz.rb def fizz_buzz(n) case when (n % 3) == 0 'Fizz' when (n % 5) == 0 'Buzz' else n.to_s end end
FizzBuzzは、以下のとおりに発言が進行します。
- 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizz Buzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, Fizz Buzz, 31, 32, Fizz, 34, Buzz, Fizz, ...
3で割り切れる場合は「Fizz」、5で割り切れる場合は「Buzz」、両者で割り切れる場合(すなわち15で割り切れる場合)は「Fizz Buzz」。
参考:Wikipedia
ルールにしたがって、テストを書きます。
# test/fizz_buzz_test.rb require 'minitest/autorun' require './lib/fizz_buzz' class FizzBuzzTest < Minitest::Test def test_fizz_buzz assert_equal '1', fizz_buzz(1) assert_equal '2', fizz_buzz(2) assert_equal 'Fizz', fizz_buzz(3) assert_equal '4', fizz_buzz(4) assert_equal 'Buzz', fizz_buzz(5) assert_equal 'Fizz', fizz_buzz(6) assert_equal 'Fizz', fizz_buzz(9) assert_equal 'Buzz', fizz_buzz(10) assert_equal 'Fizz Buzz', fizz_buzz(15) end end
テストを実行すると、エラーが発生します。
$ ruby test/fizz_buzz_test.rb Run options: --seed 62311 # Running: F Failure: FizzBuzzTest#test_fizz_buzz [test/fizz_buzz_test.rb:15]: Expected: "Fizz Buzz" Actual: "Fizz" rails test test/fizz_buzz_test.rb:5 Finished in 0.001213s, 824.4023 runs/s, 7419.6208 assertions/s.
さあ、デバッグしましょう!
まず、ラバーダックを持ちましょう!(ぬいぐるみとかでもOK)
ラバーダックに全部のテストを説明してあげます。
- 自分:1の場合は1
- ダック(ダックを押す):ガーガー
- 自分:2の場合は2
- ダック:ガーガー
- 自分:3の場合はFizz
- ダック:ガーガー
- 自分:4の場合は4
- ダック:ガーガー
- 自分:5の場合はBuzz
- ダック:ガーガー
- 自分:6の場合はFizz
- ダック:ガーガー
- 自分:9の場合はFizz
- ダック:ガーガー
- 自分:10の場合はBuzz
- ダック:ガーガー
- 自分:15の場合はFizzBuzz
- ダック:ガーガー
- 自分:じゃ、テストには問題がない
- ダック:ガーガー
次、logやメソッドを確認します
- 自分:失敗したのは15の15のケースです
- ダック:ガーガー
- 自分:エラーはExpected: "Fizz Buzz"/Actual: "Fizz"です。
- ダック:ガーガー
- 自分:というのは、3で割り切れるを処理するだけです。
- ダック:ガーガー
- 自分:コードを見て、3のケースは前ですから、"Fizz"はもちろんです。
- ダック:ガーガー
- 自分:そのあと、5のケース...
- ダック(押さない):...
コードを説明してみて、問題をみつけました
次はコード編集。5のケースは前になって編集すると、結果も失敗しました。でも、今回のlogはActual: "Buzz"です。やはり、"FizzBuzz"は別のケースにしなければならないです。このコードを追加します。
when (n % 15) == 0 'Fizz Buzz'
じゃ、もう一度テストを実行します
$ ruby test/fizz_buzz_test.rb Run options: --seed 1771 # Running: . Finished in 0.000882s, 1133.7868 runs/s, 10204.0816 assertions/s. 1 runs, 9 assertions, 0 failures, 0 errors, 0 skips
成功しました!
投稿は以上です。最後まで読んでいただいてありがとうございます。
最後に
アクトインディではエンジニアを募集しています。 actindi.net