Article complet

Cet article et deux autres ont été utilisés pour rédiger un article beaucoup plus complet. La lecture de l'article complet rend donc obsolète ce billet et les suivants :

L'article : Les procédures internes et les closures : une nouvelle manière de coder en Windev.

Avant-propos

Cet article concerne la programmation avec l'AGL Windev et présente une notion avancée dans l'utilisation du WLangage. Bien que le sujet soit extrêmement intéressant, il est utile d'avoir quelques notions en programmation pour le comprendre.

De plus, cet article traite des procédures internes qui sont apparues à partir de Windev 20. Les versions 19 et antérieures ne sont donc malheureusement pas concernées.

Les procédures internes

De temps en temps, le WLangage profite d'améliorations conséquentes qui lui redonne un petit goût de fraicheur. Les procédures internes fait partie de ces évolutions qui changent la donne. Je consacrerai (si je compte bien) trois articles aux procédures internes. Celui-ci qui les présente et deux autres qui permettront d'aller beaucoup plus loin.

Avant d'expliquer plus en détail, rappelons que dans Windev, on a plusieurs types de procédures :

  • Les procédures globales. Elles sont stockées dans une collection de procédures (fichier *.wdg) et elles peuvent être appelées de n'importe où dans le projet.
  • Les procédures locales. Elles sont stockées dans les fenêtres (fichier *.wdw) et elles peuvent être appelées de n'importe où dans le code de la fenêtre. Elles ne peuvent pas être utilisées ailleurs. On peut toutefois contourner cette règle de plusieurs manières différentes. Mais mon éthique du code propre m'interdit de le faire (sauf si je n'ai pas le choix parce que je suis tombé sur du code sale).
  • Les méthodes. Ce sont des procédures associées à une classe (fichier *.wdc). Elles peuvent être locales ou globales, publique, protégée ou privée. Mais là, on rentre dans le domaine de la POO (Programmation Orientée Objet) et ce n'est pas le sujet de l'article.
  • Les procédures compilées dynamiquement. On utilise la fonction compile.
  • Les procédures appelées à la suite d'un événement sur un champ de l'application.

Et maintenant, nous avons les procédures internes qui peuvent être définie et utilisée dans les autres types de procédures citées précédemment. Mais elle peut aussi être définie dans une autre procédure interne.

Comment ça marche ?

Un petit exemple étant plus efficace qu'une longue présentation, voici un exemple de procédure interne :

PROCEDURE ProLoc()
    PROCEDURE INTERNE ProInt()
        RENVOYER "Hello world"
    FIN

    Trace(ProInt())

On définit ici une procédure locale qui s'appelle ProLoc et dans celle-ci, on définit la procédure interne ProInt.

Dans quel cas s'en sert-on ?

On s'en sert dans plusieurs cas.

Tout d'abord, on peut s'en servir pour avoir un joli code bien écrit, autodocumenté (si vous ne connaissez pas ce terme, il faudra que je fasse un article dessus) et qui respecte la convention DRY (Don't Repeat Yourself, un autre article à prévoir).

Le code suivant :

PROCEDURE ProcédureLocale()
    POUR i = 1 _A_ 10
        Trace(i)
        Trace(i * i)
        Trace(Racine(i + 1))
    FIN

    POUR i = 30 _A_ 40
        Trace(i)
        Trace(i * i)
        Trace(Racine(i + 1))
    FIN

    POUR i = 80 _A_ 100
        Trace(i)
        Trace(i * i)
        Trace(Racine(i + 1))
    FIN

deviendrait

PROCEDURE ProcédureLocale()
    PROCEDURE INTERNE TracerEntierSousToutesCesFormes(pEntier est entier)
        Trace(pEntier)
        Trace(pEntier * pEntier)
        Trace(Racine(pEntier + 1))
    FIN

    POUR i = 1 _A_ 10
        TracerEntierSousToutesCesFormes(i)
    FIN

    POUR i = 30 _A_ 40
        TracerEntierSousToutesCesFormes(i)
    FIN

    POUR i = 80 _A_ 100
        TracerEntierSousToutesCesFormes(i)
    FIN

Le code devient ainsi plus clair, j'évite les répétions de code.

On peut aussi s'en servir pour des usages plus avancés que je décrirai dans les articles suivants : Les closures et ce que j'appelerai les pseudo-classes.

Premier piège et comment l'éviter

Plusieurs pièges vous attendent lors de l'utilisation des procédures internes. Voici le premier.

Une procédure interne ne peut pas appeler une autre procédure interne définie au même niveau qu'elle (mais elle peut s'auto-appeler)

PROCEDURE ProcédureLocale()
    PROCEDURE INTERNE PasLeDroit()
        Trace("Hello world")
    FIN

    PROCEDURE INTERNE Test()
        PasLeDroit()  // Cela ne fonctionne pas
    FIN

    Test()

Mais on peut s'en sortir en utilisant une variable de type Procédure. En effet, une procédure interne est une procédure avant tout.

Notez que je préfixe le nom des procédures internes par un i dans mon exemple pour les distinguer des variables de type procédure.

PROCEDURE ProcédureLocale()
    PasLeDroit est une procédure

    PROCEDURE INTERNE iPasLeDroit()
        Trace("Hello world")
    FIN
    PasLeDroit = iPasLeDroit

    PROCEDURE INTERNE iTest()
        PasLeDroit()  // Cela fonctionne
    FIN

    iTest()

Conclusion

Voilà pour la première approche sur les procédures internes. Vous allez voir que ce n'est que la partie visible de l'iceberg et que de belles fonctionnalités bien cachées et non-documentées vous attendent.

Merci pour votre lecture.

Cet article vous a intéressé ? Vous voulez en savoir plus ? Suivez le lien !

Jonathan Laurent

Read more posts about this author.

Comments