1

契約による設計の部分的な実施のアイデアについて、いくつかの意見を聞きたいと思います。目標は、外部ライブラリを必要とせずに、ライトバージョンのコントラクト(不変条件と事後条件のみ)を提供しない言語に追加することです。

私の例はJavaで書かれていますが、このアイデアは多くのオブジェクト指向言語に適していると思います。

次のようなクラスがあります。

class myClass{
    type1 field1;
    type2 field2;

    public myClass(type1 param1){
        //do something
    }

    public type3 method1(type1 param1, type3 param2){
        if (paramsAreNotOk()){
            throw new IllegalArgumentException();
        }
        // do a lot of things
        return //do something
    }
}

上記のコードを次のように拡張します。

class myClass{
    type1 field1;
    type2 field2;

    public myClass(type1 param1){
        //do something

        assert invariant();
    }

    public type3 method1(final type1 param1, final type3 param2){
        assert invariant();
        myClass old;
        assert ((old = this.clone()) != null)

        if (paramsAreNotOk()){
            throw new IllegalArgumentException();
        }
        //do a lot of things
        type3 res = //do something

        assert method1_post(old, param1, param2, res);
        assert invariant();
        return res;
    }

    protected boolean invariant(){
        // states something about myClass and return a boolean
        // OR
        // uses some assertions on some helping methods
    }

    protected boolean method1_post(myClass old, type1 param1, type3 param2, type3 res){
        // states something about res and about the modifications made on old
        // OR
        // uses some assertions on some helping methods
    }
}

このアプローチの制限:
-前提条件はありません。
-コントラクトは継承されません(ただし、不変条件と事後条件は保護されており、サブクラスで再利用できることに注意してください)。
-不変条件と事後条件がオブジェクトの状態を変更しないというチェックはありません。したがって、副作用のリスクがあります。
-契約は明確な方法で私たちの文書の一部ではありません。
-すべてのクラスを複製可能にする必要があります。

さて、いくつかの質問:
-この方法はパフォーマンスに何らかの影響を及ぼしますか?アサーションが無効になっている場合、古いローカル変数とresローカル変数でさえJITコンパイラによって削除されるということですか?
-このアプローチの欠点はありますか?なぜあなたはあなたのクラスでこれを使わないのですか?
-改善を提案できますか?

読んでいただきありがとうございます。

4

3 に答える 3

2

Javaの「契約による設計」が必要な場合は、(実際に)大物がどのようにそれを行っているかを確認することをお勧めします。これは、「Javaの契約」に関するGoogleの最近の見解です。

http://google-opensource.blogspot.com/2011/02/contracts-for-java.html

次に、2つの質問に答えます。

- do you see any downside of this approach? Why wouldn't you use this in your classes?

欠点の1つは、非常に冗長であるためです。コードがほとんど読めなくなるほど冗長です。

- can you suggest any improvement?

車輪の再発明をしないでください...

于 2011-02-26T10:44:39.560 に答える
2

それは恐ろしいことではありません、そして実際それはあなたの前に他の人によって書かれました。たとえば、Liskov / GuttagのJavaでのプログラム開発を参照してください。これは、不変チェックへのアプローチを採用していますが、不変()ではなくrepOK()と呼んでいます。

限られたアプリケーションでは、それはちょっと機能します。しかし、契約仕様では、実際のコードが行うような「誰が誰を呼んでいるのか」という問題について心配する必要がないという事実から生じる多くの問題があります。

  • 別のメソッドGを呼び出すメソッドFがあるとします。Fが実行中にrep不変条件を壊し、戻る前に修正するとします。これは許可されており、場合によっては必要ですが、Gはそれを認識しておらず、誤って例外を発生させます。
  • コンストラクターはもっと悪いです。クラスDがクラスCを拡張し、invariant()をオーバーライドするとします。D()はC()を呼び出し、C()はD.invariant()を呼び出しますが、これは間違っています。Cは、それ自体よりも強いDの不変量を満たす必要はありません。
  • クラス外のクライアントからメソッドに間違った引数が渡された場合、IllegalArgumentExceptionは問題ありません。ただし、発信者がクラス内にいる場合、これは通常の古い契約違反です。2つを区別したい。興味があれば、 Gary Leavensが、このペーパーでJMLがどのようにそれを行うかについて話します。
  • 他のクラスメソッドで表現された事後条件(つまり、「事後条件」)は、チェックすると無限の相互再帰を引き起こします。

私の考えでは、DbCは興味深いものであり、言語にDbC(または、Pythonの関数デコレータのようなもの)がある場合、またはModern Jassのようなツールがある場合は、掘り下げてください。しかし、純粋なJavaでそれを行うことは現実的ではありません。 。とは言うものの、私はここにあるものと同様のコードを生成する不変のチェックツールに取り組んでいますが、コールチェーンの問題はありません(代わりに、チェックを行うのが適切な時期を知っている訪問者を受け入れるようにクラスを拡張することで機能します) 。Eclipseが必要であり、それ自体に問題があります(主に、privateやstaticなどの関連する不適切な単語)が、チェックメカニズムは純粋なJavaです。

于 2011-10-23T21:55:35.887 に答える
0

このアプローチの欠点はありますか?なぜあなたはあなたのクラスでこれを使わないのですか?

私が書いたほとんどのJavaクラスは、Javaで正しく実装するのは簡単ではないため、クローン化できませんClonable。したがって、絶対に必要でない場合は実装しません。私はあなたのアプローチのためだけにこれをする必要はありません。

于 2011-02-26T11:01:38.653 に答える