0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【生涯収支管理】#2 — AIのレビュー指摘6PR分を型に分けたら偏っていた

0
Posted at

一人で書いていると、レビューが来ない

個人開発の一番の穴はレビューが無いことだと思う。設計を間違えても誰も止めてくれないし、うっかり書いた分岐も誰も見ない。

なので個人のリポジトリでも PR を切って、AI のコードレビューを通すようにしている。しばらく続けて指摘を全部コードで直してきたので、たまった分をまとめて読み返してみた。

読み返してみると、指摘が刺さる場所が驚くほど偏っていた。しかもその偏りには理由があった。以下、実際に直したものを型に分けて書く。全部すでに直っている話だ。

型1: 一人で動かしていると絶対に踏まないもの

一番多かったのがこれで、しかも一番ヒヤッとした。

監査ログの一覧を返す API が、ログインしている人の分だけでなく全件を返していた。where 句にユーザーの絞り込みが入っていなかった。自分ひとりで動かしている限り、返ってくるのは自分のログだけなので、画面上はどこまでも正しく見える。二人目が入った瞬間に他人のメールアドレスやアクセス元が混ざる。

同じ形の指摘がもう1件あった。エラーの詳細をそのままクライアントに返していたところ。開発中は自分がその文字列を読むので便利なのだが、そのまま本番に出ると内部構造を配って歩くことになる。

この型の共通点は、症状が「利用者が増えたとき」にしか出ないことだ。テストも通るし、手で触っても気づかない。自分のアカウントしか存在しない環境では、スコープ漏れは無害に見える。

一人で開発していると、この種のバグを見つける手段が原理的にない。ここは素直に助かった。

型2: パース関数が思ったより緩い

これは知識の問題だった。

URL から受け取った ID を Number.parseInt(value, 10) で数値にしていた。よく見る書き方だと思う。

Number.parseInt("5abc", 10)  // → 5

途中まで読めたらそこで止まって、読めた分を返す。 つまり "5abc" のような文字列がそのまま ID 5 として通る。URL を手で書き換えれば、意図しないレコードを触れてしまう。

直し方は単純で、正規表現で文字列全体を検証してから変換する共通関数に寄せた。

// 文字列全体が正の整数であることを確認してから通す
export function parsePositiveInt(v: string): number | null {
  return /^[1-9]\d*$/.test(v) ? Number(v) : null;
}

大事なのは1箇所に寄せたことのほうだと思っている。同じ指摘が3つのエンドポイントで同時に出ていた。個別に直していたら、4つ目を書くときにまた同じことをやる。

型3: リトライの適用範囲が広すぎた

DB のコネクションが切れることがあったので、クエリを横断的にリトライするようにしていた。全操作に一律でかけていた。

指摘されて気づいたのだが、これは書き込みで二重実行になる。DB 側では完了しているのに接続が切れてクライアントだけエラーになった場合、リトライがもう一度同じ書き込みを投げる。

リトライ対象を読み取り系だけに限定した。あわせて、リトライする条件も「接続断を示す特定のエラーコードのとき」に絞った。何でもかんでも再試行すると、本当は失敗すべきものまで粘ってしまう。

リトライは「安全に繰り返せる操作」にしか付けられない。 頭では知っていたのに、横断的に設定できる仕組みを使った瞬間に「全部にかける」を選んでいた。便利な仕組みほど、適用範囲を考えずに広げてしまう。

ついでにもう1件、リトライ絡みで指摘があった。最大5回試行するループで、5回目が失敗したあとにも待機が入っていた。もう次が無いのに10秒待ってから落ちる。CI が毎回その分だけ遅くなる。「最終試行なら待たない」の1行を入れ忘れるのは、自分でもよくやる。

型4: 境界が2箇所にあって揃っていない

これは地味だが、数字を出すアプリでは効く。

将来推計を出す処理があって、計算そのものは 2080 年まで回していた。一方、途中で適用する条件のほうは別の設定値(既定 2068 年)を上限にしていた。計算の終端と、条件の適用範囲の終端が違う。

結果として、2069 年から 2080 年までの区間だけ条件が抜け落ちた推計が出る。エラーは出ない。グラフは最後まで描画される。数字がおかしいことに気づく手がかりがない。

直したあと思ったのは、これは「同じ意味を持つ数字が2箇所にある」という、もっと一般的な形だということだった。片方だけ直る日が必ず来る。

AIレビューが指摘してこなかったもの

偏りの話に戻る。刺さったのは、スコープ、パース、適用範囲、境界。つまりコードを読めば閉じて判断できるものばかりだった。

逆に、一度も指摘されなかったものがある。この機能をそもそも作るべきかどうか。この抽象は早すぎないか。この指標は目的と制約を混ぜていないか。設計判断の部分は、当然ながら何も言ってこない。前提を知らないので言えない。

なので受け取り方としては、レビュアーというよりリンタの上位互換だと思っている。人間のレビュアーが一番時間を使うべき「そもそもこれでいいのか」は手つかずで残る。そこが空くのはありがたい。

そしてもうひとつ。指摘を全部直したのが良かったかというと、たぶん違う。ここに書いた型はどれも直して正解だったが、書式や命名の好みに寄った指摘も混ざっていて、それを全部反映していたら PR が指摘対応で埋まる。採否を自分で決めるのは変わらず自分の仕事だというのは、やってみて強く思った。

指摘を型に分けて読み返したのは今回が初めてだったが、これは定期的にやったほうがいい。同じ型を何度も踏んでいるのが見えるので、次に書くときに手が止まる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?