コード考古学:簡単な修正のその先へ進むための3つのアプローチ
バグ修正に取り組むとき、一見して手っ取り早い変更が必ずしも最善の解決策とは限りません。また、目の前にあるコードはプロジェクトの物語のすべてではありません。安易な修正の先に進むには、なぜそのような設計判断が下されたのかを知る必要があります。つまり、コードの背後にある歴史を理解することが不可欠なのです。そして、自信を持ってコードを変更するために必要な知識を得るには、3つの優れた方法があります。
git blame
git blame を使えば、プロジェクト内のすべてのコード行の変更履歴を、その行が最初に書かれた時点までさかのぼって追跡できます。
例として、ActiveJob の queue_name.rb ファイルを見ていて、queue_name_delimiter 属性が何のためのものなのか知りたくなったとしましょう。
included do
class_attribute :queue_name, instance_accessor: false
class_attribute :queue_name_delimiter, instance_accessor: false
self.queue_name = default_queue_name
self.queue_name_delimiter = '_' # set default delimiter to '_'
end
そこで git blame を実行してみます。
$ git blame queue_name.rb
da6a86f8 lib/active_job/queue_name.rb (Douwe Maan 2014-06-09 18:49:14 +0200 34) included do
1e237b4e activejob/lib/active_job/queue_name.rb (Cristian Bica 2014-08-25 17:34:50 +0300 35) class_attribute :queue_name, instance_accessor: false
11ab04b1 activejob/lib/active_job/queue_name.rb (Terry Meacham 2014-09-23 15:51:44 -0500 36) class_attribute :queue_name_delimiter, instance_accessor: false
...
各行に対して、次の情報が順に表示されます。
- その行を最後に変更したリビジョン(例:
11ab04b1) - そのコミットの作者名
- 変更が加えられた日付
そのコード行についてさらに詳しく調べるには、リビジョン番号が必要です。ID(11ab04b1 の部分)を git show や git log に渡してみましょう。
$ git show 11ab04b1
commit 11ab04b11170253e96515c3ada6f2566b092533a
Author: Terry Meacham <zv1n.fire@gmail.com>
Date: Tue Sep 23 15:51:44 2014 -0500
Added queue_name_delimiter attribute.
- Added ActiveJob::Base#queue_name_delimiter to allow for
developers using ActiveJob to change the delimiter from the default
('_') to whatever else they may be using (e.g., '.', '-', ...).
- Updated source guide to include a blurb about the delimiter.
diff --git a/activejob/lib/active_job/queue_name.rb b/activejob/lib/active_job/queue_name.rb
index d167617..6ee7142 100644
...
これで、その変更の背景や有用性を知ることができ、見逃していたかもしれない Rails ガイドの該当セクションも発見できました。
今回は運が良く、探していた情報にすぐたどり着きました。しかし git blame が表示するのは、その行が変更された最も直近の履歴だけです。場合によっては、2〜3コミット前まで遡らないと、求めている情報にたどり着かないこともあります。
より古いコミットを確認するには、git blame を再び実行します。ただしこのとき、直前に見つかったコミットのひとつ前のリビジョンを指定します。(Git では、リビジョンに ^ を付けることで「そのコミットの直前のコミット」を表せます。例:11ab04b1^)
$ git blame 11ab04b1^ queue_name.rb
da6a86f8 lib/active_job/queue_name.rb (Douwe Maan 2014-06-09 18:49:14 +0200 33) included do
1e237b4e activejob/lib/active_job/queue_name.rb (Cristian Bica 2014-08-25 17:34:50 +0300 34) class_attribute :queue_name, instance_accessor: false
94ae25ec activejob/lib/active_job/queue_name.rb (Cristian Bica 2014-08-15 23:32:08 +0300 35) self.queue_name = default_queue_name
...
$ git blame 1e237b4e^ queue_name.rb
... 以降同様 ...
とはいえ、これを手作業で繰り返すのはかなり骨が折れます。
そこで代わりに、テキストエディタの機能を活用しましょう。多くのエディタには、git blame による履歴追跡を簡単に行う仕組みが備わっています。たとえば Emacs では、git blame を実行した後、カーソルを目的の行に置きます。すると a キーを押すごとに、その行に影響した変更を一つずつさかのぼることができ、l や D キーでコミットの詳細を確認できます。
あなたのチームでは、コミットメッセージに issue 番号やプルリクエストへの参照を含めていますか?もしそうであれば、git blame を使って、コードの一行からコミットへ、さらにそのコミットをめぐる議論へと容易にたどり着けます。そして、その議論こそが本当に価値のある情報が眠る場所なのです。
GitHub Issues
少し前のことですが、Rails 4.2 で respond_with が削除されたことに気づきました。ドキュメントには削除された事実は明記されていたものの、その理由までは分かりませんでした。
GitHub の issue 検索ボックスの裏には、膨大な貴重な知識が隠されています。ある機能が削除された理由を知りたいなら、削除を決定した際のチームの議論以上に適した情報源はありません。
実際に、Rails の GitHub リポジトリで respond_with を検索すると、興味深いスレッドがいくつか見つかります。削除の理由を探しているなら、おそらく特定のスレッドに行き着くでしょう。しかし残念ながら、そこにはどのように削除されたかは書かれていても、なぜ削除されたかは書かれていません。
ところが、そのスレッドを読み進めると、respond_with 削除に関する本来の議論を指し示すコメントが見つかります。そここそが宝庫なのです!
git blame と同じように、最初から求めている情報が見つかるとは限りません。参照をたどり、コメントを読み、リンクをクリックしていく必要があります。それでも、GitHub の issue 検索は正しい出発点へと導いてくれるでしょう。少しの好奇心と探究心があれば、目的の知識に必ずたどり着けます。
質問する
残念ながら、プロジェクトに関するすべての知識が履歴や issue、プルリクエストの中に記録されているわけではありません。すべてが文書化されているとは限らないのです。
だからこそ、元のコードを書いた人を見つけられるのであれば、直接尋ねてみましょう。その決定につながった開発文化や考え方を知ることができます。おそらくどこにも記録されなかったプロジェクトの歴史を学べるでしょう。さらに、採用されなかった選択肢についても聞くことができ、状況によっては今こそ試す価値があるかもしれない案に出会えることもあります。
安易な修正は危険をはらむ
ときには、修正があまりにも簡単に見えることがあります。「この一箇所でこの例外を rescue するだけで、あとは帰れる!」——そんな具合に。
しかし、理解していないコードを変更するのは危険です。
だからこそ、コードの行が奇妙に見えたり、設計判断が変に感じられたり、ある呼び出しが無駄に思えたりしたときは、考古学者の帽子をかぶりましょう。そのコードについて、手段を選ばず、できる限り多くを学ぶのです。そうしてはじめて、意図的で確かなコード変更が可能になり、問題を根本から解決できるようになります。
-
Disney+(ディズニープラス)のエラーコード83を解決する方法|原因と対処法を徹底解説
ディズニーを「フランチャイズ」と呼ぶのは、その長年培われてきた魔法のような魅力を損なう気がしますが、実際のところそれが実態です。ディズニーは数十年にわたり、ターゲット層に「取り残される恐怖(FOMO:Fear Of Missing Out)」を抱かせることに成功してきました。しかし、Disney+(ディズニープラス)の加入者にとって、エラーコード83はその恐怖を現実のものへと変えてしまう厄介な存在です。この記事では、Disney+のエラーコード83が何を意味するのかを解説し、具体的な解決方法をご紹介します。まずは、このエラー自体について詳しく見ていきましょう。期間限定で、ExpressVPNに
-
【Windows】「このデバイスは無効になっています(コード22)」エラーの原因と6つの直し方
一部のWindowsユーザーから、正常に動作しないデバイスの状態をデバイスマネージャーやサービス管理ツールで確認した際に、「このデバイスは無効になっています。(コード 22)」というエラーが表示されると報告されています。この問題は複数のWindowsバージョンで発生が確認されており、単にデバイスがデバイスマネージャー上で無効化されていることだけが原因ではありません。コード22エラーの主な原因調査の結果、このエラーコードが表示される背景にはいくつかの異なる原因があることがわかりました。考えられる原因は以下の通りです。デバイスが無効化されている – 最も多い原因は、手動操作やリソース最適化アプリに