59 votes

Vraiment essayer d'aimer CodeContracts en C #

Je suis enfin de rattraper leur retard avec tout le nouveau qui a été ajouté à la .NET 3.5/4.0 Cadres. Depuis quelques jours, j'ai pu travailler avec CodeContracts et je suis vraiment tenté de les aimer. Je suis curieux de savoir ce que les autres pensent de la mise en œuvre de CodeContracts en C#? Plus précisément, comment sont les gens à organiser des choses comme le Contrat de classes pour les interfaces, contrat de méthodes pour le Contrat Invariants etc?

J'aime la validation des contrats de fournir, à première vue, ils ressemblent beaucoup. Avec quelques simples lignes je peux obtenir quelques belles construire la vérification avant même d'exécuter mon code. Malheureusement, je vais avoir du mal à passer par-dessus le sentiment que la façon dont les contrats de code sont de mettre en œuvre en C#, ils sont d'encombrer mon code plus que ce qu'ils documentent les contrats. Et pour profiter pleinement de contrats, je suis jonchent mon code avec des hypothèses et affirme etc (je sais certains vont dire, c'est une bonne chose); mais comme certains de mes exemples ci-dessous montrent, il s'avère une simple ligne de 4 ou 5 lignes, et n'a pas vraiment d'ajouter une valeur suffisante à mon avis, par rapport à d'autres approches (c'est à dire, affirme, exceptions...).

Actuellement, mes plus grandes frustrations sont:

Des Contrats D'Interface:

[ContractClass(typeof(IInterfaceContract))]
  public interface IInterface
  {
    Object Method(Object arg);
  }

  [ContractClassFor(typeof(IInterface))]
  internal abstract class IInterfaceContract
  {
    private IInterfaceContract() { }

    Object IInterface.Method(Object arg)
    {
      Contract.Requires(arg != null);
      Contract.Ensures(Contract.Result<Object>() != null);
      return default(Object);
    }
  }

Cela se sent comme un cludge pour moi, je souhaite qu'il y avait une manière plus propre aux exigences en matière de documents, soit par l'intermédiaire d'attributs ou de certaines formes de bâti de support de la langue. Le fait que je dois implémenter une classe abstraite qui implémente mon interface, juste pour que je puisse spécifier le contrat semble fastidieux, au mieux.

Augmentation Du Code:

typeof(Action<>).MakeGenericType(typeof(Object);

Nécessite plusieurs hypothèses, juste pour vérifier l'information qui est facilement disponible. J'apprécie le fait que tous l'analyseur sait, c'est qu'il fonctionne sur le Type et doit donc travailler sur ce peu de connaissances, mais elle continue de me frustre qu'une seule ligne de code m'oblige à ré-écrire comme

var genericAction = typeof(Action<>);

Contract.Assume(genericAction.IsGenericType);
Contract.Assume(genericAction.GetGenericArguments().Length == 1);

genericAction.MakeGenericType(typeof(Object));

Juste pour garder les choses documentées (oui, je sais que je peux utiliser ContractVerificationAttribute de désactiver cette fonction pour une méthode de classe, etc, ou SuppressMessageAttribbute à la cible de messages spécifiques, mais qui semble à l'encontre du but que votre code deviendrait rapidement jonché de suppressions, etc.

En outre, en prenant un cas comme

  public class MyClass
    : IInterface
  {
    private readonly Object _obj;

    public Object Property
    {
      get
      {
        Contract.Ensures(Contract.Result<Object>() != null);
        return _obj;
      }
    }

    public MyClass(Object obj)
    {
      Contract.Requires(obj != null);

      _obj = obj;
    }
  }

obj est nécessaire pour ne pas être nulle, et est fixé à un champ en lecture seule qui ne peut pas être changé, mais je suis encore obligé d'ajouter un "balisage" méthode de ma classe, de sorte que mon exigence de la propriété de ne pas retourner la valeur null peut être prouvé:

[ContractInvariantMethod]
private void ObjectInvariant()
{
  Contract.Invariant(_obj != null);
}

Il n'y est plus, mais j'ai pensé que j'ai probablement déclamée assez, et je voudrais vraiment l'apprécier du point de vue de gens beaucoup plus intelligents que moi pour m'aider à "comme" des Contrats de Code et de faire de ce sentiment de l'encombrement de code en aller. Aucune indication sur la façon de mieux structurer le code, la solution de contournement wonkiness questions etc serait grandement apprécié.

Merci!

26voto

Porges Points 17745

Cela se sent comme un cludge pour moi, je souhaite qu'il y avait une manière plus propre aux exigences en matière de documents, soit par l'intermédiaire d'attributs ou de certaines formes de bâti de support de la langue.

La CC de l'équipe ont déclaré que l'utilisation d'Attributs n'est tout simplement pas assez puissant, parce que vous ne pouvez pas inclure des choses comme des lambdas. Ils pourraient inclure des choses comme [NotNull] , mais ont choisi de ne pas le faire parce qu'ils sont en essayant de garder les CC aussi général que possible.

L'une des raisons que CC est une bibliothèque (plutôt que de faire partie d'une extension de C#), c'est qu'il est pris en charge sur tous les .NET languages.

Vous pouvez en savoir plus sur l'équipe du raisonnement ici.

En termes de l'utilisation de l', jusqu'à présent, j'ai juste réussi à garder mes contrats d'interface dans le même fichier que l'interface, ce qui signifie qu'il est documentée dans le même endroit. C'est quelque chose qui devrait être amélioré :)

Augmentation Du Code [...]

Votre deuxième plainte est probablement quelque chose qui peut être mis en œuvre -- je vous suggère de poster sur les contrats de code forum. (EDIT: il Semble que quelqu'un a déjà, mais pas de réponses encore.)

Cependant, il sera toujours le cas, que les sous-contrats spécifiques aurez besoin de plus d'hypothèses qui les entourent. Si vous exécutez dans un cas de ce genre .NET framework, vous pouvez demander à ce que les contrats soient ajoutés dans le Manque de Contrats sur les Bibliothèques de threads.

En outre, en prenant un cas comme [...]

Cela a été abordé. Si vous avez un auto-propriété, vous avez juste à ajouter une valeur non nulle de l'invariant et le pré-/post-conditions seront générées:

public class MyClass : IInterface
{
    private Object Property { get; set; }

    [ContractInvariantMethod]
    private void Invariants()
    {
        Contract.Invariant(Property != null);
    }
}

Vous finirez probablement avec d'autres invariants de vos classes, de toute façon, il n'est donc pas un gros problème.

12voto

Matt Dotson Points 3100

Oui, les contrats encombrent les choses, mais j'estime que cela en vaut la peine lorsque PEX lit les contrats de code et génère 25 tests unitaires et une couverture de code à 100% pour moi. Si vous n'avez pas encore utilisé PEX, vous ratez le principal avantage des contrats de code. Voici un guide de démarrage pour utiliser PEX avec des contrats .

9voto

Andy Points 756

Je voulais vraiment l'aime trop, et est allé assez loin avec une mise en œuvre dans un nouveau projet, jusqu'à ce que j'ai donné sous le poids de la petite tatillonne problèmes que j'ai eu avec elle.

J'aimerais pour Microsoft de ressusciter Spec#. Je sais que les contrats de code a été écrit comme une bibliothèque sont disponibles dans d'autres langues, mais simplement à la vitesse de l'analyse statique crie pour la prise en charge du compilateur.

Ce mec soulève certains points: http://earthli.com/news/view_article.php?id=2183

De toute façon, il n'y avait pas un problème qui a été un deal-breaker, mais une accumulation d'irritations:

  • L'analyse statique est très lent. Vous pouvez l'exécuter en arrière-plan, mais il est alors très facile de l'ignorer.
  • L'analyse statique est pas grand, pour exemple:
    • Il ne s'occupe que des flux de contrôle simple
    • Il ne présumez pas que readonly champs sont invariantes
    • Les Collections ne sont pas gérées par le vérificateur statique (uniquement à l'exécution)
  • Aucun délégué contrats
  • Ne fonctionne pas bien avec Resharper, à moins que vous suppriment activement resharper mises en garde d'une manière ou d'une autre
    • Resharper est optimiste. Il prend un paramètre de méthode n'est pas null, jusqu'à ce que vous lui donner un soupçon qu'il pourrait être - comme Contract.Assume(thing != null)
  • Peut générer beaucoup de mises en garde et suggestions, parfois issus de l'ambiguïté de la source.
    • Le moment aucun membre de l'équipe permet à leur attention slip, le nombre de mises en garde qui allait devenir écrasante pour tout le monde
  • La nécessité de préciser abstrait contrat de classes pour les interfaces de la douleur.
  • Exécution des contrats d'utilisation IL réécriture, qui, apparemment, ne joue pas bien avec les autres réécriture des solutions comme PostSharp (je pense .
    • Comme un résultat de l'IL réécriture, de modifier et continuer ne peut pas être utilisé
  • Les contrats de bâton très étroitement au principe de substitution de liskov: sous-types peuvent jamais se détendre pré-conditions. Je veux dire, bonne dans son principe, mais j'imagine que ce serait une douleur lorsque vous travaillez avec plus de-traitance de la 3e partie du code.

3voto

Jarek Kardas Points 6956

J'ai créé un plugin pour Visual Studio 2010 qui peut vous faire gagner du temps en créant des contrats de code pour les interfaces et les classes abstraites: http://visualstudiogallery.msdn.microsoft.com/en-us/d491911d-97f3-4cf6-87b0-6a2882120acf

2voto

KoMet Points 864

En fait, je trouve l'interface de mise en œuvre de grands. C'est ne pas encombrer votre interface ou votre code, et vous pouvez stocker soigneusement dans un dossier de votre solution, ou dans le même fichier de classe comme interface, selon ce que vous aimez le plus.

Pourquoi êtes-vous nécessaire d'ajouter l'objet invariant? Vous ne devez en ajouter autant que vous le sentez nécessaire.

Je comprends votre point sur l'augmentation du code, mais je suppose que c'est le compromis avec les Contrats de Code. Contrôles supplémentaires/moyens de sécurité de codes supplémentaires, au moins la façon dont il est actuellement mis en œuvre. Je vais essayer de garder le plus de contrats possibles sur les Interfaces, qui devrait au moins vous aider à soulager l'augmentation du code de la douleur.

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