- ソフトウェア開発では、設計ドキュメントからすぐにきれいなPRへつなげるのは難しく、実際にコーディングする中で前提が揺らぐため、捨てるコードで設計を探索するほうが速いことがある
- マージしない draft PR でプロトタイプや概念実証を作り、初期にレビューを受けてアプローチの方向性をそろえたうえで、設計アイデアの記録として残す流れを提案している
- この方式の前提は、最初の解法を大胆に捨てられる 組織的成熟度 であり、同じ問題を2〜3通りの方法で実装してみる姿勢はシニアリティの兆候と見なされる
- PRは特定時点の実装意図と議論を含む 発見可能なドキュメント になるが、設計ドキュメントは頻繁に更新しないと現実とずれた「undead documentation」になりやすい
- 設計ドキュメントは、複数の利害関係者のフィードバック整理、長期的なNorth Star文書、まだコーディングしにくい初期アイデア、プロトタイプがそのままデプロイされる危険がある組織では依然として必要である
Throwaway PRで設計を探索する
- 理想的な開発フローは、設計ドキュメントを書き、小さなPRを順にマージして機能をデプロイし、Git履歴をきれいに保つ形に近い
- 実際には、コーディングを始めてから初めて設計ドキュメントの前提が揺らぎ、どの順序でリリースするかを再判断しなければならないことが多い
- そのため、まず大きなコード実験を作り、その結果をもとに実際の計画を立てるやり方のほうが効率的な場合がある
-
提案される手順
- マージする意図のない draft PR でプロトタイプや概念実証を実装する
- 大規模なリファクタリングや機能へのアプローチについて、初期段階で他の人の視点を得て 方向性のアラインメント を取る
- draft PRの中にアプローチを文書化し、設計アイデアの歴史的記録として残す
- できるだけ早い時点で、draft PR全体を捨てる準備をしておく
- draft PRから実際にデプロイ可能なPRを段階的に切り出し、およそ1週間ほどかけてクリーンなデプロイ用PRへ分割する
- 各PRを段階化しながら、テストと堅牢性の穴を徐々に埋めていく
-
この方式が求めるチームの条件
- 最も重要な条件は、自分が書いた最初のアイデアを捨てられる 成熟度 である
- 同じ問題を2〜3通りの方法でコーディングしてみることに抵抗がないのは、シニアリティの重要な兆候と見なせる
- 価値の提供は、本番環境に入ったコード行数ではなく、組織が得た知識にある
- 重要な部分で早い段階にアラインメントを得られれば、その後のプロトタイピングは単なる無駄で終わらない
- コードベースの中核部分を素早くつなぎ合わせられるほど慣れている必要があり、シニア社員にはそのレベルの気楽さが求められる
- この方式は個人だけでなく、チーム単位でも実行できる
PRの文書化と設計ドキュメントの実際の役割
- PRは開発者にとって有用なドキュメント形式のひとつである
- ある実装がなぜその形になったのかを理解するとき、最初に探しに行く場所のひとつである
- 現在の状態を反映していると主張するのではなく、特定時点の状態を収めた 歴史的成果物 として残る
- 設計ドキュメントは、頻繁に最新状態へ保たないと、古い現実を反映する undead documentation になりやすい
- プロトタイプは「言うより見せる」に向いており、変化を起こす際にはドキュメントよりコードのほうが効果的なことがある
- ただし規律のない組織では、プロトタイプが「質問」ではなく「答え」として受け取られる危険がある
- 本来の意図は「これをやるべきか、それとも別のことをやるべきか?」に近い
- 組織が「これをやるべきだ」と受け取ると問題が起きる
-
設計ドキュメントが依然として適している場合
- 複数の利害関係者、管理者、外部チームからのフィードバックを整理して保管する必要があるときに有用である
- GitHubだけでは、そのような協業を処理しにくいことがある
- アイデアがあまりに概念的かつ長期的で、すぐにコーディングしにくいなら、ある程度の North Star文書 が役立つ
- 文章で表現するほうが最初のコード草案より効率的だったり、まだコードベースへのオンボーディングが十分でなく、フィードバック用の草案を残したいときに有用である
- 会社が最初の解法を捨てる規律もなく、すぐに本番デプロイを押し進めるなら、プロトタイプがそのまま「解法」として固定化されかねない
- ジュニア社員がシニア開発者のアイデア実装に反論しにくい組織では、より安全に問いを立てられる 柔らかい成果物 が必要になることがある
-
設計ドキュメントがよくない理由で使われる場合
- 規律や熟練度が不足したチームでは、プロセスを遅らせるための手段になりうる
- 文書化の目的で使われたとしても、たいていすぐに古くなった状態になる
- すべての設計上の問いに前もって答えるのは難しく、実際の問題はコードを書いてから初めて明らかになる
- チームが十分な規律を持てるなら、「設計」より ハックしながら学ぶやり方 のほうが効率的な場合がある
1件のコメント
Hacker News のコメント
これは プロトタイピング と呼ばれるもので、設計プロセスにおける価値ある部分であり、人によっては「pathfinding」とも呼ぶ。
こうしたものはすべて設計への入力だが、適切な規模の設計はやはり必要だ。そうでないと、その場その場で成り行き任せに作っているだけになる。解こうとしている問題は何で、解法は何なのかを定義しなければならない。場合によっては正式なレビューなしの1ページ文書で十分なこともあるし、数週間のレビューとフィードバックの反復を伴う複数ページの文書が必要なこともある。
忘れてはいけない:「数週間のコーディングで、数時間の計画を節約できる」 ;)
むしろ逆のほうがはるかによく当てはまっていた。人々は計画に計画を重ね、その計画が無意味な水準を超えて、生産性を積極的に損なうようになる。
数週間のコーディングが数時間の計画を節約してくれることもあるが、数週間の計画も無駄になり得る。紙の上では、筋が通らないことや不可能なことも簡単に書けてしまう。たとえば「ユニコーンの艦隊を半分悲しい色に塗る」といったことだ。
理想的には、設計とプロトタイプは一緒に進化すべきで、一方の反復がもう一方の次の反復を後押ししながら、DNA の二重らせんのようにらせん状に発展していくべきだ。プロトタイプを作る側に傾いたときの大きな利点は、1ラウンドが終わると実際に何かをするソフトウェアが残ることだ。設計のラウンドが終わっても、実質的に残るものはあまりない。
そして実装段階に至るまで、コードの捨てやすさを優先し続けるべきだ。削除しやすいほどよい。
しかし、設計文書や何らかの仕様がないソフトウェア工学は、どれほど簡潔であっても工学ではなく、木の上の小屋作りに近い。
プロジェクトの規模と重要度が大きくなるほど、問題と技術的負債はより早く表面化し始める。
文章を書くことは、問題空間を探索する うえで本当に有益だ。
問題を確実に理解したと思っていたのに、いざ書き始めると新しく重要な疑問が生まれたことが何度もある。こうしたことは、たいてい抽象化された視点からのほうがよく見えたり、最初の数回のリリースマイルストーンでは表に出なかったりする。
キャリア初期に出会ったメンターを思い出す。決済ゲートウェイに active/active 構成を後から設計した人で、Lucidchart を開きながら「この図は私の人生の6カ月を表している」と言っていた。
いつも必要だったり役に立ったりするわけではないが、必要なときには数日の計画で数週間のコーディングを節約できる。
問題が起きる箇所をずっと前から予測できたので、プロジェクトはいつもスムーズだった。問題や不確実性が見えたら、その部分だけをモデル化し、またホワイトボードに戻って続きを進めていた。
たとえるなら、地図で車の旅を計画するようなものだ。最近の設計文書は道だけを示してすぐ運転し始めるようなものだが、その上司のホワイトボード上の地図は、どこで給油するか、観光地の営業時間、国境通過の書類、全体予算、非常用キット、Plan A と Plan B まで「過剰に計画」していた。
とても退屈だが、使い捨てコードよりはずっとよかった。今では、過剰に計画しないことが怠慢に感じられる。
もちろん「誰でも一発殴られるまでは計画を持っている」という言葉は正しいが、それは戦争、政治、交渉に当てはまるもので、コーディングには当てはまらない。
結局、良い PR にも多くの文章が含まれていて、同じ効果をもたらす。よく文書化されたドラフト PR は、純粋な設計提案より優れていると思う。文章だけを書いていると、コードの中にいるときにだけ思い浮かぶ重要な制約を忘れてしまうからだ。
-- Dick Guindon
設計文書で経験した最大の問題は、誰も読まないという点だ。雇用主が要求していても同じだ。
プロトタイピングで経験した最大の問題は、人々がそれを「リリース用コード」と見なし、最終コードとして使うよう強要することだ。
だから混合アプローチが最も合っていた。計画と文書化には多くの時間を使うが、基本的には自分自身のために行い、後で最終製品に使っても問題ないように リリース品質のプロトタイプコード を書く。
設計文書は、書いた本人以外には誰もきちんと理解できない生のメモの塊になり、人々はそうしたメモを読むことを恐れるようになる。
しかし設計文書の作成者に、これは学校で採点される期末レポートのようなものだと伝えれば、何度か書き直すうちに文章はかなりよくなる。症状はプロトタイピングと同じだ。人々はドラフト品質の設計文書を書いておきながら、魔法のようにより広い読者に合った良い文章になることを期待している。プロトタイプコードを何度かリファクタリングする必要があるのと同じように、設計文書にも何度かの編集が必要だ。
契約更新を避けるには、期限までに何かを作ってリリースする必要があり、その契約には数百万ドルがかかる見込みだった。ところが、計画されていたリソースとアプローチでは期限内に終わらないことが分かった。
そこで、一時的で部分的、かつ最適ではないバージョンを素早く作ってもよいという承認を得て、そのおかげで時間どおりに離陸できた。
そのおかげで、ほかの人たちが翼のその部分について恒久的でちゃんとしたバージョンを完成させるまでの間、しばらく飛び続けることができた。
実際に飛行中、元の設計から抜けていた要件も見つかった。そのため、ちゃんとしたバージョンのプロダクションリリースは遅れたが、私のハック版にはすぐ追加でき、飛行を維持し続けることができた。
私のハック版はプロダクション支援ツールとしての役割も果たす。恒久版にバグがあって止めなければならないときには、代替経路にもなる。部分的で不完全なハックではあるが、利点はある。
使った言語があまり一般的でないという理由で不満を言った人もいた。しかし、既存のリソースとアプローチではそもそも離陸できなかったことを忘れてはならない。
期限に間に合わせるには、好まれる言語でより多くの、あるいはより速い開発者が必要だったはずだ。現在の社員の誰かが、私を含めて、好まれる言語で私のマイナー言語によるハックと同じくらい生産的に動ける余裕と能力を持っていたなら、その人が恒久的な解決策を期限内に作るよう割り当てられていただろう。そういう選択肢はなかった。
いずれにせよ、既存のプロダクション支援ツールがあるなら、プロトタイプ機能がしばらく居座れる場所にもなる。
これもまた意見記事の一つだが、データもなければ具体例すらない。
すべてのソフトウェアエンジニアが強い意見を持っているのは分かるが、これは弱い主張だ。何が正しいかを見るために大量にコードを書くのが仕事だと思っているなら、じきにGPTに置き換えられるだろう。より速く、より安くできるからだ。難しい部分は常に、何を作るべきかについて合意を形成することにあり、コーディングでその問題から逃れることはできない。
要件が明確で、自分が何を提供するのかも全員にとって明確なら必要ない。そのままプロトタイピングに進めばいい。しかし本格的なプロジェクトでは、そういうケースはまれだ。ステークホルダーから引き出さなければならない未知の未知が常にあり、技術分析はそれを行うための良い方法だ。
四角形と点線だけでは限界がある。実際のコードから離れていると、本当の制約を忘れてしまう。実際に速度を落とすものはGoogle Docsには現れない。「私が考えているのはこれです」と言ってドラフトPRを指し示すほうが、私の経験ではずっと先に進める。
それにその通り、これは100%意見だ。個人ブログであって査読付き論文ではないのだから :) 間違っていても構わない。
コードのように会話を引き留めておく実体がなければ、抽象設計をめぐる議論は結局、「私の想像上のひもはあなたの想像上のひもより長い」というような、結論のない論争に流れがちだ。
私の経験では、コードに対するフィードバックと設計に対するフィードバックは種類がものすごく違う。
設計文書は、全員に問題空間を考えさせる「なぜ」という質問を促す。たとえば「社内にはまだRustに熟達した人がいないのに、なぜRustのWebサーバーを提案するのですか?」といったコメントができる。
こうした微妙な質問は、プロトタイプが動き始めた後ではずっと提起しにくい。「チームの経験がなぜ重要なんですか? こんなにうまく動いているじゃないですか! 邪魔さえされなければ、このプロトタイプを磨き上げて1週間以内にプロダクションへ入れられます!」となりがちだ。
特に、動くコードではなく設計だけをレビューしているときはなおさらだ。
私たちは、ソフトウェア作業がきれいで整った流れをたどると想像している。
設計文書を書き、PRで機能をリリースするための小さな漸進的変更を作り、Gitの履歴はきれいで秩序立っている。着実な前進のように見える。
誰がこんなふうに想像するのだろうか? ソフトウェア工学の授業を教える教授たちだろうか?
これは、散文、エッセイ、物語、小説などを、アウトラインを書いてからそれを散文で「埋める」ように書くと思っている人たちを思い起こさせる。まるでその過程で、文書を書き直したり再構成したりする必要のある発見がまったくないかのようだ。誰もそんなふうには書かない。初稿は常にひどいもので、良い文章のほとんどは大幅に直された結果だ。
コードを書くことは、家や橋を建てることよりも、文章を書くことにはるかに近い。
新しいロジックを1行ずつ追い、変数とメモリを見る過程は、コードを改善するのに本当に役立つ。「ああ、このローカル変数はいらないな」「ここはデバッグしやすいように一時変数を追加すべきだ」「反復しているコレクションが空だと、このコードはおかしくなるな」といったことを発見する。
どれだけ年を取っても、どれだけ多くのコードを書いても、新しく書いたコードをデバッグするときは常に新しいことを発見する。作家が初稿を書いた後に読み返したり、自分自身や他人に声に出して読んだりすることになぞらえられそうだ。
設計上の意思決定を一つの文書として公式化しようとするよりも、進行中のコメントスレッドとして記録するこのプロセスが本当に好きだ。
私はGitHub Issueをこのように使っているが、機能的にはPRを使うのと同じだ。PRは実質的には、コードブランチが付いたGitHub Issueである。
私のやり方についてさらに書いた記事はこちら: https://simonwillison.net/2022/Jan/12/how-i-build-a-feature/...
言い換えると、そのスレッドを最終文書としてどう要約するのか?
両者が相互排他的だとは思わない
設計ドキュメントはより広い概念であり、目的はコミュニケーションである
時にはコード以外の方法で伝える必要がある。図、画像、文章などが必要になる
作成者本人でない人や、コードにかなり精通していない人が、変更点をひと目で理解するのは非常に難しい。読む人が変更を文脈の中で理解するための正しいメンタルモデルを素早く作るには、高レベルの説明とドキュメントが必要である
1000行のdiffを見て、それが何をしているのか、さらに重要なことに上流と下流へどのような影響を与えるのかを正確に言えるなら、嘘をついているか、私が本当にうらやむほど完全に閉じた検証可能な環境で働いているのだろう
設計ドキュメントは、可能な選択肢の中からプロトタイプの数を2〜3個に絞るのに役立つ。まったく新しいものを追加しようと探索するときには特に有用である
見せることは語ることより優れていると感じるが、新しく加わった人はコードよりも設計ドキュメントを通じたほうが理解しやすい