モンキーパッチのプログラミングスタイルとRubyでの利用について
モンキーパッチとは?動的言語において、ソースコードに手を加えることなく、機能の追加や変更を行うこと。
モンキーパッチを使用する目的
1. 追加機能
2、機能変更
3、プログラムエラーの修正
4. ログの出力、AOPの実装など、メソッド実行中に何らかの処理を行うフックを追加する。
5.キャッシュ、大量の計算の場合、決済後の結果を繰り返し利用できるため、計算終了後のメソッドの入れ替えにより、処理速度を向上させることができる。
Rubyのクラスはオープンクラス、つまりクラス定義の後に任意の内容を追加できるため、Rubyでは特にモンキーパッチの利用が容易です。また、Rubyにはメソッド、クラス、モジュールを操作する機能があり、モンキーパッチをさらに使いやすくしています。
のエイリアスです。メソッドのエイリアス
include: 他のモジュールからメソッドを導入する
remove_method: このクラスからメソッドを削除します。
undef:メソッドをキャンセルする
Rubyでモンキーパッチを使う
私が遭遇していたシナリオは、こんな感じでした。
弊社ではEC2の運用にサードパーティのライブラリであるfogを使用しています。インスタンスの作成など、多くのコマンドでインスタンスタイプのパラメータを設定する必要があります。fogでは、すべてのEC2タイプがfog/aws/models/compute/flavors.rbのFLAVORS配列で定義されています。FLAVORS配列にないタイプを設定すると、fogはそれを無効なパラメータとして扱い、エラーを報告します。
その後、Amazonが新しいインスタンスタイプD2をリリースしました。Rubyのサードパーティコミュニティは非常に活発ですが、fogの開発コミュニティはflavors.rbにD2を追加するのに間に合わず、我々の仕事ではD2インスタンスを緊急に使用する必要があります。
背景がわかったところで、どうすればいいのか見てみましょう。
方法1:新しいタイプを追加するために、fogにPull Requestを提出することができます。
しかし、この方法はうまくいきません。knife-ec2 の fog へのバージョン依存は 1.25.* でなければなりませんが、fog は 1.31.0 に更新されており、fog は 1.27.0 から構造が大きく変わっています。明らかに、新しいバージョンの fog をサポートするために knife-ec2 が更新されるのを待つことはできないので、fog を更新するための Pull Request を提出することができません。
方法2:古いfogを手動で更新する 最新バージョンのfogを使うことができないので、1.25バージョンのfogを手動で編集してGemとしてパッケージングします。この方法は、前の方法よりも簡単ですが、メンテナンスが容易ではないという問題があります。非常に小さな変更のためにサードパーティのライブラリに自分のコードを追加することは、必ずしも "clean"十分に感じられるものではありません。
最後に、同僚からの指導もあり、3番目のアプローチであるモンキーパッチを行いました。Rubyプロジェクトにlib/PROJECT_NAME/monkey_patches/flavors.rbを追加し、次のコードを fog/aws/models/ compute/flavors に加えました。
require 'fog/aws/models/compute/flavors'
class Object
def redef_without_warning(const, value)
mod = self.is_a?(Module) ? self : self.class
mod.send(:remove_const, const) if mod.const_defined?(const)
mod.const_set(const, value)
end
end
module Fog
module Compute
class AWS
NEW_FLAVORS = FLAVORS + [
{
:id => "d2.xlarge",
...
},
{
:id => "d2.2xlarge",
...
},
{
:id => "d2.4xlarge",
...
},
{
:id => "d2.8xlarge",
...
}
]
redef_without_warning :FLAVORS, NEW_FLAVORS
end
end
end
概要
自作のコードにMonkeyのパッチを追加することで、fogに新しいインスタンスタイプを動的に追加することができました。そして、この方法は、最小限のコード変更で、より簡単に維持することができるようになりました。
モンキーパッチは完璧な解決策ではなく、いくつかの落とし穴があります。そのため、この手法はソフトウェア工学の世界ではいまだに賛否両論があります。しかし、私はMonkey Patchが良いゼロデイソリューションであると信じています。
関連
-
Railsにフィールド暗号化ストレージを実装
-
Ruby on Railsフレームワークの設計構造をMVCマインドで理解する
-
Rubyのgemパッケージ管理およびgemソース構築のチュートリアル
-
Ruby on Railsで構築するアプリケーションの基本的なディレクトリ構造のまとめ
-
Jekyll静的ウェブサイトのバックエンドエンジンのチュートリアル
-
Nokogiriパッケージを使ってXML形式のデータを操作するためのRubyチュートリアル
-
RubyでXMLデータ処理ライブラリREXMLを使うための手引き
-
RubyのプログラムでXML形式のデータをパースするためにREXMLを呼び出す例
-
デザインパターンのうち、ProxyパターンとDecorativeパターンを使ったRubyのコード例
-
Rubyの基本構文
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン