28

私はグループの開発プロセスの改善に取り組んでおり、テスト駆動開発による契約による設計をどのように実装するのが最善かを検討しています。2 つの手法には多くの重複があるようです。次の (関連する) 質問について誰かが洞察を持っているかどうか疑問に思っていました。

  • コントラクトに基づいて単体テストを生成するために何らかのコード ジェネレーターを使用していない限り、TDD と DbC を使用するのは DRY の原則に反していませんか? そうしないと、2 つの場所 (テストとコントラクト自体) でコントラクトを維持する必要があります。
  • TDD は DbC をどの程度冗長にしますか? テストを十分に書けば、それは契約書を書くことと同等ではないでしょうか? テストだけでなく、実行時にもコントラクトを強制した場合にのみ、追加のメリットが得られますか?
  • DbCでTDDを使用するのではなく、TDDのみを使用する方がはるかに簡単/柔軟ですか?

これらの質問の主なポイントは、より一般的な質問です:既に適切に TDD を実行している場合、DbC も使用すると、オーバーヘッドに対して大きなメリットが得られるでしょうか?

質問は主に言語に依存しないと思いますが、いくつかの詳細:

  • 私たちのチームは非常に小さく、プログラマーは 10 人未満です。
  • 主にPerlを使用しています。
4

8 に答える 8

39

違いに注意してください。

契約による設計。契約主導の設計

テスト駆動型の開発。テスト駆動開発

それらは、一方が他方に先行するという点で関連しています。それらは、さまざまな抽象化レベルでソフトウェアを記述します。

実装に行くときに設計を破棄しますか? 設計書はDRYに違反していると思いますか? コントラクトとコードを別々に管理していますか?

ソフトウェアはコントラクトの実装の 1 つです。テストは別です。ユーザーズマニュアルは3番目です。オペレーション ガイドは 4 番目です。データベースのバックアップ/復元手順は、契約の実装の一部です。

Design by Contract による オーバーヘッドは見当たりません。

  • すでにデザインを行っている場合は、形式をあまりにも多くの単語から適切な単語に変更して、契約関係を概説します。

  • 設計を行っていない場合は、契約書を作成することで問題が解消され、コストと複雑さが軽減されます。

柔軟性の損失は見られません。

  1. 契約から始まり、

  2. それから

    を。テストを書き、

    b. コードを書きます。

2 つの開発活動が本質的に絡み合っており、両方とも契約に基づいていることを確認してください。

于 2008-12-27T03:13:15.637 に答える
27

DbC と TDD には重複部分があると思いますが、作業が重複しているとは思いません。DbC を導入すると、おそらくテスト ケースの削減につながるでしょう。

説明させてください。

TDD では、テストは実際にはテストではありません。それらは動作仕様です。ただし、これらは設計ツールでもあります。最初にテストを作成することにより、テスト対象のオブジェクトの外部 API (実際にはまだ作成していません) をユーザーと同じ方法で使用します。そうすることで、実装しやすい方法ではなく、ユーザーにとって意味のある方法で API を設計できます。queue.full?の代わりのようなものqueue.num_entries == queue.size

この 2 番目の部分を契約に置き換えることはできません。

最初の部分は、少なくとも単体テストでは、コントラクトに部分的に置き換えることができます。TDD テストは、他の開発者 (単体テスト) とドメイン エキスパート (受け入れテスト) の両方にとって、動作の仕様として機能します。コントラクトは、他の開発者やドメインの専門家だけでなく、コンパイラやランタイム ライブラリに対しても動作を指定します。

ただし、コントラクトには固定された粒度があります。メソッドの事前条件と事後条件、オブジェクトの不変条件、モジュール コントラクトなどがあります。ループバリアントと不変条件かもしれません。ただし、単体テストは動作の単位をテストします。それらはメソッドよりも小さいか、複数のメソッドで構成されている場合があります。それは契約でできることではありません。そして、「全体像」については、統合テスト、機能テスト、受け入れテストが必要です。

そして、DbC がカバーしていない TDD のもう 1 つの重要な部分があります。それは中央の D です。TDD では、テストが開発プロセスを駆動します。失敗したテストがない限り、実装コードを 1 行も書かないでください。すべてのテストに合格しない限り、テスト コードを最小限に抑える必要があります。テストに合格するための最小限の実装コードのみを記述し、失敗するテストを生成するための最小限のテスト コードのみを記述します。

結論として、テストを使用して API の「フロー」、「感触」を設計します。コントラクトを使用して、API のコントラクトを設計します。テストを使用して、開発プロセスの「リズム」を提供します。

このようなもの:

  1. 機能の受け入れテストを書く
  2. その機能の一部を実装するユニットの単体テストを書く
  3. 手順 2 で設計したメソッド シグネチャを使用して、メソッド プロトタイプを記述します。
  4. 事後条件を追加する
  5. 前提条件を追加
  6. メソッド本体を実装する
  7. 受け入れテストに合格した場合は 1 に進み、それ以外の場合は 2 に進みます

Design by Contract の発明者である Bertrand Meyer が TDD と DbC を組み合わせることについて考えていることを知りたい場合は、彼のグループによるContract-Driven Design = Test-Driven Development - Writing Test Casesという素晴らしい論文があります。基本的な前提は、コントラクトは考えられるすべてのケースの抽象的な表現を提供するのに対し、テスト ケースは特定のケースのみをテストするということです。したがって、コントラクトから適切なテスト ハーネスを自動的に生成できます。

于 2008-12-27T13:35:13.710 に答える
6

私は追加します:

API はプログラマーの契約であり、UI 定義はクライアントとの契約であり、プロトコルはクライアントとサーバーのやり取りの契約です。最初にそれらを入手してください。そうすれば、雑草の中で迷子になることなく、並行開発トラックを利用できます。はい、定期的にレビューして要件が満たされていることを確認しますが、契約なしで新しいトラックを開始することはありません。そして「契約」は強力な言葉です。一度展開すると、決して変更してはなりません。最初からバージョン管理とイントロスペクションを含める必要があります。コントラクトの変更は拡張セットによってのみ実装され、バージョン番号はこれらで変更されます。その後、混合または古いインストールを処理するときにグレースフル デグラデーションなどを行うことができます。

私はこの教訓を難しい方法で学びました。大規模なプロジェクトは決して決して土地に迷い込むことはありませんでした。その後、銃、会社の存続、短いヒューズタイムラインの下で真剣にそれを正しい方法で適用しました. プロトコルを定義し、トランザクションの各側のプロトコル エミュレーションのセットを定義して作成しました (基本的には、定型化されたメッセージ ジェネレーターと受信メッセージ チェッカー、1 晩分の 2 つの頭脳によるコーディング)。アプリの。ショーの夜を再結合しましたが、うまくいきました。要件、設計、契約、テスト、コーディング、統合。その順番で。焼きあがるまで繰り返す。

私はTLAによるデザインには少し懐疑的です。パターンと同様に、流行語に準拠したレシピは良いガイドですが、私の経験では、万能のデザインやプロジェクト管理手順などはありません。By The Book (tm) に従って物事を正確に行っている場合、それが DOD 手続き要件を伴う DOD 契約でない限り、途中でどこかで問題に遭遇する可能性があります。はい、本を読んでください。ただし、必ずそれらを理解し、チームの人的側面も考慮してください。Book によってのみ強制されるルールは、一様に強制されるわけではありません。ツールによって強制された場合でも、ドロップアウトが発生する可能性があります (たとえば、svn コメントが空のままになったり、暗号のように簡潔になったりします)。ツールチェーンがそれらを強制するだけでなく、可能なショートカットよりも簡単に実行できる場合にのみ、手順が実行される傾向があります。私を信じてください、

于 2008-12-27T06:29:23.510 に答える
2

コントラクトのドメイン言語で記述された実行可能な受け入れテストを使用することもできます。それは実際の「契約」ではないかもしれませんが、単体テストと契約の中間です。

Ruby Cucumber http://github.com/aslakhellesoy/cucumber の使用をお勧めします

しかし、あなたは Perl ショップなので、p5-cucumber で私自身の小さな試みを使用できるかもしれません。 http://github.com/kesor/p5-cucumber

于 2009-03-13T11:42:49.883 に答える
1

Microsoft は、コード コントラクトとパラメーター化された単体テストに基づいて、単体テストの自動生成に関する作業を行いました。たとえば、コントラクトでは、アイテムがコレクションに追加されたときにカウントを 1 つ増やす必要があると記述されており、パラメーター化された単体テストでは、「n」個のアイテムをコレクションに追加する方法が記述されています。次に、Pex は、契約が破られていることを証明する単体テストの作成を試みます。概要については、このビデオを参照してください。

これが機能する場合、単体テストは、テストしようとしている各項目の 1 つの例について記述するだけで済み、PEX は、データ項目がテストを中断することを解決できるようになります。

于 2009-03-13T12:21:35.110 に答える
0

DbC は、最初に単体テストを特定するのに役立つため、赤、緑、リファクタリングのサイクルを活性化するのに非常に便利であることがわかりました。DbC では、TDD されるオブジェクトが処理しなければならない前提条件について考え始めます。各前提条件は、赤-緑-リファクタリング サイクルを開始するための単体テストの失敗を表している可能性があります。ある時点で、事後条件の失敗した単体テストでサイクルを開始するように切り替え、TDD フローを続行します。私はこのアプローチを TDD の初心者に試してみましたが、TDD の考え方に弾みをつけるのに非常に効果的です。

要約すると、DbC は主要な動作ユニット テストを特定するための効果的な方法と考えてください。DbC は、入力 (事前条件) と出力 (事後条件) の分析に役立ちます。これらは、テスト可能なソフトウェアを作成するために制御 (入力) と観察 (出力) する必要がある 2 つのことです (TDD の同様の目的)。

于 2014-10-29T23:40:54.163 に答える
0

しばらく前に、そのトピックについていくつかの反省がありました。

あなたは見てみたいと思うかもしれません

http://gleichmann.wordpress.com/2007/12/09/test-driven-development-and-design-by-contract-friend-or-foe/

于 2009-12-07T07:59:57.250 に答える
0

TDD を使用して新しいメソッドを実装する場合、入力が必要です。テストをチェックインするためのアサーションを知る必要があります。契約による設計は、これらのアサーションを提供します。これらは、メソッドの事後条件および不変条件です。

于 2011-09-14T11:27:38.237 に答える