モンキーパッチ

モンキーパッチ（Monkey patch）は、システムソフトウェアを補完するために、プログラムをその時その場の実行範囲内で拡張または修正するというテクニックである。モンキーパッチの影響はその時その場のプロセス（プログラムの実行インスタンス）だけに限定されて、プログラム本体には及ばない。

モンキーパッチは動的プログラミング分野の用語であり、その定義はRubyやPythonなどの各言語コミュニティに依存している。サードパーティ製のランタイムシステム、ソフトウェアフレームワーク、仮想マシン上で発生しがちな、好ましくない動作の違いや各種バグに対してパッチ当てすることを目的にしての、プロセス上に展開されたクラスコードやモジュールコードの動的な修正作業、という点は共通している。

語源
当初はモンキーパッチは、ルールを無視して実行時にこっそりとコードを変更することから、ゲリラパッチと呼ばれていた。これらのパッチを複数当てると、時折直感に反するような相互作用が生まれることがあり、Zope 2では、交戦中のパッチと呼ばれていた。

ゲリラはゴリラとほぼ同音異字であり、ゲリラパッチをゴリラパッチと言う人が出てきた。そしてゴリラがより弱いモンキーとなり、戦いを思い起こさせるゲリラパッチではなく、弱そうに聞こえるモンキーパッチという言葉として使われ始めた。

それ以来モンキーパッチとして使用され続けているが、意味は使用するコミュニティ毎に微妙に異なっている。

Pythonでは、バグや思い通りに動かない機能の修正のために、外部のクラスにある既存のメソッドに対し、パッチを当てることで実行時のクラスを動的に変更する場合にのみ使用する。 他の形式の、実行時のクラスの変更には、他の名前が付いている。例えば、ZopeとPloneでは、セキュリティパッチは動的なクラスの変更によって提供されるが、これらはホットフィックスと呼ばれる。

Rubyでは、「あらゆるクラスに対する動的な変更」を意味し、「実行時の動的なクラスの変更」と同義語である。

Ruby界では、モンキーパッチングの代わりにダックパンチングという用語を使い始めた人もいる。この用語は、Adam Keysとpatrick EwingがRailsConf 2007で説明した用語で、RubyとPythonではダックタイピングが広く使われていることから来たものである: 

応用例
モンキーパッチは以下の用途で使用される。
 メソッド/属性/関数を実行時に置き換えることで、テストの間は使用される関数をスタブに変更して、何もアウトプットしないようにする。
 ソースコードの私的なコピーをメンテナンスし続けることなく、サードパーティ製のプログラムの振る舞いを変更したり、拡張したりする。
 ディスク上のソースコードを書き換えることなく、実行時に、メモリ中のオブジェクトに対してパッチを適用する。
 オリジナルのソースコードと並存するようなセキュリティフィックス及び、動作のフィックスの配布。Ruby on Railsプラットフォーム用のプラグインとして配布されている修正パッチがこれの例になる。

落とし穴
丁寧に作られていなかったり、ドキュメントが貧弱だったりするモンキーパッチからは、以下のような問題が引き起こされることがある:
状況が変わり、そのパッチが、変更される対象のオブジェクトに対して仮定していることがもう正しくなくなってしまった場合に、アップグレードにまつわる問題が引きおこされる。もしもパッチを適用したプロダクトが新バージョンになって変更されると、パッチが壊れて動作しなくなる可能性が高い。このような理由からほとんどの場合において、モンキーパッチは、条件をチェックして、適切な時だけ適用するように作られる。
もしも、同じメソッドに対して、2つのモジュールが同時にモンキーパッチを適用しようとすると、それがalias_method_chainのようなパターンを使用して書かれていない限りは後から実行した方が"勝ち"、もう片方のパッチは動作しない。
モンキーパッチを適用すると、ディスク上の元のソースコードと、見た目の振る舞いが異なるため、パッチの存在に気づかなかった人を混乱させる可能性がある。

例え使用されていなかったとしても、プログラミング言語内でモンキーパッチを適用できるということは、強いカプセル化を強制することと両立しないため、モンキーパッチの機能の有用性は問題である、と見る人も中にはいる。このオブジェクト間のカプセル化は、Object-capability modelで必要とされる。

脚注

関連項目
 動的プログラミング
パッチ
自己書き換えコード
動的ローディング
動的リンク
アスペクト指向

Category:オブジェクト指向
Category:プログラミング言語の構文