Comment trouver où vit une fonction
Une base de code, c’est tout le code d’un même programme. Le premier jour d’un emploi, on vous en confie une que d’autres ont écrite, avec des milliers de lignes et sans plan.
Personne ne lit tout. On apprend à poser une question, à chercher la réponse et à suivre les appels à partir de là.
À la fin de cette leçon
Remarque
Je peux trouver où vit une fonction dans un code que je n’ai pas écrit et suivre un appel d’un fichier à l’autre.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Base de code | tous les fichiers de code qui forment un même programme |
| Point d’entrée | le fichier ou la fonction où le programme commence |
| Recherche | chercher un mot dans tous les fichiers, avec un outil comme grep |
| Appelant | une ligne de code qui utilise une fonction |
| Chaîne d’appels | les fonctions auxquelles un appel mène, l’une après l’autre |
| Test comme documentation | un test qui montre, en code, ce qu’une fonction promet |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Partir d’une question, pas d’un fichier
N’ouvrez pas le premier fichier pour lire de haut en bas. Posez une petite question : où calcule-t-on la remise du coupon ?
Regardez d’abord la forme des dossiers. Lancez le programme pour voir ce qu’il fait. Puis cherchez un mot visible à l’écran.
Créez d’abord le projet. Un dossier de cache caché ajouterait du bruit aux recherches : le premier Run le désactive.
Empêcher Python d’écrire des caches
export PYTHONDONTWRITEBYTECODE=1Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Créer les deux dossiers
mkdir -p ~/lirecode/boutique ~/lirecode/testsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Entrer dans le projet
cd ~/lirecodeAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire la liste des prix
printf 'PRIX = {"the": 250, "tasse": 899, "livre": 1200}\n\n\ndef prix_unitaire(code):\n return PRIX[code]\n' > boutique/prix.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire les coupons
printf 'COUPONS = {"PROMO10": 10, "MOITIE": 50}\n\n\ndef pourcentage_remise(code):\n return COUPONS.get(code, 0)\n' > boutique/remises.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le total de la commande
printf 'from boutique.prix import prix_unitaire\nfrom boutique.remises import pourcentage_remise\n\n\ndef total_commande(articles, coupon=None):\n total = 0\n for code, nombre in articles:\n total = total + prix_unitaire(code) * nombre\n pourcentage = pourcentage_remise(coupon)\n return total - total * pourcentage // 100\n' > boutique/commandes.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire la commande
printf 'import sys\nfrom boutique.commandes import total_commande\n\n\ndef main(arguments):\n articles = [("the", 2), ("tasse", 1)]\n coupon = arguments[0] if arguments else None\n print(total_commande(articles, coupon))\n\n\nmain(sys.argv[1:])\n' > boutique/cli.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire les tests
printf 'import unittest\nfrom boutique.commandes import total_commande\n\n\nclass CommandeTest(unittest.TestCase):\n def test_sans_coupon(self):\n self.assertEqual(total_commande([("the", 2)]), 500)\n\n def test_promo10(self):\n self.assertEqual(total_commande([("the", 2)], "PROMO10"), 450)\n' > tests/test_commandes.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Regarder la forme du projet
ls -RAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le lancer avec un coupon
python3 -m boutique.cli PROMO10Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Chercher un mot que vous voyez
Le programme a affiché 1260. Le coupon s’appelait PROMO10, et ce mot est forcément écrit quelque part. grep -rn cherche dans tous les fichiers sous les dossiers nommés, et affiche le fichier, le numéro de ligne et la ligne.
Un nom visible à l’écran est la meilleure porte d’entrée d’un code inconnu.
Chercher le nom du coupon
grep -rn "PROMO10" boutique testsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Suivre l’appel jusqu’à l’endroit suivant
La recherche a trouvé une table de coupons dans remises.py. Une table ne fait rien seule : posez la question suivante. Qui l’utilise ?
Cherchez la fonction qui lit la table. Une ligne la définit, une l’importe et une l’appelle. L’appel est l’endroit où la remise atteint la commande.
Trouver chaque usage de la fonction
grep -rn "pourcentage_remise" boutiqueAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Exemple travaillé : la chaîne d’appels d’une commande
| Étape | Fichier et fonction | Ce qui se passe |
|---|---|---|
| 1 | boutique/cli.py, main | Le point d’entrée lit le coupon sur la ligne de commande |
| 2 | boutique/commandes.py, total_commande | Additionne les prix, puis demande la remise |
| 3 | boutique/prix.py, prix_unitaire | Donne le prix d’un article |
| 4 | boutique/remises.py, pourcentage_remise | Cherche le coupon, ou donne 0 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Lire les tests : ce que le code promet
Un bon test dit ce qu’une fonction doit faire, avec de vraies entrées et les réponses. C’est la seule documentation qui ne peut pas vieillir, car elle échoue quand elle vieillit.
Listez les noms des tests, puis lancez-les. S’ils passent, ce que vous avez lu est vrai aujourd’hui.
Lister les tests
grep -n "def test" tests/test_commandes.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer les tests
python3 -m unittest discover -s tests 2>&1 | grep -E "^(OK|FAILED)"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une erreur fréquente
Attention
Beaucoup lisent chaque fichier depuis le début, en espérant tout comprendre d’abord. Cela prend des jours et la plupart ne concerne pas votre question. Posez une question, cherchez, suivez l’appel, et arrêtez-vous quand vous pouvez répondre.
Pour aller plus loin : un projet plus grand
Choisissez un projet que vous utilisez, avec ses sources sur votre machine. Prenez une chose qu’il fait, comme la lecture d’un fichier de réglages.
Écrivez la question, le mot cherché et la chaîne de fichiers suivie. Combien d’étapes cela a-t-il pris ?