
【コード哲学エッセイ】 同じコードが 2 つあるとき、 僕はまず統合しない
早すぎる DRY が壊すもの
エディタをスクロールしていると、ときどき目が止まります。
似た処理。
ほぼ同じ変数名。
コピペの匂いがする、あの並び。
かつての僕は、その瞬間に少しだけ誇らしくなりました。
気づいた自分に、小さな拍手を送るみたいに。
utils に関数を切り出す。
common フォルダを増やす。
重複を消したリポジトリは、きれいに見える。
DRY —— Don't Repeat Yourself。
繰り返すなと教わった言葉は、正義みたいに響いていました。
2 つ並んだ瞬間に手が動いてしまう
フリーランスになって数年、小さな管理画面の改修を任されたことがあります。
ユーザー向けフォームと管理者向けフォーム。
どちらにも、入力チェックのロジックが必要でした。
最初は別々に書いた。
数日後、並べてみると 7 割ほど同じだった。
僕は迷わず共通化しました。
validateInput のような名前をつけ、2 つの画面から呼び出す形にした。
コミットメッセージには、確か「重複を削除」と書いたはずです。
胸のなかは、掃除が終わった直後みたいに軽かった。
似ているだけで変わる理由は違っていた
数週間後、仕様が動きました。
ユーザー側には、優しいエラーメッセージと入力のたびに軽いリアルタイム検証。
管理者側には、厳しめのルールと送信時だけまとめて検証。
似ていたのは見た目だけで、変わる理由は別物だった。
共通化した関数は、すぐに if (isAdmin) を増やし始めました。
引数は膨らみ、コメントは「ここだけ例外」と増殖する。
2 つに分かれていた変更が、一つの関数のなかで喧嘩を始めた。
あのとき学んだのは、重複は汚れではないということでした。
まだ物語が分岐していない 2 つの線が、たまたま並んで見えただけかもしれない。
早すぎる DRY が壊すもの
DRY 自体が悪いわけじゃない。
壊すのは、早すぎる統合です。
2 つあるコードを一つにまとめると、一見行数は減る。
けれど、未来の変更コストは必ずしも減らない。
むしろ、違う理由で変わるはずだった変更が一箇所に縛られる。
抽象化エッセイで書いた請求の BillingManager も同族でした。
「重複を消したい」という気持ちが、早い抽象化を呼び込む。
いまの僕は、重複を見つけたとき、こう思います。
これは、本当に同じ物語のコピーか。
それとも、まだ別れていない双子か。
統合の前に僕が置く 3 つの問い
2 つ並んだとき、僕はすぐには関数を切り出しません。
代わりに、3 つだけ問います。
なぜ、今似て見えるのか。
次に変わるとき、同じ方向に変わるか。
統合したあと、誰がその変更の責任を持つか。
答えがはっきりしないなら、しばらく 2 つのままにしておく。
コピペのままでもいい。
「TODO: 3 回目が来たら見直す」
と一行書いておくだけでも、未来の自分を救える。
3 回、同じ形の変更が来たら、ようやく統合を検討する。
そのとき初めて、重複は偶然の一致ではなく「本当の重複」に近づいている。
統合は掃除ではない。
変更の流れを読んだあとに引く境界の線だと思っています。
2 つあることは恥じなくていい
コードレビューで「重複がありますね」と言われると、つい反射的に直したくなる。
僕もそうでした。
けれど、6 月の梅雨のなかで思うのは、急いでひとつにまとめる勇気よりも 2 つを眺める忍耐のほうが、ときに価値があるということです。
境界を引く前に、物語が分岐するかどうかを見る。
設定値を隠す前に、責任の境目を見る。
先週の自分が書いた言葉と同じ姿勢です。
きれいなリポジトリは、写真のように見える。
現場で育つコードは、地図のようにしばらく線が重なってもいい。
僕がいまエディタの前で思うこと
重複を見つけた朝、僕は昔の自分に声をかけます。
「今、統合したいのは、未来の変更を安くするためか。
それとも、きれいに見せるためか」
後者なら、まだ早い。
前者でも答えが曖昧なら、2 つのままが正解かもしれない。
DRY は羅針盤にはなる。
けれど、羅針盤を握りしめたまま走り出すと崖から落ちる。
同じコードが 2 つあるとき、僕はまず統合しない。
3 つ目の変化が来るまで、並べて眺める。
その静かな時間が、あとから一番つらいリファクタリングを未然に遠ざけてくれることがあるのです。
ひとりごと
若い頃の僕は、重複を見つけると勝った気分になっていました。
きれいな diff に、少しだけ酔っていたのかもしれません。
いまは、2 つ並んだ行を眺める時間が少しだけ長くなった。
それが、設計の成熟なのかもしれないと思います。
同じように、早すぎる統合で痛い目を見た誰かに届けばうれしいです。

【note 質問箱】※ 新機能
「聞きたいけど、聞けない」
そういう質問ほど、
実は誰かの役に立つ。
note質問箱、
開けました。
フリーランス 15 年目のエンジニアに
なんでも聞いてみてください 📮
👇️ フォロワー限定
(後々、メンバーシップのみになる予定)
https://note.com/qa/digiangler777
Substack はじめました
ここまで読んでくださり、ありがとうございました。
X では短い言葉で、note では整理した文章で発信していますが、Substack では、もっと途中経過の思考や削りきらなかった葛藤、技術者として日々考えていることを書いています。
もし興味があれば、覗いてみてください。
会社員(元システムエンジニア)からフリーランスとなり、
15 年目に突入しました。
納期と障害対応に追われる毎日の中で、
「もっと自由に、もっと本質的にものづくりがしたい」
そう思ったのが独立のきっかけです。
現在は、技術と文章を軸に、
仕事がラクになる仕組みや続けられる働き方を発信しています。
【フリーランスになって15年目突入】
— おおとろ|フリーランス開発者 × ストーリーテラー (@digiangler) March 3, 2026
14年という月日は長いようで、
あっという間だった。
成功したと言えるほどの派手さはないけれど、
今日までエンジニアとしてご飯を食べ、
新しいコードを書けている。
それだけで十分幸せなことなんだと思う。
明日は明日で、また淡々と、…
あわせて読みたい
▼ 共通化と抽象化の勘違いに気づいたときに
何を共通化するかよりも、どの変更を安くしたいか。
今回の統合しないことと、並べて読みたい設計の土台です。
▼ 境界を引く判断とセットで考えたいときに
6 月のコード哲学エッセイの前篇。
統合も、早く引かない線引きのひとつです。
▼ 重複を残したことが戦略だったときに
納期前に重複を増やした話。
DRY を急がないことと、負債の付け方は表裏一体です。
次の一歩を一緒に決める作戦会議室へ
リファクタリングのタイミングや現場で使える設計の切り方、一人で迷う夜もあると思います。
作戦会議室では、そうした判断を小さく分け合える場所にしたいです。
必要なときだけ、覗いてみてください。