180 likes | 362 Views
破壊的クラス拡張のスコープを制限 する モジュール機構 の意味論およびその実装方法. ++. +, ++. 竹下 若菜,赤井 駿平,千葉 滋 + 東京大学 創造情報学専攻 ++ 東京工業大学 数理・計算学専攻. +. 破壊的クラス拡張. 既存のコードを変更せずに 既存のクラスにメソッドの追加・再定義 コードの再利用 サブクラスに関する変更・オブジェクト 生成部分の 書き換えが不必要. class Window{ : void setBorder (){ // WindowsXP の // フレームのボーダー }
E N D
破壊的クラス拡張のスコープを制限するモジュール機構の意味論およびその実装方法破壊的クラス拡張のスコープを制限するモジュール機構の意味論およびその実装方法 ++ +, ++ 竹下若菜,赤井駿平,千葉滋 +東京大学創造情報学専攻 ++東京工業大学数理・計算学専攻 +
破壊的クラス拡張 • 既存のコードを変更せずに • 既存のクラスにメソッドの追加・再定義 • コードの再利用 • サブクラスに関する変更・オブジェクト生成部分の書き換えが不必要 class Window{ : void setBorder(){ //WindowsXPの //フレームのボーダー } } Windowクラス win7パッケージ reviseWindow{ } void setBorder(){ //Windows7の //フレームのボーダー } void setBorder(){ //Windows7の //フレームのボーダー } Frameクラス Dialogクラス
例:ウィジェットを破壊的クラス拡張する • 2種類のlook&feelを持ったアプリケーションを作る • Windows 7のlook&feelだが、ボーダーだけはこのアプリケーション専用のデザイン • 管理者権限認証時だけは特別なlook&feel • インストール時など • ウイルスに偽パネルを出されにくいように
authenticationパッケージ 多重再定義の危険 • 同じクラスに対して破壊的クラス拡張を複数行うとメソッド名が衝突する危険性 revise Window{ } void setBorder(){ //管理者権限認証用の //フレームのボーダー } void setBorder(){ //管理者権限認証用の //フレームのボーダー } win7パッケージ revise Window{ } void setBorder(){ //Windows7の //フレームのボーダー } void setBorder(){ //Windows7の //フレームのボーダー } 元クラス class Window{ void setButtonColor(){ //WindowsXPデザイン } void setSize(){ ・・・・ } void setBorder(){ //WindowsXPの //フレームのボーダー } } void setButtonColor(){ //Windows7デザイン } void setButtonColor(){ //Windows7デザイン } 多重 再定義 appパッケージ revise Window{ } void setBorder(){ //アプリケーションの //フレームのボーダー } void setBorder(){ //アプリケーションの //フレームのボーダー }
用途に応じた柔軟なスコーピング • 用途に応じた柔軟なスコーピングが必要 • スコーピングはメソッド名衝突を回避する方法の一つ • 破壊的クラス拡張の影響範囲を制限 • 既存のスコーピングは固定的 • Ruby: 最新の定義が有効(スコープは制限しない) • RubyのRefinements: 有効な静的スコープを指定 • Classboxes: 有効な動的スコープを指定
提案:モジュール機構Method Shelters • 様々なスコーピングをとることができるモジュール機構 • モジュール:シェルター • 破壊的クラス拡張とrequire宣言を持つ • require宣言で他のシェルターをシェルター内に取り込むことができる • 取り込んだシェルター内の破壊的クラス拡張はそのシェルターで定義したかのように扱える • 2種類のrequire • 使い分けることで様々なスコーピングを可能に • 動的なスコーピングの中に静的なスコーピングを実現 • exposedlyrequireとhiddenlyrequire
exposedly hiddenly win7シェルター authenticationシェルター revise Window{ 権限認証用の //フレームのボーダー } void setButtonColor(){…} void checkPass(){ : setBorder(); : revise Window{ : setBorder(); : void setBorder(){ //管理者権限認証用の //フレームのボーダー } void setButtonColor(){…} void checkPass(){ : setBorder(); : }} void setBorder(){ //windows7用の //フレームのボーダー} void setButtonColor(){…} void makeFrame(){ : setBorder(); : } appシェルター requires win7; requires hiddenly authentication; revise Window{ void setBorder(){ //アプリケーション用のボーダー} void install(){ : checkPass(); : makeFrame(); : }}} void setBorder(){ //アプリケーション用のボーダー} void install(){ : checkPass(); : makeFrame(); : }}}
exposedlyrequire win7シェルター authenticationシェルター void makeFrame(){ : } • 推移的なrequire • requireしたシェルター中のメソッド定義をさらに再定義できる • 繰り返しシェルターをrequireすることでメソッドを何度も再定義可能 appシェルター requires win7; requires hiddenlyauth; : makeFrame(); 呼び出し 呼び出し update_appシェルター requires app; void makeFrame(){ : }
hiddenlyrequire win7シェルター authenticationシェルター void checkPass(){ : } • 非推移的なrequire • requireしたメソッド定義をさらに再定義することはできない • 他のシェルターに影響を与えない・影響されない appシェルター requires win7; requires hiddenlyauth; : checkPass(); 呼び出し update_appシェルター requires app; void checkPass(){ : }
シェルターによるスコーピング • 2種類のrequireで柔軟なスコーピング • 既存のスコーピングも可能 • RubyのRefinements • hiddenly requireで実現可能 • Classboxes • exposedly requireで実現可能
メソッド探索 メソッド呼び出し G • ルートから探索 • 再定義されている可能性があるため F D ここから探索 メソッド呼び出し E C B ここから探索 A
メソッド探索の実装方法 • 実行時の文脈に依存したメソッド探索 • コールスタックによりパスをチェックし、呼び出すメソッド定義を決定 void update(){ setBorder(); } <シェルター名> <クラス名>.<メソッド名> stdGUI setBorderの定義 authentication Window.setBorder stdGUI Window.update authentication win7 authentication Window.checkPass app app Window.install コールスタック
効率の良い実装方法 • コンパイル時に変更 • コールスタックを探索せずにメソッド定義を決定できるようにする • クラス名とメソッド名のみで探索ができるようにする • 通常のメソッド探索のコストに近づける • 操作的な定義を素朴に実装すると実行時間のコストがかかる
効率の良い実装方法1 • 実行時にコールスタックを見る必要をなくす • シェルターのrequire関係の木構造を静的解析 • コールスタックを探索せずにメソッドを決定 • ノード毎に一意なメソッド定義が決定 D D D ACD D D ABD AC AB B C A A
効率の良い実装方法2 • クラス名とメソッド名のみでメソッド探索を可能に • 一意に決定したメソッド定義のメソッド名を変更 • メソッド名とメソッド定義が一対一に対応 • メソッド呼び出し元も書き換える ABDノード void setFrame{ setBorder(); } void setBorder(){ //win7のボーダー } 呼び出し 変更前 ABDノード void setFrame{ setBorder_ABD(); } void setBorder_ABD(){ //win7のボーダー } 呼び出し 変更後
形式化 実装方法の形式化 操作的な定義の形式化
関連研究 • 前身研究:Method Shelters[赤井・千葉 AOSD ’12] • chamberによってシェルターの中を二つに分ける • hidden chamberとexposed chamber • chamberの中に破壊的クラス拡張とインポート宣言 • インポートは一種類 • 形式化がない • 破壊的クラス拡張は以下の言語に実装されている • Smalltalk, Ruby, AspectJ, MultiJava,GluonJ…….. • Classbox/J • ClassboxesをJavaに導入した
まとめ • モジュール機構Method Shelters • 2種類のrequireで様々なスコーピングを可能に • exposedlyなrequireとhiddenlyなrequire • 実装前と同コストでメソッド探索が可能な実装方法の提案 • 形式化 • 今後の予定 • 実際にJavaに実装してみる