Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
詳細の決定を遅らせつつ実装を早くする
Search
shimabox
November 08, 2025
Programming
2
1.9k
詳細の決定を遅らせつつ実装を早くする
PHPカンファレンス福岡2025 の発表資料になります
#phpconfuk #hall_hz
shimabox
November 08, 2025
Tweet
Share
More Decks by shimabox
See All by shimabox
明示と暗黙 ー PHPとGoの インターフェイスの違いを知る
shimabox
2
1.1k
人には人それぞれのサービス層がある
shimabox
3
1.1k
自分のためから誰かのためへ
shimabox
10
4.3k
情報処理安全確保支援士をとった話
shimabox
1
260
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
5
2.5k
GoとPHPのインターフェイスの違い
shimabox
2
520
並行処理を学びGuzzleと仲良くなる
shimabox
3
2.8k
擬人化で完全に理解するクリーンアーキテクチャ
shimabox
20
12k
Unit of Workパターンで永続化とトランザクションを制御する
shimabox
11
7.9k
Other Decks in Programming
See All in Programming
OSSとなったswift-buildで Xcodeのビルドを差し替えられるため 自分でXcodeを直せる時代になっている ダイアモンド問題編
yimajo
3
630
IFSによる形状設計/デモシーンの魅力 @ 慶應大学SFC
gam0022
1
310
CSC307 Lecture 10
javiergs
PRO
1
660
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
470
Honoを使ったリモートMCPサーバでAIツールとの連携を加速させる!
tosuri13
1
180
Vibe Coding - AI 驅動的軟體開發
mickyp100
0
180
[KNOTS 2026登壇資料]AIで拡張‧交差する プロダクト開発のプロセス および携わるメンバーの役割
hisatake
0
300
OCaml 5でモダンな並列プログラミングを Enjoyしよう!
haochenx
0
150
なぜSQLはAIぽく見えるのか/why does SQL look AI like
florets1
0
480
開発者から情シスまで - 多様なユーザー層に届けるAPI提供戦略 / Postman API Night Okinawa 2026 Winter
tasshi
0
210
副作用をどこに置くか問題:オブジェクト指向で整理する設計判断ツリー
koxya
1
620
Oxlintはいいぞ
yug1224
5
1.4k
Featured
See All Featured
Odyssey Design
rkendrick25
PRO
1
500
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
760
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
200
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
590
4 Signs Your Business is Dying
shpigford
187
22k
30 Presentation Tips
portentint
PRO
1
230
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Test your architecture with Archunit
thirion
1
2.2k
The Pragmatic Product Professional
lauravandoore
37
7.1k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
170
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
196
71k
Transcript
詳細の決定を遅らせつつ 実装を早くする 2025/11/08 PHPカンファレンス福岡2025 しまぶ@shimabox
NAME: "しまぶ" SNS: "@shimabox" TAMASHII: "沖縄" COMPANY: "カオナビ" SKILL: -
"PHP" - "Go" FUKUOKA: "SB⚾, アビスパ⚽おめ" whoami.yml 2 はいさい
こんな経験はありませんか 3 ステークホルダー XXX画面作成の進捗は どうでしょうか? ステークホルダー (まだ!!?) おれたち ただいま絶賛DB設計中で...
こんな経験はありませんか 4 ステークホルダー XXX画面作成の進捗は どうでしょうか? ステークホルダー (まだ!!?) おれたち ただいま絶賛DB設計中で... まれによくある
「完璧なDB設計になるまで 実装を始められない」 「どの外部APIを選ぶべきか 決められず1ヶ月が経過」 「仕様が決まらないので 手を動かせない」 まれによくある 5
1. 境界を作る(インターフェース) 2. かんたんな実装で動かす(デモする) 3. フィードバックを得てから本実装 6 この3つのステップを使って解決していきます
なぜ、手が止まるのか 7 そもそも
8 なぜ手が止まるのか 完璧を求めすぎている (最初からいいものを作ろうとしている)
• 「最初から正解を出さないと...」 • 「失敗したくない...」 • 「後から変更できないと思っている」 9 なぜ手が止まるのか
完璧なもの、正解なんてものはない 10 気持ちはわかる、でもね
要求は変わる 11 完璧なもの、正解なんてものはない このサイクルを回したい 作 る 試 す 直 す
→ →
詳細の決定を遅らせつつ 実装を早くする 12 そこで
13 詳細の決定は後回し Clean Architecture 達人に学ぶソフトウェアの構造と設計 詳細の決定を遅らせろ • 詳細の決定は後回しにできる • いや、後回しにすべきだと
言っている
詳細 • DB, フレームワーク, UI, 外部ライブラリ(API), テスト, などなど • 本質的な目的に直接は貢献しないが、目的を実
現するのに必要な技術的なツールや仕組み • 詳細は目的ではなく、手段 14 詳細とはなんでしょう
これらは詳細 なので後回し 「完璧なDB設計になるまで 実装を始められない」 「どの外部APIを選ぶべきか 決められず1ヶ月が経過」 「仕様が決まらないので 手を動かせない」 15 まれによくある
なぜこれで実装が早くなるのか 16 詳細の決定を遅らせる
グルメ情報サイトを作る (福岡市に特化) 17 かんたんな例で見ていきます
イメージ 18 福岡市のグルメスポット
API定義を決める ↓ DB設計を考える ↓ アーキテクチャを考える ↓ 実装 19 よくある 実装まで終わっ
てから、フィー ドバックをもら う
• 「何を受け取って、何を返すか」 • OpenAPI Specification (OAS) を用意したりする 20 API定義を決める
{ "data": [ { "area_name": "中央区", "spots": [ { "id":
1, "name": "◯蘭 天神店", "category": "ラーメン", "location": "福岡市中央区天神x-x-x", "description": "天然とんこつラーメン専門店", "note": "xxxxx", "image_url": "/images/xxxxx.jpg" }, ] }, { "area_name": "博多区", "spots": [ {// 〜 }, {// 〜 }, {// 〜 } ] }, ] } 21 レスポンスJson (正常系)
22 よくある思考 「テーブル設計、クエリはどうしよ うかな」 「正規化は?インデックスは?」 ↓ 1週間経過...まだエンドポイントが 叩けない DB設計
これは詳細 「テーブル設計、クエリはどうしよ うかな」 「正規化は?インデックスは?」 23 DB設計
1. 境界を作る(インターフェース) 2. かんたんな実装で動かす(デモする) 3. フィードバックを得てから本実装 24 そこで、この3つのステップ
• 「何を受け取って、何を返すか」 25 API定義を決める(従来通り)
26 1. 境界を作る // インターフェースで境界を作る interface GourmetSpotInterface { public function
findAll(): array; } ポイント • 「何をするか」だけ定義 • 「どうやるか」は決めない
27 2. かんたんな実装 class InMemoryGourmetSpot implements GourmetSpotInterface { private array
$gourmetSpots = [ [ 'id' => 1, 'name' => '◯蘭 天神店', 'location' => '福岡市中央区天神x-x-x', // 〜 ], [ 'id' => 2, 'name' => 'うどん◯', 'location' => '福岡市博多区住吉x-xx-xxx', // 〜 ], [// 〜], [// 〜], , , ]; public function findAll(): array { return $this->gourmetSpots; } } DB設計は知らんけど、動く!
28 2.5 依存先を変える ここでテストを書いておくと良い class GourmetSpotController { public function __construct(
private GourmetSpotInterface $gourmetSpot ) {} public function index(): JsonResponse { $gourmetSpots = $this->gourmetSpot->findAll(); // エリア別にグルーピング → ビジネスロジック $groupedByArea = $this->groupByArea($gourmetSpots); return response()->json(['data' => $groupedByArea]); } private function groupByArea(array $gourmetSpots): array { // 住所から「中央区」「博多区」などを抽出 } }
29 デモをしてフィードバックを得る おれたち 動くもの作ったので 見てもらえますか? ステークホルダー うーん、料金とか評価とか 項目をもう少し増やしたいです おれたち 了解です!
デモをしてフィードバックを得る おれたち (とりあえず配列いじればいいか) (PHPの配列マジで神) 修正楽勝だな〜 おれたち 修正したので 見てもらえますか? ステークホルダー ぺきかん!
30
// フィードバックを得た上で実装 class GourmetSpot implements GourmetSpotInterface { public function findAll():
array { // この中でDBを触っていく // インターフェースを守っていれば、 試行錯誤が可能 // ----- 以下の選択肢がある ----- // DBじゃなくていいかも // 誰でも編集できるようにファイルでいいかも } } 31 3. フィードバックを得てから本実装 選択肢を残せる / Controllerの修正は不要
32 よくある 詳細の決定を遅らせる • Week 1 ◦ API定義を決める • Week
2 ◦ DB設計、アーキテクチャを考 える • Week 3 ◦ ようやく実装開始 • Week 4 ◦ そしてデモ ↓ 1ヶ月後にやっとフィードバック • Week 1 ◦ API定義を決める • Week 2 ◦ インターフェース定義 ◦ メモリ実装 ◦ デモ ↓ 2週間目からフィードバック! • Week 3以降 ◦ 確信を持って設計、本実装
ステークホルダー 福岡市のお天気情報を表示す るようにしてください おれたち (お天気情報はどこから?) (そもそも必要なんか?) APIは何を使いますか? それが...まだ決まってないです なにかが降ってきた 33
イメージ 34 福岡市のグルメスポット ☀ 23℃(お出かけ日和です) これ
35 やっぱり、この3つのステップ 1. 境界を作る 2. かんたんな実装で動かす 3. フィードバックを得てから本実装
{ "temperature": 23, "weather": "sunny", // これで画像を決める "message": "お出かけ日和です" }
36 API定義を決める
37 1. 境界を作る interface WeatherServiceInterface { // モデルを返す(配列でもいいけど) public function
getWeather(): Weather; } ポイント • OpenWeatherMap? WeatherAPI? 気象庁API? → 後で決める!
38 2. かんたんな実装 class MockWeatherService implements WeatherServiceInterface { public function
getWeather(): Weather { // APIは呼ばずにモデルを返す return new Weather( temperature: 23, weather: 'sunny' ); } } APIの仕様は知らんけど、動かす!
39 2. かんたんな実装 final class Weather { public function __construct(
public readonly int $temperature, public readonly string $weather ) {} public function toArray(): array { return [ 'temperature' => $this->temperature, 'weather' => $this->weather, 'message' => $this->message(), ]; } // ビジネスロジック private function message(): string { return match ($this->weather) { 'sunny' => $this->temperature > 20 ? 'お出かけ日和です' : '少し肌寒いです', default => '今日も一日頑張りましょう' }; } } モデルは単独でテストが書ける!
class GourmetSpotController { public function __construct( private GourmetSpotInterface $gourmetSpot, private
WeatherServiceInterface $weatherService ) {} public function index(): JsonResponse { $gourmetSpots = $this->gourmetSpot->findAll(); $groupedByArea = $this->groupByArea($gourmetSpots); $weather = $this->weatherService->getWeather(); return response()->json([ 'data' => $groupedByArea, 'weather' => $weather->toArray() ]); } private function groupByArea(array $gourmetSpots): array {} } 40 2.5 依存先を変える ここでもテストは書いておく
うーん、、いらないです 了解です!(やっぱりな) デモをしてフィードバックをもらう 41 仮実装のおかげで • 外部API契約してない • 複雑な実装はしてない •
✅ すぐ削除できる
42 3. 採用となってもフィードバックを得ているので実装に入れる class WeatherService implements WeatherServiceInterface { public function
getWeather(): Weather { // 外部APIを叩いて本物のデータを取得 // キャッシュしたりとかも // (実際はHTTPクライアント使う) $data = file_get_contents('https://api.xxxx.org/...'); return $this->createWeather($data); } private function createWeather($data): Weather {}; } 差し替えるだけ
43 よくある 詳細の決定を遅らせる • Week 1-2 ◦ どのAPIを使うか悩む ◦ 料金は?
レスポンス速度は? • Week 3 ◦ 実装開始 • Week 4 ◦ デモ ↓ 「やっぱり、いらないです」🔥 • Week 1 ◦ 仮実装でデモ ◦ 「やっぱり、いらないです」✅ または、 • Week 1 ◦ 仮実装でデモ「よいですね!」 • Week 2-3 ◦ 仕様明確 → API選定👍 → 実装 フィードバックが早いと、 無駄なし!
白状します。 外部APIの選定に1ヶ月以上かけたことがあります。 APIの使い方や、料金、レスポンス速度ばかり調べてい ました。 今となればもう少しうまく進めることが出来たんじゃな いかなぁと反省しながら喋っています。 44 昔の思い出
閑話休題 45
46 アプローチをふりかえる
47 アプローチをふりかえる 1. 境界を作る (詳細の決定は後回し)
48 アプローチをふりかえる 2. 仮実装 (動くものを早く作る)
49 アプローチをふりかえる 3. 本実装 (確信を持って実装)
質問 「必ずインターフェースを用意しな いといけないの?」 50 唐突にQ&A
51 回答:必ずしも必要ではない ベタ書きでもOK • まずは動かすことが大事 • 変わらなそうであればコントローラにベタ書き 詳細はあとでじっくり考えたいところ • 変わりそうなものと、変わらないものを分ける
• そこに境界を作る
52 境界(抽象)をひくのは難しい • 変わりそうなものと、変わらないものを分ける • そして、変わらないものに依存したい • 抽象は変わらないものとして用意したい 抽象は安定化させたい(が、これが難しい)
53 完成までは難しい • PHPの配列は最強だからといって、そのままだ と辛い、Immutableにしたい • グルメスポット一覧は、`GourmetSpot[]` な どで表現できるようになるといい •
動くものは早く作れるけど、完成が早くなると は言っていない
まとめ 54
55 今日話したこと ✅ 詳細の決定は後回しにできる (今まで先に悩んでいたところ) ✅ インターフェースで境界を作れば 実装の置き換えが可能、試行錯誤も可能 ✅
動くものを早く作ると、フィードバックも早まる
56 動くものを早く作ると、フィードバックも早まる ↓ 早期のフィードバックで間違った方向へ進むのを 防げる だいじなこと
57 1. 境界を作る 2. かんたんな実装で動かす 3. フィードバックを得てから本実装 このパターンを身につければ 仕様が未確定でも、手は動かせるはず💪 この3つのステップを試してみよう
58 完璧なもの、正解なんてものはない 手を動かしていきましょう💪 この3つのステップで何かを作ってみてほしい 1. 境界を作る 2. かんたんな実装で動かす 3. フィードバックを得てから本実装
X @shimabox 59 おわりに この発表も「完璧を目指さず」 作られました。 私自身、まだ実践の途中です。 フィードバックをお待ちしてい ます。
60 📖 共著で本を書いています 📖(時間があれば宣伝)
ご清聴ありがとうございました 61