【書籍紹介Vol.1】Effective Debugging――デバッグ技術向上に役立つ一冊
Photo by 🇸🇮 Janko Ferlič on Unsplash
お気に入りの一冊、役に立った一冊をメンバー自身が紹介する【書籍紹介】です。
<担当メンバープロフィール>
仮称/けい
入社年/2009年
出身地/石川県
所属/CPS事業部 東京ユニット(エンジニアリング領域)
経歴/
・これまでAndroidアプリの開発、テストを担当してきました。
・現在は、組み込みLinux向けソフトの開発を行っています。
コメント/
・親指シフトユーザーです。
・たまにOSSにコントリビュートするのが趣味です。
・最近はRust推しです。
私は、技術書を読むのが好きです。そこで今回は、お気に入りの1冊を紹介します。
紹介する技術書は、「Effective Debugging(オライリー・ジャパン)」です。
この記事では、「Effective Debugging」について、私が良いと感じたところを紹介します。
デバッグが苦手な方や、今よりも効率的にデバッグをしたい方にオススメです。
デバッグ技法だけではなくバグを探しやすいプログラムの作り方もわかる「Effective Debugging」
私はデバッグが苦手でした。
デバッグのノウハウが不足しており、バグの原因を探すのに手間がかかっていたためです。
バグの原因を探すのに、何時間もコードを読み続けたり、適当にprint文を入れて実行したりしていました。
しかし、「Effective Debugging」を読んで、デバッグへの苦手意識が減りました。
「Effective Debugging」に、デバッグ時に使える技法がたくさん紹介されていたためです。
技法のなかには、設計や実装に応用可能なものや、開発プロセスの運用に活かせるものもありました。
「Effective Debugging」を読んで、次のことを意識するようになりました。
- デバッグしやすい設計・実装を目指す
- デバッグ時に様々な手段を試す
結果、デバッグの原因を早く探せるようになりました。
つまり、バグを見つけやすくするために、ソフトウェア開発全般に応用可能な技法を紹介した本が「Effective Debugging」です。
「Effective Debugging」の特に良かった3点
「Effective Debugging」で紹介されている技法は、どれも参考になると私は感じました。
「Effective Debugging」で紹介されている技法のなかでも、私が特に良かったと感じたものについて紹介します。
- デバッグのための機能を追加する
- バージョン管理システムはデバッグにも役立つ
- ログ、ユニットテスト、アサーションを使い分ける
いずれも、デバッグの効率が上がる方法です。
以下に詳細を説明します。
1. デバッグのための機能を追加する
「Effective Debugging」の以下の項目では、プログラムに内蔵されたデバッグ機能について触れています。
- 項目6:ソフトウェアのデバッグ機能を使う
- 項目40:デバッグ機能を追加する
「デバッグ機能」とは、本番時には動作せず、デバッグ時のみに動作させる機能のことです。
例えば、以下のような機能がデバッグ機能として実装されます。
- 追加のログを出力し、プログラムの動作を追跡しやすくする
- 本来は外部から入力されるデータをプログラム内部で生成し、再現性のある動作をさせる
以前の私は、プログラムに余分な機能は入れないほうが良いと考えていました。
しかし、項目内の実例を見て、考えを変えました。
最近の業務ではUNIX系OSを使用することが多いのですが、確かにデバッグ機能が付いたコマンドがあります。
例えば、項目内で実例としても取り上げられているsshです。
リモートのマシンに接続できないなどのトラブルが起きたときに、デバッグ機能を使って動作をログ出力させたことを思い出しました。
また、外部デバイスからの入力を処理するプログラムの開発に、この項目が役立ちました。
このプログラムには、外部デバイスの入力の代わりに、偽物のデータを生成して使用するモードを追加しました。
このモードのおかげで、デバッグ時に、外部デバイスの問題か、データを処理する部分の問題か、切り分けがしやすくなりました。
このように、デバッグ機能を作ることで、デバッグの効率が上がります。
2. バージョン管理システムはデバッグにも役立つ
「Effective Debugging」の以下の項目では、バージョン管理システムを用いたデバッグ技法について触れています。
- 項目5:既知の正常なシステムと問題を起こしているシステムとの違いを検出する
- 項目10:問題の効率的な再現を可能にする
- 項目26:バグの原因と経緯とをバージョン管理システムで探す
プログラムのバージョンAでは動作に問題がないのに、バージョンBでは問題がある場合、この技法が使えます。
この技法のすごいところは、コードをほとんど読まなくても原因を特定できる点です。
バージョン管理システムが、バグが混入した変更を見つけ出してくれます。
項目内では、Gitでの例が挙げられています。
Gitを使用しているのであれば、「git blame」と「git bisect」は覚えておいて損はありません。
「git blame」を使用すると、ファイル内の変更履歴が行単位でわかります。
原因に関係するファイルに心当たりがある場合は、変更履歴を見るだけで、バグの混入したコミットが見つかることがあります。
「git bisect」を使用すると、コミット履歴を二分探索して、問題が混入したコミットを探せます。
コードを読まなくても、Gitが提示するコミットでの動作を確認するだけで、バグの混入したコミットがわかります。
このように、バージョン管理システムをデバッグに活用することで、デバッグの効率が上がります。
3. ログ、ユニットテスト、アサーションを使い分ける
「Effective Debugging」の以下の項目では、ログ、ユニットテスト、アサーションを用いたデバッグ技法について触れています。
- 項目41:ロギング文を追加する
- 項目42:ユニットテストを使う
- 項目43:アサーションを使う
最近のプログラミング言語では、ログ、ユニットテスト、アサーションがサポートされているものが多いです。
サポートされていない場合でも、オープンソースのものが簡単に見つかります。
ただ、ログ、ユニットテスト、アサーションをどう使い分ければ良いか、以前の私にはよくわかりませんでした。
なので、ユニットテストのみをほとんどの場合に使っていました。
ログはprintfデバッグのようで抵抗がありました。
アサーションは、ユニットテストがあれば十分と考えていました。
上記の項目では、ログとアサーションについて、次のように使い分けを説明しています。
- ログ
- 主要な処理の出入口、主要なデータ構造、状態変更など、動作の追跡のためにログを出す
- アサーション
- 処理の事前条件や事後条件、到達しない箇所など、デバッグ用途の検証やコードのわかりやすさのためにアサーションを入れる
- ユニットテストでテスト可能な場合は、ユニットテストを優先する
上記の項目を読んだ後は、意識的にログを使うようになりました。
結果、デバッグ時にプログラムの動作を解析しやすくなりました。
また、ユニットテストの補完としてアサーションを使用するようになりました。
結果、想定外の状態となった場所が、呼び出し階層の深い部分でもわかりやすくなりました。
このように、ログ、ユニットテスト、アサーションを使い分けることで、デバッグの効率が上がります。
最後に
ここまで「Effective Debugging」について紹介してきました。
「Effective Debugging」から以下の点を学ぶことで、バグの原因を探しやすくなりました。
- デバッグしやすい設計・実装
- デバッグ時に使用できる様々な手段
結果として、デバッグへの苦手意識を減らすことができました。
デバッグに苦手意識がある方や、今よりも効率的にデバッグしたい方には、ぜひオススメしたい本です。
記事を最後までお読みくださり、ありがとうございます。