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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Shohei Okada
May 29, 2021
Programming
260
0
Share
自分たちのコードを Composer パッケージに分割して開発する
PHP カンファレンス沖縄 2021
Shohei Okada
May 29, 2021
More Decks by Shohei Okada
See All by Shohei Okada
Symfony + NelmioApiDocBundle を使った スキーマ駆動開発 / Schema Driven Development with NelmioApiDocBundle
okashoi
0
300
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
930
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
3
2.3k
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
390
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
11
6.1k
"config" ってなんだ? / What is "config"?
okashoi
0
1.8k
ファイル先頭の use の意味、説明できますか? 〜PHP の namespace と autoloading の関係を正しく理解しよう〜 / namespace and autoloading in php
okashoi
4
2.2k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
1.3k
PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai static analysis for PHP
okashoi
1
1.5k
Other Decks in Programming
See All in Programming
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
490
AutonomyとControlのあいだ:Graflowで記述するAIエージェント協調
myui
0
110
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.3k
SPMマルチモジュールで テストカバレッジを取得する技法
yosshi4486
0
140
3Dシーンの圧縮
fadis
1
640
tsserverとは何だったのか、これからどうなるのか
nowaki28
1
450
The Arts and Crafts of Work in the AI Era — Toward Mastery in Software Development
kuranuki
1
720
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
12k
TAKTでAI駆動開発の品質を設計する
j5ik2o
6
880
AIチームを指揮するOSS「TAKT」活用術 / How to Use “TAKT,” an OSS Tool for Orchestrating AI Teams
nrslib
6
820
権限チェックの一貫性を型で守る TypeScript による多層防御
mnch
4
1.1k
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
190
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.3k
BBQ
matthewcrist
89
10k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
250
How to train your dragon (web standard)
notwaldorf
97
6.7k
So, you think you're a good person
axbom
PRO
2
2k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
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 等のライブラリへの依存も同様 最終的にどこまでやるかは「さじ加減」