37 votes

La "conception par contrat" en C#

J'ai voulu essayer un peu de conception par contrat dans ma dernière application C# et je voulais avoir une syntaxe semblable à :

public string Foo()
{
    set {
        Assert.IsNotNull(value);
        Assert.IsTrue(value.Contains("bar"));
        _foo = value;
    }
}

Je sais que je peux obtenir des méthodes statiques de ce type à partir d'un cadre de test unitaire, mais je voulais savoir si quelque chose de ce genre était déjà intégré au langage ou s'il existait déjà une sorte de cadre flottant. Je peux écrire mes propres fonctions Assert, mais je ne veux pas réinventer la roue.

82voto

Luke Quinane Points 8257

Contrats de code C# 4.0

Microsoft a publié une bibliothèque pour la conception par contrat dans la version 4.0 du .net framework. L'une des caractéristiques les plus intéressantes de cette bibliothèque est qu'elle est également fournie avec un outil d'analyse statique (similaire à FxCop, je suppose) qui exploite les détails des contrats que vous placez sur le code.

Voici quelques ressources Microsoft :

Voici d'autres ressources :

22voto

Jim Burger Points 3166

Spec# est un populaire projet de recherche microsoft qui permet de réaliser certaines constructions DBC, comme la vérification des conditions post et pre. Par exemple, une recherche binaire peut être implémentée avec des pré et post conditions ainsi que des invariants de boucle. Cet exemple et bien d'autres encore :

 public static int BinarySearch(int[]! a, int key)
    requires forall{int i in (0: a.Length), int j in (i: a.Length); a[i] <= a[j]};
    ensures 0 <= result ==> a[result] == key;
    ensures result < 0 ==> forall{int i in (0: a.Length); a[i] != key};
 {
   int low = 0;
   int high = a.Length - 1;

   while (low <= high)
     invariant high+1 <= a.Length;
     invariant forall{int i in (0: low); a[i] != key};
     invariant forall{int i in (high+1: a.Length); a[i] != key};
   {
     int mid = (low + high) / 2;
     int midVal = a[mid];

     if (midVal < key) {
       low = mid + 1;
     } else if (key < midVal) {
       high = mid - 1;
     } else {
       return mid; // key found
     }
   }
   return -(low + 1);  // key not found.
 }

Notez qu'en utilisant le langage Spec#, on obtient vérification au moment de la compilation pour les constructions DBC, ce qui, à mon avis, est la meilleure façon de tirer parti de DBC. Souvent, s'appuyer sur les assertions d'exécution devient un casse-tête en production et les gens choisissent en général de exceptions d'utilisation à la place.

Hay autres langues qui considèrent les concepts DBC comme des constructions de première classe, à savoir Eiffel qui est également disponible pour la plate-forme .NET.

11voto

FlySwat Points 61945

Outre l'utilisation d'une bibliothèque externe, vous disposez d'une simple assert dans System.Diagnostics :

using System.Diagnostics

Debug.Assert(value != null);
Debug.Assert(value == true);

Pas très utile, je sais.

7voto

ligaoren Points 401

Il y a une réponse dans .net Fx 4.0 :

System.Diagnostics.Contracts

http://msdn.microsoft.com/en-us/library/dd264808.aspx

Contract.Requires(newNumber > 0, "Contrat échoué : négatif") ; Contract.Ensures(list.Count == Contract.OldValue(list.Count) + 1) ;

3voto

mmiika Points 3027

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X