設計がうまくいかない現場では、構造や技術よりも先に「判断」が見えなくなっていることが多い。本書は、モノリスや設計不良を単なる実装の問題としてではなく、「どの判断が、どこで、なぜ行われているのか」という視点から捉え直す。
判断を見つけ、切り出し、名前をつけ、動かし、変化を追い、そして説明できるようにする。
設計をセンスや経験則に頼らず、再現可能な思考として身に付けたいエンジニア、テックリードのための一冊。
設計がうまくいかない現場では、構造や技術よりも先に「判断」が見えなくなっていることが多い。本書は、モノリスや設計不良を単なる実装の問題としてではなく、「どの判断が、どこで、なぜ行われているのか」という視点から捉え直す。
判断を見つけ、切り出し、名前をつけ、動かし、変化を追い、そして説明できるようにする。
設計をセンスや経験則に頼らず、再現可能な思考として身に付けたいエンジニア、テックリードのための一冊。
設計ができないのではなく、判断が残っていないだけ 設計が壊れるのは、いつか 良い設計者は、うまいコードを書いているとは限らない モノリスは、問題そのものではない 構造より先に、判断がある 再現できなかったのは、技術ではない この本が扱うのは「正解」ではない 設計とは、未来に対する判断である 設計ができないのではなく、判断が残っていないだけ 多くの現場では、 「設計が弱い」「設計ができていない」 という言葉が使われます。 コードが複雑になっている。 変更に弱い。 触るのが怖い。 そうした状態をまとめて、 「設計の問題」と呼ぶことは珍しくありません。 ただし本書では、 この捉え方を少しだけ変えます。 多くの場合、 問題は設計そのものではありません。 判断が、残っていないのです。 設計が壊れるのは、いつか 設計が壊れる瞬間は、 突然訪れるわけではありません。 ある日いきなり破綻するのではなく、 小さな判断が、少しずつ積み重なった結果として現れます。 たとえば、 とりあえず今はこれでいい。 前からこうなっている。 あとで直せばいい。 ここまで影響しないと思った。 こうした判断自体が、 必ずしも間違っているわけではありません。 問題は、 その判断がどんな前提で行われたのかが、 コードにも、ドキュメントにも、 残っていないことです。 設計が壊れるのは、判断の理由が失われたときです。 良い設計者は、うまいコードを書いているとは限らない 設計ができる人、という言葉から、 次のような人物像を思い浮かべる人も多いかもしれません。 抽象化がうまい人。 新しいアーキテクチャに詳しい人。 きれいなコードを書ける人。 しかし本書では、 それを設計者の条件だとは考えません。 良い設計者とは、 判断を説明できる人です。 なぜこの構造にしたのか。 なぜ今はやらなかったのか。 なぜ将来の変更を見送ったのか。 それらを、 感覚や雰囲気ではなく、 後付けの理由でもなく、 当時の制約と目的を使って説明できること。 設計とは、構造ではなく、説明可能な判断です。 モノリスは、問題そのものではない モノリスは、 しばしば問題視されます。 ただし本書では、 モノリスを悪者にはしません。 モノリスとは、 過去の判断が積み重なった結果です。 問題になるのは、 その判断が今も有効なのか分からない。 なぜそうなったのか説明できない。 変えようとしても、判断材料が残っていない。 こうした状態に陥っていることです。 問題は構造ではなく、判断の履歴が失われていることです。 ...
判断は、どこに散らばっていくのか 判断は、いつも一か所に書かれるわけではない 条件分岐は、判断の化石である コメントが消えたとき、判断も消える 設計ドキュメントが読まれなくなる理由 判断は、人の頭の中に集約される 属人化とは、判断が共有されていない状態である 判断は、なぜ散らばるのか この章のまとめ 判断は、どこに散らばっていくのか 設計が壊れる原因は、 判断が間違っていたからではありません。 多くの場合、 判断が散らばり、追えなくなったことが原因です。 この章では、 判断がどのようにコードベースの中に散在し、 やがて誰にも把握できなくなっていくのかを見ていきます。 判断は、いつも一か所に書かれるわけではない 一つの機能を実装するとき、 判断は一回で終わるわけではありません。 画面の責務をどう分けるか。 どこでデータを加工するか。 例外はどこで握りつぶすか。 将来増えそうな仕様を考慮するか。 これらは、 実装のあちこちで、少しずつ行われます。 しかもその多くは、 「判断した」という自覚すらないまま下されています。 判断は、気づかないうちに行われます。 条件分岐は、判断の化石である コードの中で、 もっとも分かりやすい判断の痕跡は、条件分岐です。 if。 when。 早期 return。 それらはすべて、 「どちらを選ぶか」という判断の結果です。 なぜこの条件が存在するのか。 なぜこの分岐は統合されていないのか。 なぜここで例外にしているのか。 理由が分かるうちは、 その判断は生きています。 しかし理由が分からなくなった瞬間、 それは 判断の化石 になります。 コメントが消えたとき、判断も消える 判断を残す方法として、 コメントを書く人も多いでしょう。 しかしコメントは、 とても壊れやすい存在です。 リファクタリングで消される。 意味が古くなる。 「コードを見れば分かる」と判断されて削除される。 そしてコメントが消えると、 判断の前提も一緒に消えます。 残るのは、 なぜ存在するのか分からない構造です。 設計ドキュメントが読まれなくなる理由 「判断はドキュメントに書いてある」 というケースもあります。 しかし多くの現場で、 設計ドキュメントは次第に読まれなくなります。 なぜでしょうか。 理由は単純です。 コードとズレるからです。 仕様変更。 例外対応。 場当たり的な修正。 ...
設計とは、判断の軸を一本通すこと 判断が強い設計には「一本の軸」がある 軸がない設計は、すべて場当たりになる 設計の仕事は「選択肢を減らす」こと 軸とは「何を守るか」の宣言である 軸があれば、判断は再利用できる 構造は、軸の副産物である この章のまとめ 設計とは、判断の軸を一本通すこと 設計の話になると、 よくこんな言葉が出てきます。 責務を分離する。 関心事を分ける。 疎結合にする。 これらはすべて、 設計において重要な考え方です。 しかし本書では、 それらを個別のテクニックとしては扱いません。 なぜなら、 それらはすべて 結果として現れるもの だからです。 判断が強い設計には「一本の軸」がある 良い設計を眺めると、 ある共通点があります。 それは、 判断の軸が一貫している ことです。 どの責務を分けるか。 どこにロジックを置くか。 どこで例外を吸収するか。 それらの判断が、 同じ方向を向いています。 一方で、 設計が崩れているコードでは、 判断の基準が場所ごとに違います。 ある場所では変更頻度を重視し、 別の場所では実装の楽さを優先し、 さらに別の場所では将来拡張を想定する。 軸が複数あると、設計は必ず歪みます。 軸がない設計は、すべて場当たりになる 判断の軸が明示されていない場合、 設計はどうなるでしょうか。 答えは単純です。 その場で一番納得しやすい判断が選ばれます。 今すぐ直せるか。 影響が少なそうか。 説明しやすいか。 これらは、 判断基準として間違ってはいません。 しかしそれが積み重なると、 判断同士が噛み合わなくなります。 結果として、 「なぜこうなっているのか分からない構造」 が生まれます。 設計の仕事は「選択肢を減らす」こと 設計というと、 選択肢を増やす行為だと思われがちです。 将来に備える。 拡張ポイントを作る。 何でもできる構造にする。 しかし実際には、 良い設計ほど、選択肢を減らします。 この変更は、ここに影響する。 この責務は、ここにしか書かない。 この種類の判断は、ここでまとめて行う。 判断の置き場所を固定すること。 それが、設計の重要な役割です。 軸とは「何を守るか」の宣言である 判断の軸とは、 言い換えると「何を守るか」です。 ...
判断の軸を、コードの外に逃がさない 軸が失われる一番の理由 判断は「読む人が必ず通る場所」に置く 命名は、判断を閉じ込める最初の手段 層を作ることは、判断の担当を決めること コメントを書くなら「なぜ」だけを書く テストは、判断を固定する最後の砦 判断を書かない設計は、必ず口頭説明に戻る この章のまとめ 判断の軸を、コードの外に逃がさない 判断の軸が重要だ、 という話までは、 多くのエンジニアが同意します。 問題は、その次です。 判断の軸は、 どこに置けばよいのでしょうか。 頭の中でしょうか。 設計ドキュメントでしょうか。 コードでしょうか。 この章では、 判断の軸を「消えにくい形」で残す方法を考えます。 軸が失われる一番の理由 判断の軸が失われる理由は、 実はとても単純です。 軸が、コードの外にあるからです。 ドキュメント Wiki 設計資料 それらは悪ではありません。 しかし、 コードと更新タイミングがズレた瞬間、 信頼されなくなります。 結果として、 人はコードだけを見るようになります。 そしてコードの中に、 判断の理由が見つからなくなります。 判断は「読む人が必ず通る場所」に置く 判断の軸を残すための原則は、 一つだけです。 読む人が、必ず通る場所に置くこと。 誰も読まないドキュメントに、 重要な判断を書いても意味はありません。 一方で、 必ず読まれる場所があります。 それは、 コードです。 正確には、 コードを理解するために、 必ず目に入る構造です。 命名は、判断を閉じ込める最初の手段 もっとも軽く、 もっとも効果的な方法は、 命名です。 なぜこのクラスが存在するのか。 なぜこの責務が切り出されているのか。 それが名前に現れていれば、 読む人は自然に軸を追えます。 逆に、 無難で抽象的な名前は、 判断を隠します。 Manager Helper Util これらは、 判断を先送りにした結果です。 命名は、判断を固定する行為です。 層を作ることは、判断の担当を決めること レイヤー分割も、 判断を残すための手段です。 どこで判断するのか。 どこでは判断しないのか。 ...
失われた判断を、既存コードから読み解く 最初にやってはいけないこと コードは、判断の痕跡でできている 「変えにくい場所」から見る 不自然な一貫性を探す 変更履歴は、判断の化石層である 軸は「正解」ではなく「現実」から見つける この章のまとめ 失われた判断を、既存コードから読み解く 設計の話をすると、 しばしばこう言われます、 「それは新規開発だからできた話ですよね」、 既にコードがあり、 既にモノリスになっていて、 既に判断が失われている場合、 どうすればよいのでしょうか、 この章では、 今あるコードを出発点として、 判断の軸を見つけ直す方法を扱います、 最初にやってはいけないこと 既存コードを前にしたとき、 多くのエンジニアが最初にやりがちなことがあります、 それは、 「理想的な構造」を思い描くことです、 レイヤーを引き直す、 責務を整理する、 きれいなアーキテクチャに作り替える、 気持ちはよく分かります、 しかし、このアプローチはほぼ確実に失敗します、 なぜなら、 現状の判断を理解しないまま、 別の判断を上書きしようとするからです、 コードは、判断の痕跡でできている どれだけ荒れて見えるコードでも、 そこには必ず判断の痕跡があります、 意味の分からない条件分岐、 不自然な責務の集まり、 やたらと慎重なガード、 それらは偶然ではありません、 誰かが、 何かを恐れ、 何かを避け、 何かを守ろうとした結果です、 コードは、過去の判断の集合体です、 「変えにくい場所」から見る 判断の軸を探すとき、 まず注目すべき場所があります、 それは、 誰も触りたがらない場所です、 変更すると壊れそう、 影響範囲が読めない、 テストがなくて怖い、 こうした場所には、 強い判断が眠っています、 なぜここは、 こんなにも慎重に扱われているのか、 その理由を考えることが、 軸を見つける第一歩です、 不自然な一貫性を探す もう一つ、 有効な手がかりがあります、 それは、 不自然なほど一貫している部分です、 毎回同じチェックをしている、 似たような変換が何度も出てくる、 例外処理の方針が妙に揃っている、 それは、 偶然ではありません、 誰かが、 「ここだけは揺らがせない」と 決めた可能性があります、 ...
最初の一手は、「判断の置き場所」に打つ なぜ「小さいところから」は失敗しやすいのか 最初の一手が変えるべきもの 「守られている判断」を一つ選ぶ 切り出すのは「処理」ではない 判断は、まだ if 文の中にある 切り出すべきなのは「条件」ではない 改善例:判断に名前と置き場所を与える 何が変わったのか canApplySpecialDiscount の場合に起きていること isEligible の場合に起きていること 「置き場所が決まる」と何が変わるのか もう一つ大事な違い 設計とは、if を減らすことではない 成功する最初の一手の形 最初の一手は、小さくていい この章のまとめ 最初の一手は、「判断の置き場所」に打つ 既存のモノリスを前にして、 次に必ず出てくる問いがあります。 「で、どこから直せばいいんですか。」 この問いに対して、 多くの現場ではこう答えがちです。 影響範囲が小さいところから テストがあるところから 簡単そうなところから これらは、 間違いではありません。 しかし、 十分でもありません。 なぜ「小さいところから」は失敗しやすいのか 影響範囲の小さい修正は、 安全に見えます。 しかし、 それは多くの場合、 判断に触れていない修正 です。 ロジックを少し整理した クラスを分割した 命名を直した コードはきれいになります。 ですが、 設計はほとんど変わりません。 なぜなら、 判断がそのままだからです。 最初の一手が変えるべきもの 最初の一手で変えるべきなのは、 構造ではなく、 判断です。 もっと正確に言うと、 「この判断は、ここに置く」という 配置の仕方です。 つまり、 判断の所在地を動かすこと が 効果的な最初の一手になります。 「守られている判断」を一つ選ぶ 第5章で見つけた、 判断の軸を思い出してください。 その中から、 次の条件を満たすものを 一つだけ選びます。 長く守られてきた 壊れると致命的 多くの場所から参照されている これは、 今のモノリスの中心判断 です。 ...
改善を止めないために必要なもの 連鎖が途切れる典型的な瞬間 なぜ一気に触ると、連鎖が止まるのか 判断を一つだけ動かした場合 変更が重なると、因果が見えなくなる 「追えない」とは、どういう状態か 連鎖が続く条件は「因果が見えること」 チームでは、さらに問題が大きくなる 改善を止めないためのルール この章のまとめ 改善を止めないために必要なもの 第6章で見たように、 最初の一手は「判断を動かす」ことから始まります。 この一手がうまくいくと、 現場では次に、こんな感覚が生まれます。 「もう少し、ここも直せそうだ」 「次は、あの判断も整理できそうだ」 設計改善が、 連鎖し始める瞬間 です。 しかし、この連鎖は、 意外と簡単に途切れます。 連鎖が途切れる典型的な瞬間 連鎖が止まるのは、 多くの場合、次の判断をしたときです。 「今の流れで、 まとめて構造も整理してしまおう」 判断を一つ動かせた成功体験があると、 つい、こうしたくなります。 クラス構成を整理する パッケージを切り直す 似た責務をまとめる 命名を一気に整える 結果として、 コードはきれいになります。 しかし、 ここで一気に構造を触ると、 改善の連鎖は途切れます。 なぜ一気に触ると、連鎖が止まるのか 理由は単純です。 判断の変化が、追えなくなるからです。 判断を一つだけ動かした場合 たとえば、 第6章で扱ったように、 散らばっていた if の判断を SpecialDiscountPolicy に集めた この変更は、 とても説明しやすい状態です。 「特別割引という判断を、 このクラスに置きました」 何が変わったのか なぜ変えたのか どの判断を動かしたのか が、 一文で説明できます。 変わった判断が、ひとつだけ だからです。 変更が重なると、因果が見えなくなる 一方で、 次のような変更を同時に行った場合を考えてみてください。 判断を切り出した クラスを分割した パッケージを整理した util を削除した コードの見た目は、 確実に良くなっています。 ...
設計力とは、再現可能な判断の質 本書で扱ってきた設計は、実は同じ話をしている 判断はどこに置かれているか その判断は説明できるか 判断の変化を追えるか その判断は再現可能か 設計力とは、再現可能な判断の質 設計力とは、再現可能な判断の質である ここまで本書では、 モノリスや設計改善という題材を通して、 さまざまな話をしてきました。 一見すると、 章ごとにテーマは違って見えるかもしれません。 しかし振り返ってみると、 私たちはずっと、 同じ対象に対して、別の角度から向き合ってきた ことに気づきます。 それは、 判断 です。 本書でやってきたことを振り返る 各章で扱ってきた内容を、 「判断に対して何をしてきたか」という観点で整理すると、 次のようになります。 判断を 見つける 判断を 切り出す 判断に 名前をつける 判断を 動かす 判断の 変化を追う 章ごとに扱っていたのは、 構造でも、クラス分割でも、if 文でもありません。 判断そのものに、どう向き合うか を扱ってきました。 判断を見つける 多くのモノリスでは、 判断はすでに存在しています。 ただし、 それは明示されていません。 if 文の奥に隠れていたり、 複数の条件に分散していたり、 暗黙の前提として人の頭の中にあったりします。 設計改善の最初の一歩は、 新しい構造を作ることではなく、 「ここには判断がある」 と気づくこと でした。 判断を切り出す 判断に気づいても、 それがコードの中に埋もれたままでは、 扱うことができません。 そこで私たちは、 条件式 分岐 ロジックの塊 から、 判断を切り出す ということを行いました。 これは、判断を 「独立した存在として扱える状態」に するための行為です。 判断に名前をつける 切り出された判断は、 まだ不安定です。 ...