$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Perlにおける動的なモジュールロードのメリットとデメリット
Search
ybrliiu
November 03, 2019
Technology
0
880
Perlにおける動的なモジュールロードのメリットとデメリット
ybrliiu
November 03, 2019
Tweet
Share
More Decks by ybrliiu
See All by ybrliiu
これまでと、これからのPerlコミュニティ
ybrliiu
0
170
AstroNvim を使おう!
ybrliiu
0
4.9k
Perlでも関数の型をチェックしたい
ybrliiu
0
3.4k
Perl5.32の新機能
ybrliiu
0
170
Vue.jsで作ったサイトをバニラJSで書き直す悲しいお話
ybrliiu
1
1.1k
黒魔術で独自定義のenum型制約を満たす値のリ ストを取得する話
ybrliiu
0
430
Perlにおけるクラスの実装パターン.pdf
ybrliiu
0
1.7k
Presentation.pdf
ybrliiu
0
280
ぼくがPerlで開発を行う時に工夫していること
ybrliiu
0
560
Other Decks in Technology
See All in Technology
LLM-Readyなデータ基盤を高速に構築するためのアジャイルデータモデリングの実例
kashira
0
210
Debugging Edge AI on Zephyr and Lessons Learned
iotengineer22
0
120
Noを伝える技術2025: 爆速合意形成のためのNICOフレームワーク速習 #pmconf2025
aki_iinuma
2
2.1k
非CUDAの悲哀 〜Claude Code と挑んだ image to 3D “Hunyuan3D”を EVO-X2(Ryzen AI Max+395)で動作させるチャレンジ〜
hawkymisc
1
160
AIと二人三脚で育てた、個人開発アプリグロース術
zozotech
PRO
0
690
5分で知るMicrosoft Ignite
taiponrock
PRO
0
220
直接メモリアクセス
koba789
0
280
技術以外の世界に『越境』しエンジニアとして進化を遂げる 〜Kotlinへの愛とDevHRとしての挑戦を添えて〜
subroh0508
1
390
計算機科学をRubyと歩む 〜DFA型正規表現エンジンをつくる~
ydah
3
200
エンジニアリングマネージャー はじめての目標設定と評価
halkt
0
250
AI時代の開発フローとともに気を付けたいこと
kkamegawa
0
2.3k
【pmconf2025】PdMの「責任感」がチームを弱くする?「分業型」から全員がユーザー価値に本気で向き合う「共創型開発チーム」への変遷
toshimasa012345
0
270
Featured
See All Featured
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
The Language of Interfaces
destraynor
162
25k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
54k
It's Worth the Effort
3n
187
29k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
Making the Leap to Tech Lead
cromwellryan
135
9.7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
36
6.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Designing for humans not robots
tammielis
254
26k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
The Invisible Side of Design
smashingmag
302
51k
A designer walks into a library…
pauljervisheath
210
24k
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句の中で頑張って静的にロードさせるようにすることができる • 依存関係が循環しているような場合は結合度が高く、設計としてよく ない状態になっているので設計を修正する
まとめ
まとめ • 動的なモジュールロードは下手な使い方をすると保守性が下がってし まう ◦ 静的なモジュールロードを行う方法でできないか検討しよう ◦ 動的なモジュールロードをする方が合理的なら保守性が下がらな いように工夫しよう
ご清聴ありがとうございました