「何を作るか」と「どこで作るか」を分離すると、開発は壊れにくくなる
Hatched by Ryusei Nakamura
Aug 30, 2026
1 min read
2 views
88%
「このコードは何をすべきか」と問われたとき、すぐに実装の話を始めるチームは多い。しかし、もう一つの問いを見落としていないだろうか。それは、「この作業は、どの場所に置かれるべきか」である。
振る舞いを明確に記述することと、作業用の環境を安全に隔離すること。一見すると、前者はテスト設計の問題で、後者は Git の操作やツール設定の問題に見える。だが両者は、開発者の認知負荷を減らし、変更を安全に試し、チームの意図をコードの外側へ逃がさないという一点で深くつながっている。
本当に優れた開発環境とは、開発者に注意深さを要求する環境ではない。注意深くなくても、意図しない事故が起きにくい環境である。
ソフトウェア開発の失敗は、曖昧さから始まる
テストという言葉には、しばしば「実装が正しいかを後から検査するもの」という響きがある。そのため、テストを書くときでさえ、開発者は実装の細部に引っ張られやすい。内部のメソッドや条件分岐を見て、どの行を通過させるかを考え始めるからだ。
しかし、利用者や別のシステムが関心を持つのは、内部構造ではない。入力に対して何が起こるのか、どの条件でどんな結果になるのか、失敗したときに何が保証されるのかである。そこで「テスト」よりも「振る舞い」という言葉を使うと、視点が実装から価値へ移る。
たとえば、オンラインショップの割引機能を考えてみよう。
「DiscountCalculator の calculate メソッドに 1000 と 0.1 を渡し、900 が返ることを確認する」と書けば、実装の形は伝わる。しかし、これは仕様としては脆い。クラス名やメソッド名が変われば、意味まで失われてしまう。
一方で、次のように書けば、関係者が共有したい意図が見える。
会員が対象商品を購入したとき、通常価格から会員割引が適用され、支払額が減額される。
ここで重要なのは、文章が読みやすいことだけではない。何を守るべきかが、実装の都合から切り離されていることである。実装は変わっても、振る舞いが変わらない限り、チームが守るべき契約は残る。
この考え方は、テストを単なる検査装置から、設計の会話へ変える。テストは「正しいかを確認するもの」ではなく、「このソフトウェアが外部に約束することを記録するもの」になる。
場所を意識させないことも、仕様を意識させないことと同じくらい重要だ
ところが、意図を明確にしても、作業環境が混乱していれば安全性は崩れる。複数の機能を並行して開発すると、作業ツリーに未完成の変更が混ざる。別のブランチを確認したいのに、現在の変更を退避しなければならない。検証用の一時ファイルがリポジトリの中に残り、後から誰かがそれを本物の成果物と誤認する。
この種の問題は、技術的には小さく見える。しかし、開発者の頭の中に「今どの変更が、どの場所にあり、どの状態なのか」という追加の管理業務を発生させる。
Git worktree は、同じリポジトリから複数の作業場所を持つための仕組みである。ある場所ではバグ修正を進め、別の場所ではレビュー対象を確認し、さらに別の場所では実験的な変更を試せる。ブランチの切り替えによって一つの作業場所を使い回すのではなく、作業そのものを空間的に分ける発想だ。
ここで、作成先を毎回覚えたり、リポジトリ内に一時的なフォルダを増やしたりする必要がなければ、効果はさらに大きくなる。ツールがデフォルトで適切な場所を選び、作業場所の命名や配置を引き受けるからだ。
これは単なる便利機能ではない。作業場所に関する判断を自動化することで、変更内容に集中できるようにする設計である。
振る舞いを記述するときには、「どの実装を通ったか」を意識しなくてよいようにする。worktree を扱うときには、「どのフォルダを使えばよいか」を意識しなくてよいようにする。両者は同じ方向を向いている。開発者から、価値を生まない記憶作業を取り除いているのだ。
良い抽象化は、意図と事故の境界線を引く
この二つを結びつける鍵は、境界線という考え方である。
振る舞いを記述する場合、境界線は「利用者が観測できること」と「実装の内部」に引かれる。利用者が見られる結果や保証は表に出し、内部のデータ構造や関数分割は隠す。この境界があるから、実装を改善しても契約を壊さずに済む。
作業場所を分離する場合、境界線は「ある変更」と「別の変更」の間に引かれる。機能開発、レビュー、実験、緊急修正を同じ作業ツリーに押し込めなければ、それぞれの状態を独立して扱える。この境界があるから、未完成の変更が別の作業へ漏れ出しにくい。
つまり、ソフトウェアの安全性は、コードの中だけで作られるものではない。意味の境界線と、作業の境界線を揃えることによって作られる。
たとえば、決済機能を開発しているチームがあるとする。振る舞いの側では、「支払いが成功した場合に注文が確定する」「支払いが失敗した場合に注文は確定しない」という観測可能な契約を記述する。作業環境の側では、決済機能の開発、決済失敗時の再試行機能、別チームの画面改修をそれぞれ別の worktree に置く。
このとき、仕様の境界と変更の境界が対応する。どの作業場所で、どの振る舞いを変更しているのかが明確になる。もしテストが失敗しても、原因を探す範囲が狭い。レビューする側も、「この変更は何を保証し、何を変更していないのか」を把握しやすい。
反対に、仕様が実装の細部に密着し、複数の目的の変更が一つの作業場所に混在すると、二つの種類の漏れが起きる。意図が実装へ埋没し、変更が別の変更へ侵入する。前者は理解の事故であり、後者は操作の事故だが、根は同じである。異なるものを、同じ場所や同じ表現に押し込んでいる。
「人間が覚える」から「環境が守る」へ
開発現場では、事故を防ぐために手順を増やしがちだ。「このコマンドを実行する前にブランチ名を確認する」「このテストではモックの状態をリセットする」「このフォルダは一時用なのでコミットしない」といった注意書きが増えていく。
もちろん、手順が必要な場面はある。しかし、重要な安全性を人間の記憶に依存し続けるのは危険だ。疲労、割り込み、緊急対応、複数作業の並行によって、確認は簡単に抜け落ちる。
ここで使えるのが、開発環境を考えるための三層モデルである。
第一層は、意味の明示
ソフトウェアが守るべき振る舞いを、読み手が理解できる言葉で記述する。これはチームの意図を保存する層だ。テストの名前や Gherkin のような形式は、その意図を実行可能な形に近づける役割を持つ。
第二層は、変更の隔離
異なる目的の作業を、異なる作業場所や変更単位に分ける。これは意図が混ざることを防ぐ層だ。worktree の自動作成や、リポジトリ外への配置は、隔離のための判断を仕組みに移す。
第三層は、検証の自動化
明示された振る舞いと、実際のコードの結果を繰り返し照合する。ここで初めて、仕様と実装のずれを機械的に検知できる。
このモデルの面白い点は、テストだけでも、環境分離だけでも不十分なことだ。意味が明確でも変更が混ざれば検証結果を信頼しにくい。変更が完全に隔離されても、何を守るべきかが曖昧なら、整然とした間違いを作るだけである。
意味を明確にし、変更を隔離し、結果を検証する。安全な開発とは、この三つを同時に設計することである。
すぐに試せる「意図と場所」の設計
この考え方を、日々の開発に落とし込む方法は難しくない。大切なのは、新しいツールを増やすことではなく、判断をどこに置くかを見直すことだ。
まず、作業を始める前に「この変更が外部に与える振る舞いは何か」を一文で書く。内部のクラス名や関数名ではなく、利用者が観測できる結果で書く。たとえば「在庫がない商品を注文した場合、注文を確定せず、利用者に理由を伝える」のようにする。
次に、その一文に対応する変更だけを一つの作業場所に置く。緊急修正を確認するために現在の作業を中断するのではなく、別の worktree を作る。作成場所や命名を人間が毎回考えなくて済むなら、あらかじめ標準の方法として定着させる。
さらに、作業場所の名前やブランチ名だけに意味を預けない。場所は変更を隔離するためのもの、振る舞いの記述は目的を共有するためのものだと役割を分ける。名前が十分に分かりやすくても、仕様の代わりにはならないし、仕様があっても隔離の代わりにはならない。
最後に、レビューではコードの差分だけでなく、次の三点を確認する。
- この変更が保証する振る舞いは、利用者の言葉で説明できるか。
- その振る舞いに関係しない変更が、同じ作業場所や差分に混ざっていないか。
- 失敗時の状態や、変更していないことまで検証できているか。
Key Takeaways
- テストを実装の検査ではなく、ソフトウェアが外部に約束する振る舞いの記録として扱う。
- 作業場所を自動的に分離し、フォルダの配置や一時ファイルの管理を人間の記憶に依存させない。
- 「何を守るか」と「どこで変更するか」を別々に設計し、意味の境界と作業の境界を対応させる。
- 一つの変更には、一つの目的と、一つの検証可能な振る舞いを結びつける。
- 開発環境を、注意力の高い人だけが安全に使えるものではなく、注意力が落ちても事故を広げにくいものにする。
最終的に問われているのは、テストを書くか、worktree を使うかではない。もっと根本的な問いである。チームの意図を、どこに保存し、どの境界で守るのか。
意図を文章だけに置けば、実装とのずれが生まれる。コードだけに置けば、設計の理由が消える。一つの作業場所だけに置けば、変更同士が衝突する。だから、意図は振る舞いとして明示し、変更は空間として分離し、結果は自動的に検証する。
開発者の生産性とは、より速く入力する能力ではない。覚えるべきこと、混ぜてはいけないもの、毎回判断すべきことを減らす能力である。優れた抽象化は、何かを隠すだけではない。守るべきものだけを見える場所に残し、それ以外を安全に環境へ委ねる。
そう考えると、テストと作業ディレクトリは別の道具ではなくなる。どちらも、ソフトウェア開発における曖昧さと混線を減らすための境界線である。コードを壊れにくくする前に、まず意図と変更が壊れにくい置き場所を設計する。そこから、開発の安全性は始まる。
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣