その悩みは本当に設計上の悩みなのか?

設計のフレームワークを作っていたら、モデリングのフレームワークになっていた 要件定義、仕様策定、設計、実装は、すべてモデリングなのではないか モデリングのフレームワーク 実装で迷ったとき、「どこで迷っているのか」が分かるようになった そういえば、要件と仕様の違いをちゃんと理解していなかった 要件は What / Goal、仕様は How 「迷い」を上流へ遡る モデリングのフレームワークを作っていたから見えるようになった 設計のフレームワークを作っていたら、モデリングのフレームワークになっていた 現在、私はソフトウェア開発における「モデリングのフレームワーク」を作っています。 もともとは、より良い設計をするためのフレームワークを作ろうとしていました。 しかし、考えているうちに、あることに気が付きました。 要件定義、仕様策定、設計、そして実装は、それぞれ独立した活動ではなく、前工程で作られたものを、別の形でモデリングし直していく活動なのではないか。 この気付きから、現在は「設計のフレームワーク」ではなく、「モデリングのフレームワーク」として整理し直しています。 要件定義、仕様策定、設計、実装は、すべてモデリングなのではないか ソフトウェア開発では、一般的に、 要件定義 ↓ 仕様策定 ↓ 設計 ↓ 実装 という工程に分けて考えます。 以前の私は、これらをそれぞれ別の作業として捉えていました。 しかし、モデリングという視点から見ると、少し違った見え方をします。 例えば、要件定義では、現実世界の課題や目的を、「システムが何を達成する必要があるのか」という形に変換します。 仕様策定では、その要件を、「システムがどのように振る舞うべきか」という形に変換します。 設計では、その振る舞いを、「ソフトウェアをどのような構造にすれば実現できるか」という形に変換します。 そして実装では、その設計をコードという形に変換します。 つまり、 現実の課題・目的 ↓ 要件として表現 ↓ 仕様として表現 ↓ 設計として表現 ↓ コードとして表現 というように、同じ対象を、工程ごとに異なるモデルとして表現していると考えることができます。 この見方をすると、要件定義、仕様策定、設計、実装の間にあった境界が、少し違って見えてきました。 モデリングのフレームワーク 現在作っているフレームワークは、まだ大枠しか定まっていません。 イメージとしては、クリーンアーキテクチャのような同心円状の構造を考えています。 中心から外側に向かって、上流工程から下流工程へと進んでいきます。 そして、それぞれのレイヤーには、その工程で適切なモデリングを行うための考え方を配置します。 ┌───────────────────┐ │ 実装 │ │ ┌───────────────┐ │ │ │ 設計 │ │ │ │ ┌───────────┐ │ │ │ │ │ 仕様 │ │ │ │ │ │ ┌───────┐ │ │ │ │ │ │ │ 要件 │ │ │ │ │ │ │ └───────┘ │ │ │ │ │ └───────────┘ │ │ │ └───────────────┘ │ └───────────────────┘ まだこの図自体も発展途中です。 ...

2026年9月20日 · 2 分 · 奥田 智紘

抽象化しすぎない正義

はじめに 1. 「裁量がある会社」を探していた 2. さらに抽象化してみた 3. 抽象化には「ちょうどいい地点」がある 4. これはソフトウェア設計にも応用できる 5. 「本質を見抜く」と「抽象化しすぎない」は両立する まとめ はじめに ソフトウェア設計では、「抽象化」が重要だと言われます。 重複した処理を共通化したり、具体的な実装から本質的な概念を取り出したりすることで、変更に強く、再利用しやすい設計を作ることができます。 私自身、これまで設計について学ぶ中で、具体的な事例から共通する本質を見つけ出し、より抽象的な概念として捉えることを意識してきました。 しかし最近、別の重要なことに気づきました。 抽象化は、必ずしも最後まで行えばよいわけではない。 抽象化を進めすぎると、今度は意味が伝わりにくくなることがあります。 今回は、転職活動での企業選びを通して、このことに気づいたので整理してみます。 1. 「裁量がある会社」を探していた これまで私は、転職先を選ぶ際の基準として、 裁量があること をかなり重視していました。 例えば、 設計に関われる 技術選定に関われる 仕様について提案できる スケジュールについて意見を言える といったことです。 しかし、改めて「なぜ裁量が欲しいのか?」を考えてみると、裁量そのものが目的ではないことに気づきました。 例えば、技術的負債によって実装が非常に難しくなっている状況を考えます。 現場のエンジニアが、 「このままでは予定通りに実装するのが難しい」 と判断したとします。 このとき重要なのは、必ずしもそのエンジニア自身が、 「では私の判断でスケジュールを変更します」 と決められることではありません。 むしろ、 「このままでは難しいので、スケジュールを見直したほうがよい」 という現場の判断を、上司やマネージャーが受け止め、必要ならさらに上の意思決定者に伝え、組織として判断できることのほうが重要です。 つまり、私が本当に求めていたのは「裁量」そのものではありませんでした。 現場で行われた合理的な判断が、組織の意思決定に反映されること だったのです。 2. さらに抽象化してみた そこで、もう一段階抽象化してみました。 「現場の判断が尊重される」ということをさらに抽象化すると、 チームとして適切な意思決定が行われていること と言えそうです。 または、 適切な意思決定プロセスがあること とも表現できます。 確かに、これは概念としては間違っていません。 抽象化したことで、より本質的な意味を表しているようにも思えます。 しかし、ここで問題が起きました。 分かりにくいのです。 自分の企業選びの基準として考えてみても、 「チームとして適切な意思決定が行われている会社がいい」 と言われたとき、具体的に何を確認すればいいのかが分かりにくい。 面接官に説明するとしても、 「適切な意思決定プロセスとは何ですか?」 という話になり、かえって説明が必要になります。 一方、すこし具体的にして 「現場の判断が尊重されること」 なら、かなりイメージしやすい。 例えば、 技術的に難しい問題があれば相談できる 無理なスケジュールなら調整を検討してもらえる より良い設計案があれば検討してもらえる 技術的負債の解消が必要なら、リファクタリングの時間を確保してもらえる といった具体例にすぐ落とし込めます。 ...

2026年8月24日 · 1 分 · 奥田 智紘

技術的判断に必要な前提について深堀りする

はじめに 1. 意見の違いは、前提の違いから生まれる 2. さらに一つ前の前提を見る 3. 何を重要視しているかを確認する 4. 前提が一致しない場合どうするべきか 4-1. 価値観の違いを認識する 4-2. 制約によって変更できない場合を理解する 5. 良い技術者は正解を知っている人ではない まとめ 過去のブログで、良い判断をするためには、良い前提が必要であるという主張をしました。 例えば以下の記事です。 演繹(えんえき)法から考える設計の本質 多くの場合、前提を明確にすればうまくいくと感じています。 しかし、場合によってはうまくいかないこともありました。 今回は、 前提 について深堀していき、 前提を明確にしてもうまくいかない場合に、どうしたらよいのかを考えた内容を共有します。 はじめに アプリ開発では、日々多くの技術的な判断を行います。 どのアーキテクチャを採用するか どこに責務を配置するか 新しいライブラリを導入するか 技術的負債を返済するか これらの判断には、多くの場合「唯一の正解」はありません。 同じ技術者でも、状況によって異なる判断をすることがあります。 では、良い技術的判断とは何でしょうか。 この記事では、技術的な意思決定を行う上で重要な「前提」という考え方について整理します。 1. 意見の違いは、前提の違いから生まれる 例: 「APIレスポンスの加工処理をどこに書くべきか」 という議論。 Aさん: ViewModelで十分ではないか Bさん: UseCaseに分離すべきではないか 表面的には、 「ViewModel派」 「UseCase派」 の対立に見える。 しかし、本質的には、 「どのような未来を想定しているか」 が違います。 Aさん: この機能は小さい 今後変更されない シンプルさを優先したい Bさん: 今後拡張される可能性がある 複数画面で利用する可能性がある テスト容易性を重視したい つまり、意見ではなく、その背景にある前提を見る必要があります。 2. さらに一つ前の前提を見る 前提は深掘りできます。つまり、さらに一つ前の前提が存在します。 例えば、 「UseCaseに分離するべき」 という判断の裏には、 「保守性を高めたい」 という前提があります。しかし、さらに上を見ると、 このプロダクトは長期運用されるのか リリース時期は固定なのか 開発リソースは十分なのか 今回変更できる範囲はどこまでなのか という、さらに上位の前提が存在します。例えば、 ...

2026年8月6日 · 1 分 · 奥田 智紘

ソフトウェア設計をしていたら仕様の違和感に気が付いた話

違和感のある仕様 違和感のある仕様通りに実装した場合 現時点の動作が同じなら、前者でも後者でもいいのではないか? 解決策 まとめ ソフトウェア設計をしていたら、仕様の違和感に気が付いて、仕様を変更した話を書きたいと思います。 違和感のある仕様 ある画面 C は、画面 A と画面 B という二つの画面から遷移可能な画面でした。 画面 C には、戻るボタンがありました。 戻るボタンをタップすると、 「画面 A から遷移した場合は A に戻り、画面 B から遷移した場合は B に戻る」 という仕様でした。 この、何の変哲もない普通の仕様に、実は違和感が潜んでいました。 【補足】 今回の話は、非常に些細な点をとりあげます。 そのため、この話で出てくる例自体は、実際にはほぼ無害です。 しかし、簡単な例だからこそ、 どのようにソフトウェアが壊れていくのかを 誰が読んでもわかる例になっています。 それを知るきっかけとなるように、この記事を残します。 違和感のある仕様通りに実装した場合 Android で画面遷移を実装する場合は、 Navigation Component というライブラリを使用することが一般的です。 Navigation には、 一つ前の画面に戻る 場合には、 NavController.navigateUp() という関数が使えます。 一方で、 指定した画面まで戻る 場合には、 NavController.popBackStack(route = /* 戻りたい画面 */, inclusive = false) という関数が使えます。 仕様では、「画面 A から遷移した場合は A に戻り…」とあるので、後者の関数を使って実装します。 前者の関数を使用して実装しても、現時点では同じ動作になりますが、将来的には同じとは限りません。 例えば、 A -> D -> C という画面遷移になった場合には、 ...

2026年6月10日 · 1 分 · 奥田 智紘

演繹(えんえき)法から考える設計の本質

演繹法とは 私たちは日常的に演繹している 問題は前提が曖昧なときに起こる 設計とは何をしているのか 演繹法と設計の関係 まとめ ソフトウェア設計について考えていると、「演繹法」という言葉に出会うことがあります。 しかし、演繹法と聞くと何か特別な思考法のように感じるかもしれません。 私自身、演繹法について改めて考えてみた結果、 「普段当たり前にやっていることに名前が付いているだけではないか?」 と感じました。 この記事では、演繹法とソフトウェア設計の関係について考えてみます。 演繹法とは 演繹法とは、 一般的なルール(前提)から、個別の結論を導く考え方 です。例えば、 すべての鳥は羽を持つ スズメは鳥である したがってスズメは羽を持つ のように考えられます。もっとソフトウェア寄りの例だと すべてのRepositoryはデータ取得の責務を持つ UserRepositoryはRepositoryである したがってUserRepositoryはデータ取得の責務を持つ のように言えます。 重要なのは、 前提が正しければ、結論も正しい という点です。 私たちは日常的に演繹している 実はソフトウェア開発者は、日常的に演繹法を使っています。 例えば、次のようなインターフェースがあったとします。 interface PaymentRepository { suspend fun save(payment: Payment) } このコードを見たとき、多くの開発者は自然に次のように考えるはずです。 save は保存処理である 保存したデータは後で取得できるはず 保存したデータが勝手に壊れてはいけないはず これはすべて、 save は保存する ↓ だから○○であるべき という演繹です。 特別なことをしているわけではありません。 普段の設計レビューやコードレビューで当たり前に行っている思考です。 問題は前提が曖昧なときに起こる ただし、演繹法には重要なポイントがあります。 それは、 前提が明確であること です。 例えば、次のようなインターフェースを考えます。 interface PaymentRepository { suspend fun delete(id: Int) } これを見た多くの人は、 delete は削除処理である 削除したデータは取得できなくなるはず と考えるでしょう。 しかし、実際には仕様として、 論理削除を行う というルールが存在するかもしれません。 この場合、 delete は物理削除である ...

2026年6月10日 · 1 分 · 奥田 智紘