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
自分たちのコードを Composer パッケージに分割して開発する
Search
Shohei Okada
May 29, 2021
Programming
0
220
自分たちのコードを Composer パッケージに分割して開発する
PHP カンファレンス沖縄 2021
Shohei Okada
May 29, 2021
Tweet
Share
More Decks by Shohei Okada
See All by Shohei Okada
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
190
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
3
1.4k
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
210
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
11
3.8k
"config" ってなんだ? / What is "config"?
okashoi
0
1.2k
ファイル先頭の use の意味、説明できますか? 〜PHP の namespace と autoloading の関係を正しく理解しよう〜 / namespace and autoloading in php
okashoi
4
1.6k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
890
PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai static analysis for PHP
okashoi
1
600
【PHPカンファレンス沖縄 2023】素朴で考慮漏れのある PHP コードをテストコードとともに補強していく(ライブコーディング補足資料) / #phpcon_okinawa 2023 livecoding supplementary material
okashoi
3
1.9k
Other Decks in Programming
See All in Programming
来たるべき 8.0 に備えて React 19 新機能と React Router 固有機能の取捨選択とすり合わせを考える
oukayuka
2
860
High-Level Programming Languages in AI Era -Human Thought and Mind-
hayat01sh1da
PRO
0
300
データの民主化を支える、透明性のあるデータ利活用への挑戦 2025-06-25 Database Engineering Meetup#7
y_ken
0
320
Google Agent Development Kit でLINE Botを作ってみた
ymd65536
2
190
KotlinConf 2025 現地で感じたServer-Side Kotlin
n_takehata
1
230
AWS CDKの推しポイント 〜CloudFormationと比較してみた〜
akihisaikeda
3
310
CursorはMCPを使った方が良いぞ
taigakono
1
180
LT 2025-06-30: プロダクトエンジニアの役割
yamamotok
0
460
Cursor AI Agentと伴走する アプリケーションの高速リプレイス
daisuketakeda
1
130
エンジニア向け採用ピッチ資料
inusan
0
160
git worktree × Claude Code × MCP ~生成AI時代の並列開発フロー~
hisuzuya
1
480
Systèmes distribués, pour le meilleur et pour le pire - BreizhCamp 2025 - Conférence
slecache
0
110
Featured
See All Featured
Become a Pro
speakerdeck
PRO
28
5.4k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
2.9k
Into the Great Unknown - MozCon
thekraken
39
1.9k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
4 Signs Your Business is Dying
shpigford
184
22k
The Straight Up "How To Draw Better" Workshop
denniskardys
234
140k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
A Tale of Four Properties
chriscoyier
160
23k
Why You Should Never Use an ORM
jnunemaker
PRO
57
9.4k
Optimizing for Happiness
mojombo
379
70k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.8k
Documentation Writing (for coders)
carmenintech
72
4.9k
Transcript
自分たちのコードを Composer パッケージに 分割して開発する 2021/05/29 PHP カンファレンス沖縄 2021 @okashoi
岡田 正平/おかしょい Twitter: @okashoi GitHub: @okashoi 所属:株式会社ウィルゲート 登壇:
寄稿:
目次 • 導入(問題提起、提案) • ローカルのディレクトリを Composer パッケージとして扱う方法 • パッケージを分割する際の考え方 •
こぼれ話
目次 • 導入(問題提起、提案) • ローカルのディレクトリを Composer パッケージとして扱う方法 • パッケージを分割する際の考え方 •
こぼれ話
開発についてまわる問題 何も意識せずにフレームワークを使って開発していると 巨大なひとつの構造物となっていく 結果、次のような状態を引き起こしやすい • Controller に書き下される一連の詳細な処理 • 責任の境界が曖昧なクラス
• あちらこちらに出てくる同じような手順 • フレームワークの機能に過度に依存したコード → 可読性や再利用性の低下、バグの原因
ソフトウェア設計の領域において古くから存在する 「モジュール化」というアプローチ →しかし PHP は言語機能としてモジュールに相当するものを備えていない ※「モジュール」という語彙自体は「拡張モジュール」で使われるが別物 モジュール化
PHP における依存関係管理ツール 依存関係を「パッケージ(※)」単位で扱う ※Composer におけるパッケージとは composer.json が存在するディレクトリ
Composer
PHP における依存関係管理ツール 依存関係を「パッケージ(※)」単位で扱う ※Composer におけるパッケージとは composer.json が存在するディレクトリ
Composer 本発表で紹介する方法 Composer パッケージを「モジュール」に近い概念として扱う
目次 • 導入(問題提起、提案) • ローカルのディレクトリを Composer パッケージとして扱う方法 • パッケージを分割する際の考え方 •
こぼれ話
Packagist
Packagist からパッケージを持ってくることだけが選択肢ではない Composer には「リポジトリ」という概念があり、 GitHub のリポジトリやローカルに存在するディレクトリを composer install や
composer require の対象にできる Composer におけるリポジトリ
Packagist からパッケージを持ってくることだけが選択肢ではない Composer には「リポジトリ」という概念があり、 GitHub のリポジトリやローカルに存在するディレクトリを composer install や
composer require の対象にできる Composer におけるリポジトリ 今回はこっち
ローカルのディレクトリを Composer パッケージとして扱う ... ├── apps │ └── my-app │
└── composer.json ├── packages │ └── my-package │ └── composer.json ...
ローカルのディレクトリを Composer パッケージとして扱う ... ├── apps │ └── my-app │
└── composer.json ├── packages │ └── my-package │ └── composer.json ...
ローカルのディレクトリを Composer パッケージとして扱う ... ├── apps │ └── my-app │
└── composer.json ├── packages │ └── my-package │ └── composer.json ...
ローカルのディレクトリを Composer パッケージとして扱う { ... "repositories": [ { "type": "path",
"url": "../../packages/my-package" } ], ... } ... ├── apps │ └── my-app │ └── composer.json ├── packages │ └── my-package │ └── composer.json ...
ローカルのディレクトリを Composer パッケージとして扱う { ... "repositories": [ { "type": "path",
"url": "../../packages/my-package" } ], ... } ... ├── apps │ └── my-app │ └── composer.json ├── packages │ └── my-package │ └── composer.json ...
ローカルのディレクトリを Composer パッケージとして扱う ... ├── apps │ └── my-app │
└── composer.json ├── packages │ └── my-package │ └── composer.json ... $ composer require "my/package:*@dev"
ローカルのディレクトリを Composer パッケージとして扱う ... ├── apps │ └── my-app │
└── composer.json ├── packages │ └── my-package │ └── composer.json ... $ composer require "my/package:*@dev" "name": "my/package"
ローカルのディレクトリを Composer パッケージとして扱う ... ├── apps │ └── my-app │
└── composer.json ├── packages │ └── my-package │ └── composer.json ... apps/my-app/vendor/my/package から packages/my-package へとシンボリックリンクが張られる → Composer の autoload 機能を経由して my-app から my-package を利用できるようになる
Laravel におけるディレクトリ構造の例 ├── app │ ├── ... ... ├── composer.json
... ├── app │ ├── ... ... ├── packages │ └── my-package │ └── composer.json ... ├── composer.json ... ※ “my-package” はあくまで例なので、 適切な名前をつけてあげてください。
後藤知宏, “Laravel Package Development”, Laravel JP Conference 2019, https://speakerdeck.com/mikakane/laravel-package-development 参考資料
目次 • 導入(問題提起、提案) • ローカルのディレクトリを Composer パッケージとして扱う方法 • パッケージを分割する際の考え方 •
こぼれ話
パッケージに切り出す(モジュール化する)こと = インターフェースをデザインすること ポイントは • (特にフレームワークとの)依存関係 • 凝集度と結合度 どうやって分割していくか?
フレームワークに依存している状態 = 「フレームワークのその場所」から動かすのが困難な状態 • コードの再利用性が下がっている • フレームワークのバージョンアップに追従しにくくなる • 長期運用するアプリケーションではフレームワークを乗り換えることも
◦ 過度に依存しているとほぼ書き直しになる 「フレームワークに依存させないこと」の動機
Laravel の例を挙げれば • Illuminate に依存しない(use したり、完全修飾名で利用しない) ◦ extends、implements、引数、戻り値に出てこない • グローバルヘルパ関数や
Class Alias(\Log とか)を使わない これらを取り除いて残るのは、自ずと「自分たち」固有のコードになるはず ※ここでいう「自分たち」とはサービスやビジネス フレームワークに依存していない状態
自分たち固有のコードとは? • 見積もりの計算ロジックかもしれない • マッチングのアルゴリズムかもしれない • データのアクセス権限に関する条件式かもしれない • 税金の計算かもしれない
これら正しく抽出するには開発する対象領域への深い理解が必要 →この過程こそがモデリング 「自分たちのコード」
@77web, “そのコード、フレームワークの外でも動きますか?”, PHPerKaigi20201, https://speakerdeck.com/77web/sofalsekodo-huremuwakufalsewai-demodong-kimasuka 参考資料
モジュールの設計において古くから用いられている尺度 凝集度:責任範囲が明確でそこに集中しているかどうか。高い方が良い。 結合度:モジュール間でのデータの共有度合い。低いほうが良い。 凝集度と結合度
@sonatard, “オブジェクト指向その前に凝集度と結合度”, Object Oriented Conference 2020, https://speakerdeck.com/sonatard/coheision-coupling 参考資料
型情報の上でフレームワークに依存しなくなっても 「見えない依存関係」が存在しているケースがある • 型宣言がない箇所で、フレームワーク固有のクラスを想定している • 関数の呼び出しに暗黙の前提条件が存在している • 型は int や
string だが、その値の意味がフレームワークに特化している ◦ 例)フレームワークで使われるクラス名の文字列 このような実装は「結合度が高い」と言える →そのクラスや関数を使うのに、型から得られる情報以上の知識が 必要になってないかを意識する 見えない依存関係
パッケージに切り出す(モジュール化する)こと = インターフェースをデザインすること ポイントは • (特にフレームワークとの)依存関係 • 凝集度と結合度 どうやって分割していくか?(再掲)
パッケージに切り出す(モジュール化する)こと = インターフェースをデザインすること ポイントは • (特にフレームワークとの)依存関係 • 凝集度と結合度
→いきなり「自分たちのコード」を網羅的に切り出すのは難しい まず、1 つの関数だけでいいので切り出してみよう どうやって分割していくか?(再掲)
「自分たちのコード」を 依存の束縛から解き放とう
目次 • 導入(問題提起、提案) • ローカルのディレクトリを Composer パッケージとして扱う方法 • パッケージを分割する際の考え方 •
こぼれ話
「同一パッケージ内からのみアクセスできるクラス」は定義できない パッケージの詳細を(仕組みとして)隠蔽できないため、運用でカバーする必要があ る PHP のクラスは全て public
ルートパッケージの vendor ディレクトリ内に全ての依存関係が フラットに集約されるため、例えば次のような場合もエラーにならない 依存関係を厳密にチェックできるわけではない ルートパッケージ パッケージ A パッケージ B
ルートパッケージ パッケージ A パッケージ B ▪ composer.json に定義した依存関係 ▪本来依存していないパッケージにアクセスできてしまう パッケージ B からパッケージ A のコードを利用
私はやったことはないが、想定できるのは 🙆 分離することで CI のサイクルが早くなる 🙆 共通のコードを複数のプロジェクトから使える 🙅 運用やデプロイ(ローカル開発環境含む)が複雑になる 🙅
インターフェースの決定や変更について取り決めが必要になる 相当の規模の開発でないか、運用上のノウハウが無い限り デメリットの方が大きい気がする(経験・知見のある方の意見求ム) パッケージごとに Git リポジトリを別にすべきか?
「フレームワークにどこまで依存するのか?」は必ずどこかで線引きが必要 フレームワークに依存しないコードは • フレームワーク側から適切に呼び出すために、 フレームワークの一歩踏み込んだ理解が必要になる • コードの量が増える傾向にある あるいは
Carbon や Guzzle 等のライブラリへの依存も同様 最終的にどこまでやるかは「さじ加減」