頼んでいないものが付いてくる

ボタンを 1 つ追加してほしいと頼んだら、設定画面から表示位置を変えられるようにする仕組みまで付いてきた。項目を 1 つ足すだけの依頼に、汎用的な入力コンポーネントが添えられていた。

AI に実装を任せていると、こういうことが起きます。親切に見えますが、レビューする側からすると厄介です。 依頼した変更と、付け足された部分を見分けるところから始めることになります。

見分ける手間だけなら小さな話です。問題は、通してしまった付け足しがそのまま保守対象として残ることにあります。

なぜ「余る」ほうに寄るのか

不足と過剰では、目立ち方が違います。足りない実装はその場で問題になりますが、余分な実装は「あって困らないもの」として見過ごされます。この非対称が、余るほうへ寄せる圧力になります。

具体的には、次のようなものが足されやすくなります。

  • 依頼されていないエラー処理や入力チェック
  • 将来の変更を見越した設定項目
  • 1 箇所でしか使わないのに切り出された共通部品
  • 今回の要件では発生しない条件への分岐

いずれも、単体で見ると悪いものではありません。だからこそレビューで止めにくく、通ってしまいます。

書かれていない範囲は、良かれと判断されて埋まります。 ここを前提にしないと、指示をいくら丁寧にしても余分は減りません。

人が書いていた頃との違い

過剰実装そのものは、AI が使われる前からありました。将来を見越した設計、使われない設定項目、早すぎる共通化。どれも昔からある話です。

変わったのは量と速さです。人が書いていた頃は、余分を作るのにも時間がかかりました。面倒だという感覚が、そのままブレーキになっていた わけです。今はそのブレーキが外れています。

もう 1 つの違いは、書いた人の意図が残らないことです。人が余分を書いたときは、少なくとも本人には理由がありました。あとから聞けば「こういうつもりだった」と返ってきます。生成された余分には、そういう背景がありません。

観点人が書いていた頃AI に任せる場合
余分が生まれる量手間がブレーキになるブレーキが効かない
意図の追跡書いた人に聞けば分かる背景が残らない
見つけやすさ差分が小さく目に付く量に紛れて見落とす

同じ現象でも、対処の急ぎ方が変わります。 昔と同じ感覚で「あとで整理すればいい」と考えていると、整理が追いつかない速度で積み上がります。

害は静かに積み上がる

過剰実装の害は、その場では現れません。時間をかけて効いてきます。

現れ方起きること
レビューが重い依頼した変更と付け足しの切り分けから始まる
保守対象が増える使われない設定項目や分岐が、ずっと残る
変更が怖くなる誰も使っていない箇所が、消せないまま残り続ける
前提が崩れる1 箇所でしか使わない共通部品が、勝手に育っていく

とくに 3 つ目が効きます。使われていない実装を消すには、消しても壊れないことの確認が要ります。 時間が経つほどその確認が重くなるので、判断が先送りされ、結果として残り続けます。

注意

「動いているし、あとで判断すればよい」で残した実装は、ほぼそのまま定着します。消す判断が最も軽いのはレビューの時点です。

止めるのは「やること」ではなく「触らない範囲」

指示を詳しく書けば止まる、と考えて長い指示を書く方がいますが、効き目は限定的です。長さではなく、境界が引かれているかで決まります。

書くべきは、次の 3 つです。

  1. 変更してよいファイルや場所
  2. 追加してよい依存や部品 (増やさないなら、増やさないと書く)
  3. 今回は対応しなくてよい条件

3 つ目が特に効きます。「対応しない」と書かれていない条件は、埋めるべき穴として扱われます。 逆に、書いてあればそこで止まります。

たとえば「入力値が空のケースは今回対応しない」「多言語対応は範囲外」と一行入れておくだけで、その周辺の付け足しがなくなります。

依頼が大きいほど余りが増える

もう 1 つ、依頼の大きさも効きます。範囲が広い依頼ほど、境界が曖昧な部分が増えるためです。

依頼の大きさ起きやすいこと
1 つの画面、1 つの関数余りが出ても小さく、レビューで気づける
1 つの機能まるごと共通部分の作り方が委ねられ、抽象化が増える
「◯◯を改善して」何をもって完了かが決まらず、範囲が発散する

依頼を小さくすることは、範囲を書くことと同じ効果を持ちます。 小さく切れば、そもそも余りが入る隙間が減ります。範囲を書くのが面倒なら、依頼を切るほうから入っても構いません。

「今回やらないこと」に書く内容

範囲を切るといっても、何を書けばよいか迷うことがあります。実際に効く項目を挙げておきます。

  • 対応しない入力。想定外の値、空、極端に大きい値のうち、今回扱わないもの
  • 対応しない環境。特定の画面幅や、古い環境への対応
  • 作らない仕組み。設定で切り替えられるようにする、外部から差し替えられるようにする、といった拡張
  • 触らない領域。今回の変更と隣接するが、対象外の機能

4 つ目が抜けると、隣の機能まで「ついでに」整えられることがあります。隣接する領域は、明示的に除外しないかぎり範囲に含まれます。

書く量は数行で足ります。長い文章にする必要はなく、箇条書きで並べておけば十分に効きます。

「これは過剰か」を見分ける 3 つの問い

レビューで迷ったときに使える問いを挙げておきます。どれか 1 つでも「いいえ」なら、消す側に倒して構いません。

  1. 今回の依頼に、それは書かれていたか
  2. 今それが無いと、動かないか
  3. それを消すとき、他のどこも触らずに済むか

2 つ目で引っかかるものが最も多いはずです。「将来必要になりそう」で入っている実装は、今は動作に不要です。必要になった時点で足せばよく、そのときのほうが要件も具体的になっています。

3 つ目は、消す難しさの見積もりです。消すのに他の箇所を触る必要があるなら、それはすでに周囲と結びついています。結びつく前に落とすのが、いちばん安い判断です。

コツ

迷ったら「必要になったらもう一度足せるか」を考えてください。足し直せるものは、今消して構いません。

必要な作り込みとの線引き

ここまで読むと「では堅牢に作るのも過剰なのか」という疑問が出ます。線引きははっきりしています。

要件から導けるものは作り込み、要件から導けないものが過剰実装です。

たとえば、入力を受け取る画面で不正な値を弾く処理は、その画面の要件から導けます。使う人が何を入力するか分からない以上、必要な作り込みです。一方、今回扱わない種類の入力に備えた分岐は、要件から導けません。

実装判定理由
想定される入力への対応必要要件から導ける
起こりうる失敗の扱い必要運用上避けられない
使う予定のない設定項目過剰要件に無い
1 箇所しか使わない共通部品過剰今の要件では抽象化の根拠が無い

迷う場合は、その実装が無いときに困る人が具体的に思い浮かぶかを考えてください。思い浮かばないなら、まだ必要になっていません。

出てきた余りはその場で消す

範囲を書いても、余りがゼロになるわけではありません。残った分はレビューで落とします。

判断はごく単純で構いません。依頼になかった変更は、原則として消す。 必要なら次の依頼として立て直します。この線を引いておかないと、判断のたびに「これは残してもいいのでは」という迷いが入り、そのうち全部残るようになります。

FIXITFIXIT
でも、良さそうな実装なら残してもよくない?
IrodoriIrodori

残すなら、必要だと判断した記録も要ります。そこまでやりますか。

FIXITFIXIT
…消したほうが早いってこと?
IrodoriIrodori

はい。必要になったら、そのとき依頼として立てるほうが崩れません。

レビューで指摘するときの言い方

消すと決めたあと、どう伝えるかも運用に効きます。レビューの指摘は、書いた相手が人でもエージェントでも、何を基準に落とすのかが伝わる形 にしておいたほうが後が楽です。

避けたいのは「不要なので消してください」だけの指摘です。基準が伝わらないので、次も同じものが出てきます。

書くならこの形です。

この設定項目は今回の依頼に含まれていないため、削除してください。
必要になった時点で、別の変更として追加します。

理由が「依頼に含まれていない」であることを明示しておくと、判断の軸が共有されます。良し悪しの議論にしないのが要点です。 良いか悪いかを論じ始めると、残す方向に倒れやすくなります。

同じ指摘が繰り返されるようなら、指摘ではなく依頼のひな形を直してください。レビューで毎回同じことを言っている状態は、上流で防げていないという合図です。

仕組みにするなら 2 つで足りる

チームで防ぐ場合、大掛かりな仕組みは要りません。

1 つは、依頼のひな形に「今回やらないこと」の欄を作ること。書き手が範囲を意識するようになり、レビュー側も何が範囲外かを判断できます。

もう 1 つは、レビューの観点に「依頼になかった変更が混ざっていないか」を 1 行足すこと。観点として明示されていないと、良さそうなものは素通りします。

この 2 つで、過剰実装の大半は止まります。凝った仕組みを作るより、ひな形とレビュー観点に 1 行ずつ足すほうが確実に効きます。

すでに積み上がっている場合

これから防ぐ話とは別に、すでに溜まっている分の扱いも要ります。全部を一度に消すのは現実的ではないので、優先順位をつけてください。

先に手をつけるのは、これから触る予定がある場所 です。改修が入る箇所を触るついでに、使われていない分岐や設定を落とします。触る予定のない場所は、動いているかぎり急ぎません。

判断の材料としては、次の 2 つを見ます。

  • その実装が実際に呼ばれているか。呼ばれていないなら消す候補
  • 消したときに壊れるかどうかを、テストで確かめられるか

2 つ目が用意できていないと、消す判断そのものができません。過剰実装を減らす作業は、テストが無いと始まりません。 ここが弱い場合は、消す前にテストを足すほうが先になります。

作業の順番としては、次のようになります。

  1. これから触る範囲に、テストがあるかを確認する
  2. 無ければ、現状の動きを固定するテストを足す
  3. 使われていない実装を落とす
  4. テストが通ることを確認する

2 番を飛ばして 3 番から入ると、消したあとに「これで合っているのか」が分からなくなります。消す作業で怖いのは、消したこと自体ではなく、確かめられないことです。

なお、この順番は過剰実装に限らず、古い実装を整理するとき全般に使えます。整理を進めたいのにテストが無い、という状態が続いているなら、そこが本当のボトルネックです。

FIXITFIXIT

使ってないコードって、放っておいても害はなくない?

IrodoriIrodori

読む人の時間を毎回奪います。それが積もると、全体に響きます。

発注している場合はどう見るか

社外に開発を任せている場合、過剰実装は見積と保守費の両方に効いてきます。作った分だけ工数が乗り、作った分だけ後年の保守対象が増えるためです。

見分ける材料は、成果物より 要件と実装の対応 です。要件に書かれていない機能や設定が入っていないかを確認してください。入っているなら、その根拠を聞きます。

説明判断
要件の◯◯を満たすために必要妥当。要件から導けている
運用上こうしないと事故が起きる妥当。理由が具体的
将来の拡張を考えて要確認。今回の費用で払う理由が要る
一般的にこうすることが多い要確認。自社の要件から導けていない

下 2 つが多い場合は、今回の範囲を決め直したほうが安く済みます。 将来の拡張は、必要になった時点で発注するほうが要件も具体的になり、無駄が出ません。

逆に、上 2 つで説明できるものは削るべきではありません。削ると運用で事故が起きます。過剰かどうかは、量ではなく根拠の有無で判断してください。

指示の書き方そのものを整えたい場合は AI 駆動開発のプロンプト設計 を、レビューやテストを含めた全体像は AI 駆動開発の品質保証 を参照してください。

過剰を恐れて逆に振れないこと

最後に、逆側の注意を書いておきます。過剰実装を止める話をすると、必要な確認まで削る方向に振れる ことがあります。

削ってよいのは、要件から導けない実装です。想定される失敗の扱いや、入力の確認は、要件から導けるものであり削る対象ではありません。ここを混同すると、動くけれど脆いものが出来上がります。

判断に迷ったときは、前掲の線引きに戻ってください。根拠を要件に求められるかどうか。 それだけで、ほとんどの場合は決まります。

もう 1 つ、範囲を切る指示に慣れてくると、今度は範囲を狭く書きすぎて、依頼が細切れになることがあります。1 回の依頼で終わる作業が 3 回に分かれると、全体では遅くなります。切るのは影響範囲であって、作業量ではありません。

まとめ

  • 不足より過剰のほうが見過ごされやすく、指示以上のものが足される
  • 害はその場ではなく、レビュー負荷と保守対象の増加として後から出る
  • 止めるには、やることより「触らない範囲」「対応しない条件」を書く
  • 残った余りはレビューで消す。あとで判断する運用は定着してしまう
  • 依頼のひな形とレビュー観点、この 2 つを整えれば大半は防げる
  • 反動で必要な確認まで削らない。判断は常に「要件から導けるか」で行う