ソフトウェア設計

YAGNIまとめ、開発者の「いつか使うだろう」が高くつく理由

「あとで必要になりそうですが、先に作っておきますか?」

読了 4 分
YAGNIまとめ、開発者の「いつか使うだろう」が高くつく理由のカバー画像

「あとで必要になりそうですが、先に作っておきますか?」

開発していると、この誘惑は本当によく訪れます。設定オプションを先に用意し、多言語対応の構造も先に整え、管理画面から変更できるようにテーブルまで先に作ってしまいます。

今日取り上げるYAGNIは、まさにこの誘惑に正面から「いいえ」と答える原則です。KISS、DRYとともに、開発原則の三本柱と呼ばれています。

YAGNIは「You Aren’t Gonna Need It」の略です。「それ、どうせ必要ないよ」という意味です。

エクストリームプログラミング(XP)という開発手法から生まれた言葉で、ケント・ベックやロン・ジェフリーズなどXP陣営の人々が口癖のように使っていた表現が、原則として定着したものです。

核心となる主張は一つです。

機能は実際に必要になったときに実装する。必要になりそうだと予測したときではありません。


先に作ると何が問題なのか?

「先に作っておけば、あとで楽ですよね?」という反論がすぐ出てきそうです。問題は、その予測のほとんどが外れることです。

マーティン・ファウラーはこのテーマについてまとめた記事で、先に作った機能のコストを四つに分けています。

コスト 内容
実装コスト 今すぐ使わない機能を作るために費やす時間
遅延コスト その時間で作るべきだった本当の機能が遅れること
維持コスト 使わないコードにも、テスト・リファクタリング・バグ修正が継続的について回ること
修正コスト 実際に必要になった時点では要件が変わっていて、作り直さなければならないこと

一番痛いのは最後です。「あとで」が本当に来たとき、その時点の要件は、予想していた形とほぼ必ず違います。結局、先に作ったコードを作り直すコストまで二重に払うことになります。


実務でYAGNIが破られる場面

言葉にすると皆うなずきますが、実際には次のような形で忍び込んできます。

1. パラメータを先に用意する

// 今はメール通知だけですが
func sendNotification(user: User, message: String, channel: String = "email",
                      retryCount: Int = 3, priority: String = "normal",
                      template: String? = nil) {
    // channelこの "email"場合にだけ動作するコード
}

呼び出し元はすべてsendNotification(user: user, message: msg)だけです。残りのパラメータは「あとでSlack通知を追加するときに使うため」に作ったのですが、Slack通知の要件は結局入りませんでした。

2. プロトコルを先に用意する

実装が一つしかないのに、先にプロトコルを作るケースです。UserServiceを一つ作りながらUserServiceProtocolも同時に作るパターンですが、二つ目の実装が登場するまで、そのプロトコルはファイル数を増やすだけの飾りです。

3. 「設定に切り出しておくと便利ですよね」

ハードコードを恐れて、すべての値を設定ファイルや管理画面に切り出すケースです。実際にはその設定を変更することは年に一度もなく、設定が増えるほど「この値を変えるとどこに影響しますか?」という質問だけが増えていきます。

使わないオプションにも維持コストはきちんとかかります
使わないオプションにも維持コストはきちんとかかります

YAGNIではないもの

誤解を防ぐために、線引きしておきます。YAGNIは次のような意味ではありません。

まず、設計をするなという意味ではありません。コードを変更しやすくする努力(よい名前、小さな関数、テスト)は今すぐ価値があるため、YAGNIの対象ではありません。むしろコードを変更しやすくしておけば、「必要になったそのとき」に素早く作れます。

また、後戻りしにくい決定まで先送りしろという意味でもありません。データベースの選択やAPI公開仕様のように、一度決めると変更が難しいものは、先に検討するのが正しいでしょう。YAGNIが対象とするのは、「あとで簡単に追加できるのに先に作る機能」です。


私が使っている判断基準

私は「先に作っておこうか?」と思ったとき、二つのことを尋ねます。

この機能が必要だという根拠はロードマップにあるのか、それとも自分の想像の中にあるのか?

あとで追加すると、今よりはるかに高くつくのか?

根拠が想像で、あとから追加してもコストがほぼ同じなら、作りません。ほとんどの場合はこれに当てはまると感じます。

二つの質問で十分に判断できると感じます
二つの質問で十分に判断できると感じます
必要になった日に作っても遅くありません
必要になった日に作っても遅くありません

まとめ

YAGNIの原則から持ち帰ることは三つです。

  • 機能は必要になったときに作りましょう。必要になりそうなときではありません。
  • 先に作った機能は、実装・遅延・維持・修正のコストを四重に請求してきます。
  • ただし、よい設計習慣と後戻りしにくい決定はYAGNIの対象ではありません。

KISS、DRYに続いてYAGNIまで並べてみると、三つの原則は結局一つの文にまとまります。今日必要なものを、シンプルに、一か所だけに作ること。

「いつか使うだろう」と作ったまま眠っている機能が一つでもあるなら、2年後に自分の手で削除することになるかもしれません。