[Code Contracts] Les post-conditions : ce n’est pas uniquement pour contrôler la valeur de retour d’une méthode !

Aujourd’hui j’ai été en mission chez un client qui à mis en place Code Contracts et son outil de vérification statique du code. Lorsque j’ai relus une partie de son code, je me suis aperçu que certains développeurs posait des Contract.Assume() afin d’obliger l’outil de vérification statique à considérer la condition spécifiée en paramètre comme vraie. Voici le code en question (bien évidemment j’ai très simplifié le code…) :

public static class Programme
{
    public static void Main(string[] args)
    {
        Personne personne;
        personne = new Personne();

        InsérerPersonne(personne);

        Contract.Assume(personne.Id != 0, "Le ID ne la personne n'a pas été récupéré depuis la base de données");

        Afficher(personne);
    }

    public static void Afficher(Personne personne)
    {
        Contract.Requires<ArgumentNullException>(personne != null);
        Contract.Requires<ArgumentException>(personne.Id != 0);

        Console.WriteLine(personne.Id);
    }

    public static void InsérerPersonne(Personne personne)
    {
        Contract.Requires<ArgumentNullException>(personne != null);

        personne.Id = 1664;   // On suppose que l'ID provient d'un INSERT sur une base SQL.
    }
}

public class Personne
{
    public int Id
    {
        get;
        set;
    }
}

Bien évidemment je suis aller voir le développeur qui a écrit ce Contract.Assume() et lui ai demandé pourquoi il en avait besoin. Il m’a répondu que c’est l’outil de vérification statique qui lui a indiqué que la pré-condition « personne.Id != 0 » dans la méthode Afficher() ne peut être prouvée…

Contrat non prouvé

Bien évidemment, même si on a affecté le « Id » de la personne (en provenance d’une base de données) dans la méthode InsérerPersonne() il n’y a rien qui nous prouve que l’identifiant est supérieur à 0. J’ai donc poser la question suivante au développeur : « Pourquoi vous ne spécifiez pas une post-conditions qui indique que l’Id de personne est supérieur à 0 ». J’ai été surpris aussitôt surpris par sa réponse : « Les post-conditions, ce n’est pas pour contrôler le retour des méthodes ? ». Et bien non ! Les post-conditions, ce sont des conditions qui doivent être vérifiées à la fin de la méthode. Ces conditions peuvent vérifier le retour de la méthode, mais aussi si une exception est déclenchée, si un paramètre est correcte, si l’âge du capitaine n’a pas changé….

Bref, toute condition qui doit être vérifié à la fin de la méthode, peut-être marquée à l’aide des post-conditions. Rappelez-vous aussi que les post-conditions sont des bons indicateurs aux intégrateurs de votre méthode (ceux qui vont utilisés votre méthode) afin de leur indiquer le nouvel état des objets qui sont modifiés par la méthode (paramètres, propriétés d’une classe, retour de la méthode,…).

Si on reprend l’exemple précédent voici le code qui faudrait mettre dans la méthode InsérerPersonne() :

public static void InsérerPersonne(Personne personne)
{
Contract.Requires<ArgumentNullException>(personne != null);
Contract.Ensures(personne.Id != 0);

personne.Id = 1664;   // On suppose que l'ID provient d'un INSERT sur une base SQL.
}

au niveau du Main() bien évidemment on supprimera le Contract.Assume() :

public static void Main(string[] args)
{
    Personne personne;
    personne = new Personne();

    InsérerPersonne(personne);

    Afficher(personne);
}

Et voilà le résultat au niveau de l’outil de vérification statique du code de Code Contracts :

Contrats vérifiés

Publié dans la catégorie Code Contracts.
Tags : , , . TrackBack URL.

Leave a comment