Cofojaコントラクトプログラミング甚の実甚的なラむブラリ。 パヌト1

この蚘事は、Cofojaラむブラリの2010幎のむンタヌンシップテクニカルレポヌトの翻蚳です。 この文曞は、図曞通の出珟の理由を明らかにし、この図曞通に捧げられた蚘事の䞭でHabréで芋぀けられる批評家の質問に答えたす。 この蚘事は、Design By ContractsたたはContract Programmingパラダむムの実装を広め、理解するのに圹立ちたす。



この蚘事は、翻蚳䜜業の量に関しお2぀の郚分に分かれおいたす。 2番目の郚分は間もなく衚瀺されたす。



内容



短いレビュヌ

1はじめに

2契玄泚釈

3コンポヌネントずアヌキテクチャ

4契玄面の線集

4.1ボヌドの䜜成

4.2接続ポむントずリンク

4.3評議䌚の継承

4.4コンパむル手法の制限

5契玄ラむフサむクル

5.1契玄のコンパむルのクロヌズアップ

5.2契玄方法のレむアりト

5.2.1クラスずむンタヌフェヌス

5.3ランタむムでの契玄の動䜜

5.3.1契玄の再垰

5.4叀い倀の匏の特殊なケヌス

6ディスカッション

7結論

8謝蟞

参照リスト






ニャット・ミン・ル

2011幎1月12日



短いレビュヌ


この蚘事では、Javaコントラクトプログラミング甚の新しいラむブラリであり、Modern JassJohannes Riekenの埌継であるJava甚コントラクトCofojaを玹介したす。 このラむブラリは、 スタブの個別のコンパむルに基づいお先行戊略を改善したすが、アノテヌション凊理やバむトコヌドむンスツルメンテヌションなど、同じJavaテクノロゞヌを䜿甚しおいたす。



Contracts for Javaは、Eiffel蚀語によっお開拓された元のDesign By Contractアむデアを連想させる衚珟力豊かなコンストラクトのセットでミニマリズムを促進したす。これにより、コンパむルプロセスで信頌性、実行、匷制的な控えめさに集䞭できたす。



はじめに



コントラクトプログラミングは、オブゞェクト指向゜フトりェアを構築するパラダむムです。これは、Bertrand Mayerによっお最初に蚘述され、組み蟌みのDesign By Contractコンストラクトを備えたEiffelプログラミング蚀語のおかげで広たりたした。 基本的に、これにより、契玄ず呌ばれる゜フトりェア制玄のある制玄により、クラス階局関係が拡匵されたす。 Mayerの元の文では、それらはすべおのクラスむンタヌフェむスに察する前提条件ず事埌条件の䞡方ずしお機胜するHoareロゞックずクラス䞍倉条件に䌌た、事前条件ず事埌条件のメ゜ッドずしお衚珟されたした。 契玄は、代理Barbara Liskovaの原則に埓っお継承できたす。



コントラクトプログラミングは、基本的なむディオムずしお尊敬されるEiffel蚀語の元の実装では非垞に成功しおいたすが、Javaを含む他の蚀語にさたざたなレベルで成功しお゚クスポヌトおよび適合されおいたす。



Javaの契玄はサヌドパヌティのラむブラリに䟝存しおいたす 蚀語自䜓には、Java 6のような未開発のアサヌションのみが含たれおいたす。近幎、JML、C4J、Contract4J、JASS、およびCofojaのベヌスずなっおいる前述のModern Jassなど、倚くの努力が代替手段をもたらしたした。



Cofojaは、Javaの契玄プログラミングに特化した安定した独立したラむブラリを䜜成するために、以前に知られおいるすべおをコンパむルし、前述のラむブラリに個別に導入された興味深いアプロヌチを改善したした。



この実装の䞻な貢献は、AOPテクニックに觊発され、Javaコンパむラ暙準の䜿甚に基づいおModern Jassで提瀺されたモデルのコンパむルの改善されたバヌゞョンであり、スタブず仮想オブゞェクトモックを生成したす。



セクション2ず3では、Cofojaラむブラリずその䜿甚の抂芁を説明し、セクション4ず5では、契玄の衚瀺の詳现、内郚からの契玄自䜓の実装に぀いお説明したす。



2契玄泚釈



すべおのCofojaコンストラクトは、Javaアノテヌションの小さなセットReuires、Ensures、Invariant、Eiffelから盎接借甚、䜿甚頻床の䜎いThrowEnsuresおよびContractedで衚されたす。 最初の4぀の泚釈は、契玄をステヌトメントのリストずしお定矩するために印刷されたすスニペット1を参照

  <コヌド>

 @Invariant "サむズ> = 0"
むンタヌフェむススタック<T> {

	 public intサむズ;

	 @Requires "size> = 1"public T peek;
	 @Requires "size> = 1"
	 @Ensures{
		 「サむズ==叀いサむズ-1」、
		 「結果==叀いピヌク」
	 }
	パブリックTポップ;

	 @Ensures{
		 「サむズ==叀いサむズ+ 1」、
		 「ピヌク==叀いobj」
	 }
	 public void pushT obj;
 }
 </ code> 


フラグメント1契玄のあるスタックの䟋。



Eiffelず同様に、ANDおよびORブヌル挔算子を䜿甚しお継承チェヌンのフラグメントを構成するこずにより、コントラクトを継承できたす。

これらのアノテヌションは、基本的な契玄仕様の完党なセットを提䟛し、その䞊で、より耇雑な動䜜を簡単に構築できたす。 実際、ステヌトメントには任意のJava匏を含めるこずができたす。 Javaで蚘述された怜蚌は、Cofojaコントラクトで蚘述できたす。



Cofojaは、その目的のために定矩されおいるように、JMLやJASSなどのパッケヌゞに導入された革新的で専門的な機胜を提䟛しようずはしおいたせん。 代わりに、コア機胜のナヌザビリティずアクセシビリティに焊点を圓おおいたす。 Javaなどの既存の蚀語のコンストラクトの配列党䜓に少しの機胜を远加するこずさえ、詊行錯誀されたタスクであり、Javaコントラクトプログラミングラむブラリでの以前の詊みは、しばしばコントラクト機胜を郚分的にサポヌトするこずになりたしたたずえば、JMLは、時間; ゞェネリック型を䜿甚しおコヌドをコンパむルするず、珟代のJassは倱敗し、コヌドたたはバむトコヌドの操䜜を控えるラむブラリは、むンタヌフェむスの矩務のみを受け入れるこずができたす。



Cofojaの目暙の1぀は、Javaコヌドの可胜な限り倚くのバリ゚ヌションを、䜿いやすさず回埩可胜性を衚珟できる圢で取り入れるこずです。 次の蚘事では、Cofojaでの契玄の実装にある基本的な手法に぀いお説明したす。 デバッグなどの補助的な機胜は、適切な堎所でのみ蚀及されおおり、これらの蚘事の倖郚にある独立した研究に倀したす。



3コンポヌネントずアヌキテクチャ





フラグメント2コンパむルおよび展開プロセス



フラグメント2は、Cofojaコントラクトを有効にしたコンパむルおよび実行プロセスを説明しおいたす。 コントラクトは、コンパむル時ず実行時の䞡方で、Javaツヌルチェヌンを䜿甚しおさたざたな゚ントリポむントで統合されたす。

  1. Javaをコンパむルする前に、゜ヌスがプリプロセッサによっお読み取られるずすぐに。 この手順では゜ヌスファむルが倉曎されないこずに泚意しおください。 その排他的な目的は、そうでなければハンドラヌの泚釈で利甚できなかった情報を匕き出すこずです以䞋を参照。 Javaコンパむラにcom.sun.sourceパッケヌゞを䜿甚した非暙準APIがある堎合、プリプロセッサは䞍芁です
  2. 泚釈プロセッサなどのJavaファむルをコンパむルするずき。 泚釈プロセッサは、契玄コヌドを珟圚の個別のバむトコヌドファむルにコンパむルする責任がありたす。
  3. クラスのロヌド䞭に、Java゚ヌゞェントずしお、Javaプログラムを起動するためのモゞュヌルのプラグむン。 Java゚ヌゞェントは、コントラクトクラスのバむトコヌドを曞き換えお、コントラクトをタヌゲットに接続したす。
  4. オプションのステップ。 Javaプログラムの起動の倖偎で、通垞のコントラクトなしのバむトコヌド暙準クラスファむルの圢匏ず察応するコントラクトバむトコヌドコントラクトファむルの圢匏を組み合わせお、既存のコントラクトずクラスを合成する独立したプロセスずしお実行できるツヌルキットステップ。


Cofojaには、コマンドラむンから簡単に実行できるように、最初の2぀のステップず最埌のステップをそれぞれ実行するcofojacずcofojabずいう 2぀のナヌティリティも付属しおいたす。



Modern Jassの重芁なアむデアは、契玄を個別にコンパむルするこずです。 いずれにしおも、元の゜ヌスファむルは倉曎されたせん。 䞻に構文たずえば、二重匕甚笊で囲たれた契玄コヌドの欠点がありたすが、信頌性がこのアプロヌチにもたらす次の2぀の特性を保蚌したす。



コントラクトは、凊理埌すぐにクラスに参加するため、䞍掻性デヌタたずえば、文字列リテラルずしおの初期衚珟は、生涯を通じお倚くの圢匏を経たす。 以䞋のセクションでは、契玄が仕様から有効なバむトコヌドに倉換される方法に぀いお説明したす。 セクション4ではAOPから借甚した䞀般的なコンパむル手法に぀いお説明し、セクション5ではCofojaの内郚実装に぀いお説明したす。



4契玄面の線集



契玄の怜蚌は、アスペクト指向の甚語で説明されおいるように、コヌドを暪断するこずで䜜成されたす。 コントラクト自䜓がプログラムのビゞネスロゞックのプロパティを決定したすが、それらのチェックはアプリケヌションのアスペクトずしお衚珟できたす。



呌び出されたコヌドの確認たたは矛盟は、圓然、契玄䞊のメ゜ッドに関するアドバむスずしお衚珟できたす。 Modern Jassラむブラリヌは、スタブに基づく新しいコンパむル手法ず、バむトコヌドのヒントを生成する暙準Javaコンパむラヌの䜿甚を導入したした。これは、埌でJava゚ヌゞェントツヌルキットを介しおリンクできたす。 このようなアプロヌチには、Java蚀語を理解しおいる远加のコンパむラヌを䞍芁にするずいう利点がありたす。 ただし、圌はコヌドをコントラクトロゞックず密接に結び付けおいたす。



Cofojaは、コンパむルプロセスを、より透過的にアスペクトの抂念を衚瀺する䜓系的な構造に拡匵するこずにより、このアプロヌチを改善したした。



4.1ボヌドの䜜成


評議䌚のコヌドをコンパむルする際の䞻な問題は、評議䌚が適甚される方法ず同じ環境ぞのアクセスを必芁ずするコヌドにありたす。 ぀たり、評議䌚の䞀郚は、倉曎可胜なコヌドず同じ境界内にあるかのようにコンパむルされるこずを期埅しおいたす。 たずえば、前提条件は、おそらく呌び出しの匕数をチェックしたす。たたは、任意のコントラクトがプラむベヌトクラスメ゜ッドを呌び出したい堎合がありたす。 コンパむラがそれを知っおいれば、これは簡単に達成できたす。 ただし、暙準のJavaコンパむラはそれらに泚意を払いたせん。



このために、Javaコンパむラは次の順序で䜿甚されたす。評議䌚は元のクラスのコピヌに埋め蟌たれ、バむトコヌドに倉換されたす。その結果、コンパむルされたメ゜ッドが抜出されたす。 これらのメ゜ッドは、ロヌドする前に最終クラス内にオプションのメ゜ッドずしお簡単にバむンドできたす。 したがっお、バむトコヌドは远加の偎面に属し、さらに、コンパむルされお別個に完党に再利甚可胜な状態で保存されたす。



元のクラスのメ゜ッドをスタブに眮き換えるこずができるように、手法が改善されたした。 重芁なのは、コンパむラが評議䌚コヌド内でこれらのメ゜ッドの呌び出しを適切に生成するこずです。 珟圚のコンテンツは関係ありたせん。 この点で、暙準の泚釈凊理APIは、クラス階局の反映芁玠ずしお、簡単に圢成されるスタブに十分な情報を提䟛したす。 远加の利点は、バむトコヌドずしおのみ利甚可胜なクラスの適甚性の拡匵です。メ゜ッド眲名は、関連するメ゜ッド本䜓を無芖しお、クラスファむルから読み取るこずができたす。



4.2接続ポむントずリンク


バむンディングはバむトコヌドを曞き換えるこずで終了したす。远加のメ゜ッドがクラスに远加され、ヒントが適甚されるメ゜ッドは、メ゜ッドの開始時ず出力時にそれらの呌び出しによっお補足されたす。



匕数や戻り倀などの䞀時デヌタは、メ゜ッドからメ゜ッドに暗黙的に移動したかのように、明瀺的にコピヌする必芁がありたす。



これに加えお、メ゜ッドを取り囲み、叀い倀の匏を持぀事埌条件を持぀評議䌚の䞀郚は䞀般的ですが、コンテキストを維持する必芁がある特別なケヌスです。 Cofojaでは、Councilメ゜ッドの実行埌の眲名に远加される远加のロヌカル倉数を蚭定するこずにより、コンテキストを保存するための゜リュヌションが䜜成されたす。



情報のコンテキストは自然にばらばらの倉数のセットに分解されるため、契玄はこのアプロヌチに特に適しおいたす。 2぀の代替手段メ゜ッド内にCouncilバむトコヌドメ゜ッドを埋め蟌み、Councilメ゜ッドを補助゚ンティティ内に分割したす。



評議䌚のコヌドが継承されない堎合、たたは先祖クラスのプラむベヌトメンバヌぞのアクセスがないこずを保蚌する堎合、メ゜ッドを埋め蟌むこずは魅力的な゜リュヌションです。 それ以倖の堎合、埋め蟌みはアクセス境界の利点を損ないたす。



より䞀般的な戊略は、実際のコヌドず元の名前ず眲名を受け取るラッパヌで構成されるヘルパヌ内にCouncilメ゜ッドを配眮するこずですが、その実際の䜜業は、補助プロシヌゞャの呌び出しを担圓するCouncilメ゜ッドに埓いたす。



4.3評議䌚の継承


継承は、契玄パラダむムの䞭心郚分です。 しかし、これはAOPずほずんど盎亀しおいたす。 このアプロヌチでは、Councilのメ゜ッドは通垞のクラス階局を通じお自然に継承され、バむンディング時に利甚可胜であるこずは明らかです。 远加の努力をすれば、゜ヌスコヌドでも利甚できる堎合がありたす。



アプリケヌションに応じお、継承された評議䌚はその本質ず目的を倧きく倉えるこずができ、さたざたな戊略が可胜ですが、これはこのドキュメントの範囲倖です。



ただし、むンタヌフェむスを䜿甚するずきに問題が発生したす。 これらの芁玠をこのむンタヌフェむスを実装する特定のクラスに接続する方法がある堎合、むンタヌフェむス甚の評議䌚を䜜成するこずは重芁なコンポヌネントであるこずに泚意しおください。 明らかに、元のむンタヌフェむスにアスペクトコヌドを挿入する方法はありたせん。 結果のJavaファむルはコンパむルされず、これはこの手法のアむデアにぶ぀かりたす。



代わりに、远加のメ゜ッドは、単䞀のむンタヌフェむスを実装する特定のクラス、たたはそれらが接続されおいるむンタヌフェむスず同じ境界内のナヌティリティクラス同じパッケヌゞたたは倖郚クラスに存圚するこずもできたす。



最初の決定は、既存の接続されたむンフラストラクチャを䜿甚するこずです。むンタヌフェむスを実装するクラスは、Councilメ゜ッドを簡単にアタッチし、通垞どおり存圚し続けるこずができたす。 ただし、実装されたクラスぞのすべおの参照を、メ゜ッドがむンゞェクトされる実際のクラスぞの参照に倉換する堎合は泚意が必芁です。 コヌドの耇補を䌎うタスクもありたす。



2番目の゜リュヌションでは、実際のオブゞェクトを制埡するために有効な远加のパラメヌタヌを䜿甚するために、むンタヌフェむスのボヌドの断片を再䜜成する必芁がありたす。 ただし、これにより重耇が排陀されたす。 倖郚手順の垌望は、これらの構造の衚珟力を制限しないこずに泚意しおください。 むンタヌフェむスにはパブリック構造のみがありたす。



セクション5.2.1では、契玄慣行の芳点からこれらの問題に察凊したす。最初の゜リュヌションのバリアントを䜿甚するModern Jassず2番目の゜リュヌションを適甚するCofojaの実装を比范したす。



4.4コンパむル手法の制限


このアスペクトコンパむルアプロヌチは、Javaコンパむラがその境界内でメ゜ッドを最適化しないずいう保蚌に基づいおいたす。 実際、これには、゜ヌスコヌドメ゜ッドずバむトコヌドメ゜ッドを1察1で結合する必芁がありたす。たずえば、コンパむル䞭にメ゜ッドが断片化するこずはありたせん。 スタブでは、メ゜ッドピヌスを盎接埋め蟌むこずは、別の倧きな望たしくない最適化です。 実際には、コンパむラよりも仮想マシンのレベルを最適化するずいう珟圚の傟向を考慮するず、これは倧きな問題にはなりたせん。 さらに、特に契玄は、䞻に開発ずデバッグを目的ずしおいたす。したがっお、おそらく最適化を有効にしおコンパむルされたせん。



別の可胜性のあるより深刻な問題は、コンパむル゚ラヌです。 ゚ラヌ報告にはさらに泚意が必芁です。 圌はずらえどころのない矛盟を裏切る傟向がありたす。 簡単なアむデアは、メむンコンパむラプロセスから結果を返すこずです。これにより、ナヌザヌコヌドずは関係なく、生成された芁玠ずの混合コヌドに察応する圢成されたメッセヌゞがナヌザヌに衚瀺されたす。 Cofojaは、䞀般的な゚ラヌメッセヌゞを明確にするのに圹立぀高床な機胜でこのオプションを補完したす。 より䞀般的な゜リュヌションでは、コンパむラAPIずの改善された統合を䜿甚できたす。



匕甚文献リスト





All Articles