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
Perlにおける動的なモジュールロードのメリットとデメリット
Search
ybrliiu
November 03, 2019
Technology
0
790
Perlにおける動的なモジュールロードのメリットとデメリット
ybrliiu
November 03, 2019
Tweet
Share
More Decks by ybrliiu
See All by ybrliiu
これまでと、これからのPerlコミュニティ
ybrliiu
0
130
AstroNvim を使おう!
ybrliiu
0
4.1k
Perlでも関数の型をチェックしたい
ybrliiu
0
2.8k
Perl5.32の新機能
ybrliiu
0
140
Vue.jsで作ったサイトをバニラJSで書き直す悲しいお話
ybrliiu
1
1k
黒魔術で独自定義のenum型制約を満たす値のリ ストを取得する話
ybrliiu
0
370
Perlにおけるクラスの実装パターン.pdf
ybrliiu
0
1.5k
Presentation.pdf
ybrliiu
0
250
ぼくがPerlで開発を行う時に工夫していること
ybrliiu
0
500
Other Decks in Technology
See All in Technology
『衛星データ利用の方々にとって近いようで触れる機会のなさそうな小話 ~ 衛星搭載ソフトウェアと衛星運用ソフトウェア (実物) を動かしながらわいわいする編 ~』 @日本衛星データコミニティ勉強会
meltingrabbit
0
140
関東Kaggler会LT: 人狼コンペとLLM量子化について
nejumi
3
540
PL900試験から学ぶ Power Platform 基礎知識講座
kumikeyy
0
120
インフラをつくるとはどういうことなのか、 あるいはPlatform Engineeringについて
nwiizo
5
2.4k
スクラムのイテレーションを導入してチームの雰囲気がより良くなった話
eccyun
0
110
Nekko Cloud、 これまでとこれから ~学生サークルが作る、 小さなクラウド
logica0419
2
880
Postman Flowsの基本 / Postman Flows Basics
yokawasa
1
100
プロセス改善による品質向上事例
tomasagi
2
2.2k
Developers Summit 2025 浅野卓也(13-B-7 LegalOn Technologies)
legalontechnologies
PRO
0
500
CZII - CryoET Object Identification 参加振り返り・解法共有
tattaka
0
310
バックエンドエンジニアのためのフロントエンド入門 #devsumiC
panda_program
16
7k
スタートアップ1人目QAエンジニアが QAチームを立ち上げ、“個”からチーム、 そして“組織”に成長するまで / How to set up QA team at reiwatravel
mii3king
2
1.3k
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
174
51k
Designing Experiences People Love
moore
139
23k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
99
18k
Into the Great Unknown - MozCon
thekraken
35
1.6k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Code Reviewing Like a Champion
maltzj
521
39k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
3
320
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.3k
Making the Leap to Tech Lead
cromwellryan
133
9.1k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Transcript
Perlにおける動的なモジュールロードの メリットとデメリット YAPC::Nagoya::Tiny @_ybrliiu
自己紹介 • id: mp0liiu / @_ybrliiu • 所属 : 株式会社モバイルファクトリー
• 新卒2年目(23歳) • Perl歴約7年 • 最近はソフトウェアアーキテクチャとか型に関心があります ◦ https://github.com/ybrliiu/p5-Types-TypedCodeRef
Perlの好きなところ • TMTOWTDI • 特にオブジェクト指向の実現方法がいろいろあるところ ◦ Any reference base class,
Inside-out class, いろんなクラスビ ルダー, etc... • 最近Perlコアにオブジェクト指向の構文を入れようという提案がでて いたりしていてテンションが上っています
よろしくお願いいたします!!!
なぜこの発表をしようと思ったのか • これまで趣味 + お仕事で動的なモジュールロードを行うコードをカ ジュアルに書いてきました • そのようなコードを運用していると、後から辛くなってくることが多かっ たので、なぜそうなっているのかを整理し、どうすれば改善できるのか を考えました
• http://mp0liiu.hatenablog.com/entry/2019/02/28/111424
次のようなコードがありました • とあるソーシャルゲームのコード • アイテムを使用すると、アイテムの種類に応じて効果が発動する • アイテムのデータはDBで管理されている
エンジニアA 「いちいちアイテム効果クラスを1つ1つuseしてアイテム の種類と対応させるコードを書くのめんどくさいなー」 エンジニアA 「せや!アイテムデータの種類を見て正規表現でいい感 じのアイテムクラス名を作ってそれをロードするようにするんや!」 エンジニアA 「よし!簡潔に書けていいな!」
数カ月後・・・
新しい効果をもつアイテムを追加することになりました
エンジニアB 「新しいアイテムのデータも追加したしアイテムの効果も 実装するか」 エンジニアB 「とりあえず他のアイテムのクラスを真似て作ろう」 エンジニアB 「クラス名はなんてすればいいんだ? grepしてもアイテム 効果クラスが使われている場所が見つからないぞ?」
None
今回の発表で伝えたいこと • 動的なモジュールロードは柔軟性がありすぎるので下手な使い方をす ると保守性が下がってしまう ◦ 静的なモジュールロードを行う方法でできないか検討しよう ◦ 動的なモジュールロードをする方が合理的なら保守性が下がらな いように工夫しよう
今日話すこと • 静的なモジュールロードと動的なモジュールロードについて • 動的なモジュールロードのメリット • 動的なモジュールロードのデメリット • 保守性を下げないようにするには
静的なモジュールロード • コンパイルフェーズで行うモジュールロードのこと • 通常は use でロード • ロードするタイミングやロードするモジュールに制約がかかる ◦
少なくともランタイムが開始する前にどんなモジュールがロードさ れるかが定まるようになっていないけない
動的なモジュールロード • ランタイムで行うモジュールロードのこと • ロードするタイミングやモジュールを好きなように決められる • 言語組み込みの機能で行うのなら require でのモジュールロード ◦
ロードするモジュールを動的に決めたいなら eval “require ...” • 通常は Module::Load, Class::Load などといったモジュールローダー を利用してロード
動的なモジュールロード • use する場合と挙動が違うところがあるので注意 ◦ import は自動的に呼ばれない ◦ CHECK, INITブロックに書かれたコードが実行されない
動的なモジュールロードを行うことによる メリット あるいはどのようなときに動的なモジュールロードを行いたくなるのか
コード量が少なくなる
for, while 文などでまとめてロードすればコード量が減る
Module::Find を利用すると、ある名前空間の下に属するモジュール をすべて読み込むことができる
Catalyst 風のモジュールローダーを利用する • useしなくてもモジュールを使える、use忘れがなくなる • パッケージ名を短く書ける
プラガブルなモジュールを簡単に作れる
モジュールに新たなメソッドを追加したりやモンキーパッチを当てれる ようにしたい場合 (Tengのようなケース)
None
与えられたものを読み取って何かするようなモジュールに、ルールを 追加していける構造にしたい (Perl::Critic のようなケース)
None
動的にディスパッチできる • 利用するモジュールを動的にディスパッチできる • プログラムの外部で管理されていたり、外部から受け付ける入力に応 じて処理を分岐させたい場合に非常に便利 ◦ 項目が多いマスタデータの種類に応じて ◦ HTTPリクエストの内容に応じて
動的にディスパッチできる
起動 / ロードにかかる時間の短縮 • モジュールをロードするタイミングをモジュール内のコードを実行する 直前にまで遅らせることで、アプリケーションの起動やモジュールの ロードにかかる時間を短くすることができる ◦ 当然その分実行時に短くした分の時間がかかる •
高速化を意識しているCPANモジュールや巨大なアプリケーションで よく見かける ◦ Moo, Type::Tiny, Class::Accessor::Lite, etc...
依存関係を動的に解決できる • 依存関係を動的に解決できる ◦ 条件に応じて依存モジュールを変更できる ◦ モジュールが相互に依存しても警告が発生しない • モジュールロードに失敗した場合の処理が書ける
動的なモジュールロードを行うことによる デメリット 開発体験にどのような悪影響がでるのか
可読性が下がる • 動的にロードするモジュール名を組み立てていると発生する問題 • 特に動的にモジュールロードされていることを知らない人がコードを 読むと、どこで何のモジュールが使われているのかがわかりにくい ◦ 特に正規表現でモジュール名を作ったりしていると非常に厳しい
可読性が下がる • 本質的には greppability の話 ◦ 調べたいコードが検索しにくい状態になってしまう ◦ 動的にシンボルを組み立てているとコードが検索しにくくて機械 も人間も辛い思いをする
◦ 静的解析を利用したツールの恩恵を授かれない恐れも
良くない設計の原因になる • どこでモジュールがロードがされるかわかりにくくなるので、注意しな いと混沌とした依存関係や構造ができあがる • モジュールの先頭で依存しているモジュールがまとめて use されて いる方が依存関係はわかりやすい •
依存関係が循環しているモジュールがあっても警告がでない
実際にロードされるまで動くかわからない • 依存しているモジュールがエラーなどで動かなくなっていても、実際 にコードが動くまでわからない • しっかりテストが書かれていたり、 Test::UseAllModules::all_use_ok みたいなテストが用意されてい るならそんなに問題にはならない •
またリッチな機能をもつエディタなら Syntax Error とかにも気づきや すい
つまり、むやみに動的なモジュールロード を行うと保守性が下がる
静的にモジュールロードする場合、柔軟性がない分 保守性が下がるような書き方をしにくい
なるべく静的にモジュールロードしたい
動的なモジュールロードを行うほうが合理的なときは、 なるべく保守性が下がらないようにしたい
どうするか
コード量を減らしたいとき
パッケージ名が長すぎる モジュールローダーの代わりに 定数や aliased でパッケージ名のエイリ アスを作る
use 忘れを防ぎたい • 現状代替案は知りません・・・ • いい方法を知っている方がいれば教えて下さい! • 理想を言えば他の言語みたいにエディタやIDEの機能でパッケージを 利用していたら自動でuseできるようになってほしい •
うたがわさんが便利そうなプラグインを作られていました ◦ 開発体験良くなりそうですね
まとめてロードしたい • 普通にuseする方法では不可能 • そもそもたくさんのモジュールをロードしたいケースは頻繁にあるの か? ◦ 拡張性を重視する構造でなければ、責務が大きくなりすぎている 可能性がある ◦
その場合はモジュールを分割すべき
まとめてロードしたい • 拡張性を重視していたり、useを延々と書き続けるのが現実的ではな い場合は動的にロードすべき • ただし保守性が低下しないように工夫する ◦ まとめすぎない (Module::Find::useall()) ◦
動的にパッケージ名を組み立てない ◦ Test::UseAllModules などを利用してコンパイルフェーズでエ ラーが起きないかをテストするようにする
プラグイン機構を実装したい時 • 手間がかかるが、プラグインオブジェクトを外でuseして作って渡すこ ともできる • フレームワークだったりプラガブルにしたい場合は動的にロードする のもよい • プロダクトのコード、特にビジネスロジックなどではプラガブルな構造 を用意するのはやり過ぎなケースが多い
◦ 基本的に保守性を重視して静的にロードする
モジュールに新たなメソッドを追加したりやモンキーパッチを当てれ るようにしたい場合 (Tengのようなケース)
None
動的にディスパッチしたい時 • 利用しうるモジュールは全て事前にロードしておき、外部からの値に 応じて利用するモジュールを分けるような対応表を書くことで対応で きる ◦ 数が多いなら対応表を自動生成する仕組みをつくるという手も • 工数、拡張性と保守性のトレードオフになるので状況に応じて判断 •
利用するパッケージ名を難しい正規表現とかで作っている場合は読 みにくくなるので対応表をちゃんと書くべき
動的にディスパッチしたい時
起動 / ロードにかかる時間の短縮 • 起動やロードにかかる時間を短縮したい場合は動的にロードするし かない • 保守性との引き換えになることを念頭に置いた上で、なるべく保守性 がおちないように工夫する ◦
良くない設計になってしまわないように注意を払う ◦ 動的にパッケージ名を組み立てない ◦ Test::UseAllModules などを利用してテストする
依存関係を動的に解決したい • 条件が実行する前に決まるなら if プラグマを利用したり、importや BEGIN句の中で頑張って静的にロードさせるようにすることができる • 依存関係が循環しているような場合は結合度が高く、設計としてよく ない状態になっているので設計を修正する
まとめ
まとめ • 動的なモジュールロードは下手な使い方をすると保守性が下がってし まう ◦ 静的なモジュールロードを行う方法でできないか検討しよう ◦ 動的なモジュールロードをする方が合理的なら保守性が下がらな いように工夫しよう
ご清聴ありがとうございました