Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
詳細の決定を遅らせつつ実装を早くする
Search
shimabox
November 08, 2025
Programming
2
1.5k
詳細の決定を遅らせつつ実装を早くする
PHPカンファレンス福岡2025 の発表資料になります
#phpconfuk #hall_hz
shimabox
November 08, 2025
Tweet
Share
More Decks by shimabox
See All by shimabox
明示と暗黙 ー PHPとGoの インターフェイスの違いを知る
shimabox
2
1k
人には人それぞれのサービス層がある
shimabox
3
990
自分のためから誰かのためへ
shimabox
10
4.1k
情報処理安全確保支援士をとった話
shimabox
1
260
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
5
2.2k
GoとPHPのインターフェイスの違い
shimabox
2
480
並行処理を学びGuzzleと仲良くなる
shimabox
3
2.6k
擬人化で完全に理解するクリーンアーキテクチャ
shimabox
20
12k
Unit of Workパターンで永続化とトランザクションを制御する
shimabox
11
7.4k
Other Decks in Programming
See All in Programming
Cap'n Webについて
yusukebe
0
140
Go コードベースの構成と AI コンテキスト定義
andpad
0
130
Github Copilotのチャット履歴ビューワーを作りました~WPF、dotnet10もあるよ~ #clrh111
katsuyuzu
0
110
これならできる!個人開発のすゝめ
tinykitten
PRO
0
110
LLM Çağında Backend Olmak: 10 Milyon Prompt'u Milisaniyede Sorgulamak
selcukusta
0
130
FluorTracer / RayTracingCamp11
kugimasa
0
240
AIエンジニアリングのご紹介 / Introduction to AI Engineering
rkaga
8
3k
大体よく分かるscala.collection.immutable.HashMap ~ Compressed Hash-Array Mapped Prefix-tree (CHAMP) ~
matsu_chara
2
220
【Streamlit x Snowflake】データ基盤からアプリ開発・AI活用まで、すべてをSnowflake内で実現
ayumu_yamaguchi
1
120
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
250
tparseでgo testの出力を見やすくする
utgwkk
2
240
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.3k
Featured
See All Featured
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Building an army of robots
kneath
306
46k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.2k
Fireside Chat
paigeccino
41
3.7k
Producing Creativity
orderedlist
PRO
348
40k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
7.9k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.3k
Unsuck your backbone
ammeep
671
58k
It's Worth the Effort
3n
187
29k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
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