レガシーコードをなんとかして読み解く方法

レガシーコードをリプレイスするタスクで、レガシーコードが全然読めなくて時間を浪費しきってもまだ何もわからなくて詰んだ。 先輩エンジニアに相談したら即席コードリーディング会を開く声掛けをしてもらえて、どうレガシーコードを追うのか見ることができた。

今日はそのときの学びを書いておく。

タスク内容

n年モノのメディア系PHPコードのごく一部のビュー(リンク集的なパーツ)の描画ロジックを別システムにリプレイスする。

学び

全部を追わない

何より全部を追うとツラすぎるし、得られる完璧な仕様もコストに見合わない。

外部仕様をざっくり理解する

今回はHTMLがアウトプットになるので、どんなHTMLがどのコードから出てくるのか、その末端から理解すると良いということがわかった。 リンクに必要なURLやタイトルがどういうオブジェクトから生成されているのかをまず把握する。 そして次にそのオブジェクトがどの別のオブジェクトから生成されているのかを把握していく。でも深入りはしない。

行間を読む

正直、今となっては命名が微妙だったり不要な引数を受け取っていたり、必ずある値しか来ないのにif文が書かれていたりすることは全然ありえる。 そうなった時に今までの歴史を知っている人に聞くことはもちろん大事だけど、それとは別に「当時やりたかったことを察してあげる」ことも大事だと学んだ。

今回はPHPだがあの名著「SQLアンチパターン」にも、

問題の解決を意図しながらも、しばしば他の問題を生じさせてしまうような技法

と書かれている。たとえあるコードがアンチパターンを踏んでいたとしても、特定の状況を解決したといえるはず。 それをよりスマートな方法で実現して、今お金を稼いでくれているコードへの弔いにしよう。

関数の引数を追わない

これをやり始めると無限に違う箇所を読み続けて、自分が何者だったのかも忘れてしまう。 僕は今回これを何度もやらかして時間も精神力も浪費した。

先輩エンジニア氏は、外部仕様をざっくり把握するにあたって関数の引数が現れたら、その時に呼ばれている関数だけを調べてなんとなくそのオブジェクトの役割を理解すると言っていた。 たしかに、一応オブジェクト指向で書かれているんだからあるオブジェクトのすべての振る舞いではなくて必要な振る舞いだけを調べればいいはずだよな。 それに、リプレイス対象の関数が(当時必要だったかもしれないけど)今や不必要な大きなオブジェクト(HttpRequestみたいなやつ)を引数に受け取ってしまっている可能性は全然想像できる。そうだった時に、引数を先に追うと必要な処理に必要ない情報ばかり掴まされることになる。

ざっくり分かったらとりあえず書き始める

なんとなくどんな条件の時にどんなビューが返ればいいのか分かってきたら、もう書き始める。 これでちょっとずつキレイなコードを吐いて、脳内に覚えておかなければいけない仕様を減らす。で、またオカワリする。

道は遠いが、僕はまだレガシーコードと出会ってそう時間が経っていない。 単にレガシーコードを書くスキルレベルが1なのだ。

ありがたみと滅せよという気持ちを内在させながら、その念を飼い慣らしていこう。