Upgrade to Pro — share decks privately, control downloads, hide ads and more …

自分たちのコードを Composer パッケージに分割して開発する

自分たちのコードを Composer パッケージに分割して開発する

PHP カンファレンス沖縄 2021

Avatar for Shohei Okada

Shohei Okada

May 29, 2021
Tweet

More Decks by Shohei Okada

Other Decks in Programming

Transcript

  1. ローカルのディレクトリを Composer パッケージとして扱う
 ... ├── apps │ └── my-app │

    └── composer.json ├── packages │ └── my-package │ └── composer.json ...
  2. ローカルのディレクトリを Composer パッケージとして扱う
 ... ├── apps │ └── my-app │

    └── composer.json ├── packages │ └── my-package │ └── composer.json ...
  3. ローカルのディレクトリを Composer パッケージとして扱う
 ... ├── apps │ └── my-app │

    └── composer.json ├── packages │ └── my-package │ └── composer.json ...
  4. ローカルのディレクトリを Composer パッケージとして扱う
 { ... "repositories": [ { "type": "path",

    "url": "../../packages/my-package" } ], ... } ... ├── apps │ └── my-app │ └── composer.json ├── packages │ └── my-package │ └── composer.json ...
  5. ローカルのディレクトリを Composer パッケージとして扱う
 { ... "repositories": [ { "type": "path",

    "url": "../../packages/my-package" } ], ... } ... ├── apps │ └── my-app │ └── composer.json ├── packages │ └── my-package │ └── composer.json ...
  6. ローカルのディレクトリを Composer パッケージとして扱う
 ... ├── apps │ └── my-app │

    └── composer.json ├── packages │ └── my-package │ └── composer.json ... $ composer require "my/package:*@dev"
  7. ローカルのディレクトリを Composer パッケージとして扱う
 ... ├── apps │ └── my-app │

    └── composer.json ├── packages │ └── my-package │ └── composer.json ... $ composer require "my/package:*@dev" "name": "my/package"
  8. ローカルのディレクトリを 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 を利用できるようになる 

  9. Laravel におけるディレクトリ構造の例
 ├── app │ ├── ... ... ├── composer.json

    ... ├── app │ ├── ... ... ├── packages │ └── my-package │ └── composer.json ... ├── composer.json ... ※ “my-package” はあくまで例なので、 
  適切な名前をつけてあげてください。 

  10. 
 
 
 
 
 
 
 
 
 


    後藤知宏, “Laravel Package Development”, Laravel JP Conference 2019, https://speakerdeck.com/mikakane/laravel-package-development
 
 参考資料

  11. Laravel の例を挙げれば
 • Illuminate に依存しない(use したり、完全修飾名で利用しない)
 ◦ extends、implements、引数、戻り値に出てこない
 • グローバルヘルパ関数や

    Class Alias(\Log とか)を使わない
 
 これらを取り除いて残るのは、自ずと「自分たち」固有のコードになるはず
 
 ※ここでいう「自分たち」とはサービスやビジネス
 フレームワークに依存していない状態

  12. 
 
 
 
 
 
 
 
 
 


    @77web, “そのコード、フレームワークの外でも動きますか?”, PHPerKaigi20201, https://speakerdeck.com/77web/sofalsekodo-huremuwakufalsewai-demodong-kimasuka 
 
 参考資料

  13. 
 
 
 
 
 
 
 
 
 


    @sonatard, “オブジェクト指向その前に凝集度と結合度”, Object Oriented Conference 2020, https://speakerdeck.com/sonatard/coheision-coupling
 
 参考資料

  14. 型情報の上でフレームワークに依存しなくなっても
 「見えない依存関係」が存在しているケースがある
 • 型宣言がない箇所で、フレームワーク固有のクラスを想定している
 • 関数の呼び出しに暗黙の前提条件が存在している
 • 型は int や

    string だが、その値の意味がフレームワークに特化している
 ◦ 例)フレームワークで使われるクラス名の文字列
 
 このような実装は「結合度が高い」と言える
 →そのクラスや関数を使うのに、型から得られる情報以上の知識が
  必要になってないかを意識する
 見えない依存関係

  15. パッケージに切り出す(モジュール化する)こと
 = インターフェースをデザインすること
 
 ポイントは
 • (特にフレームワークとの)依存関係
 • 凝集度と結合度
 


    →いきなり「自分たちのコード」を網羅的に切り出すのは難しい
  まず、1 つの関数だけでいいので切り出してみよう
 どうやって分割していくか?(再掲)

  16. ルートパッケージの vendor ディレクトリ内に全ての依存関係が
 フラットに集約されるため、例えば次のような場合もエラーにならない
 依存関係を厳密にチェックできるわけではない
 ルートパッケージ パッケージ A パッケージ B

    ルートパッケージ パッケージ A パッケージ B ▪ composer.json に定義した依存関係
 ▪本来依存していないパッケージにアクセスできてしまう
 パッケージ B からパッケージ A のコードを利用

  17. 私はやったことはないが、想定できるのは
 🙆 分離することで CI のサイクルが早くなる
 🙆 共通のコードを複数のプロジェクトから使える
 🙅 運用やデプロイ(ローカル開発環境含む)が複雑になる
 🙅

    インターフェースの決定や変更について取り決めが必要になる
 
 相当の規模の開発でないか、運用上のノウハウが無い限り
 デメリットの方が大きい気がする(経験・知見のある方の意見求ム)
 パッケージごとに Git リポジトリを別にすべきか?