== Boite à outils

=== Python

Le langage https://www.python.org/[Python] est un https://docs.python.org/3/faq/general.html#what-is-python[langage de programmation] interprété, interactif, orienté objet (souvent), fonctionnel (parfois), open source, multi-plateformes, flexible, facile à apprendre et difficile à maîtriser.

.https://xkcd.com/353/
image::images/xkcd-353-python.png[]

A première vue, certains concepts restent difficiles à aborder: l'indentation définit l'étendue d'un bloc (classe, fonction, méthode, boucle, condition, ...), il n'y a pas de typage fort des variables et le compilateur n'est pas là pour assurer le filet de sécurité avant la mise en production (puisqu'il n'y a pas de compilateur 😛).
Et malgré ces quelques points, Python reste un langage généraliste accessible et "bon partout", et de pouvoir se reposer sur un écosystème stable et fonctionnel.

Il fonctionne avec un système d'améliorations basées sur des propositions: les PEP, ou "**Python Enhancement Proposal**".
Chacune d'entre elles doit être approuvée par le http://fr.wikipedia.org/wiki/Benevolent_Dictator_for_Life[Benevolent Dictator For Life].

Si vous avez besoin d'un aide-mémoire ou d'une liste exhaustive des types et structures de données du langage, référez-vous au lien suivant: https://gto76.github.io/python-cheatsheet/[Python Cheat Sheet].

NOTE: Le langage Python utilise un typage dynamique appelé https://fr.wikipedia.org/wiki/Duck_typing[*duck typing*]: "_When I see a bird that quacks like a duck, walks like a duck, has feathers and webbed feet and associates with ducks — I’m certainly going to assume that he is a duck_" (Source: http://en.wikipedia.org/wiki/Duck_test[Wikipedia (as usual)]).

==== PEP8 - Style Guide for Python Code

La première PEP qui va nous intéresser est la https://www.python.org/dev/peps/pep-0008/[PEP 8 -- Style Guide for Python Code]. Elle spécifie comment du code Python doit être organisé ou formaté, quelles sont les conventions pour l’indentation, le nommage des variables et des classes, ...
En bref, elle décrit comment écrire du code proprement, afin que d’autres développeurs puissent le reprendre facilement, ou simplement que votre base de code ne dérive lentement vers un seuil de non-maintenabilité.

Dans cet objectif, un outil existe et listera l'ensemble des conventions qui ne sont pas correctement suivies dans votre projet: pep8. Pour l'installer, passez par pip. Lancez ensuite la commande pep8 suivie du chemin à analyser (`.`, le nom d'un répertoire, le nom d'un fichier `.py`, ...). Si vous souhaitez uniquement avoir le nombre d'erreur de chaque type, saisissez les options `--statistics -qq`.


[source,bash]
----
$ pep8 . --statistics -qq

7       E101 indentation contains mixed spaces and tabs
6       E122 continuation line missing indentation or outdented
8       E127 continuation line over-indented for visual indent
23      E128 continuation line under-indented for visual indent
3       E131 continuation line unaligned for hanging indent
12      E201 whitespace after '{'
13      E202 whitespace before '}'
86      E203 whitespace before ':'
----

Si vous ne voulez pas être dérangé sur votre manière de coder, et que vous voulez juste avoir un retour sur une analyse de votre code, essayez `pyflakes`: cette librairie analysera vos sources à la recherche de sources d'erreurs possibles (imports inutilisés, méthodes inconnues, etc.).

Il existe une solution qui couvre ces deux domaines: https://github.com/PyCQA/flake8[flake8].
Sur base de la même interface que `pep8`, vous rencontreez en plus tous les avantages liés à `pyflakes`


==== PEP257 - Docstring Conventions

Python étant un langage interprété fortement typé, il est plus que conseillé, au même titre que les tests unitaires, de documenter son code.
Cela impose une certaine rigueur, mais améliore énormément la qualité (et la reprise) du code par une tierce personne. Cela implique aussi de **tout** documenter: les modules, les paquets, les classes, les fonctions, méthodes, ... Tout doit avoir un *docstring* associé :-).

WARNING: Documentation: be obsessed!

Il existe plusieurs types de conventions de documentation:

. PEP 257
. Numpy
. Google Style (parfois connue sous l'intitulé `Napoleon`)
. ...

Les https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings[conventions proposées par Google] nous semblent  plus faciles à lire que du RestructuredText, mais sont parfois moins bien intégrées que les docstrings officiellement supportées (typiquement, par exemple par https://clize.readthedocs.io/en/stable/[clize] qui ne reconnait que du RestructuredText).
L'exemple donné dans les styleguide est celui-ci:

[source,python]
----
def fetch_smalltable_rows(table_handle: smalltable.Table,
                          keys: Sequence[Union[bytes, str]],
                          require_all_keys: bool = False,
) -> Mapping[bytes, Tuple[str]]:
    """Fetches rows from a Smalltable.

    Retrieves rows pertaining to the given keys from the Table instance
    represented by table_handle.  String keys will be UTF-8 encoded.

    Args:
        table_handle: An open smalltable.Table instance.
        keys: A sequence of strings representing the key of each table
          row to fetch.  String keys will be UTF-8 encoded.
        require_all_keys: Optional; If require_all_keys is True only
          rows with values set for all keys will be returned.

    Returns:
        A dict mapping keys to the corresponding table row data
        fetched. Each row is represented as a tuple of strings. For
        example:

        {b'Serak': ('Rigel VII', 'Preparer'),
         b'Zim': ('Irk', 'Invader'),
         b'Lrrr': ('Omicron Persei 8', 'Emperor')}

        Returned keys are always bytes.  If a key from the keys argument is
        missing from the dictionary, then that row was not found in the
        table (and require_all_keys must have been False).

    Raises:
        IOError: An error occurred accessing the smalltable.
    """
----

C'est-à-dire:

. Une courte ligne d'introduction, descriptive, indiquant ce que la fonction ou la méthode réalise. Attention, la documentation ne doit pas indiquer _comment_ la fonction/méthode est implémentée, mais ce qu'elle fait concrètement (et succintement).
. Une ligne vide
. Une description plus complète et plus verbeuse
. Une ligne vide
. La description des arguments et paramètres, des valeurs de retour (+ exemples) et les exceptions qui peuvent être levées.

Un exemple (encore) plus complet peut être trouvé https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html#example-google[dans le dépôt sphinxcontrib-napoleon].

Pour ceux que cela pourrait intéresser, il existe https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring[une extension pour Codium], comme nous le verrons juste après, qui permet de générer automatiquement le squelette de documentation d'un bloc de code:

.autodocstring
image::images/environment/python-docstring-vscode.png[]

=== Environnement de développement

Concrètement, nous pourrions tout à fait nous limiter à Notepad ou Notepad++.
Mais à moins d'aimer se fouetter avec un câble USB, nous apprécions la complétion du code, la coloration syntaxique, l'intégration des tests unitaires et d'un debugger, ainsi que deux-trois sucreries qui feront plaisir à n'importe quel développeur.

Si vous manquez d'idées ou si vous ne savez pas par où commencer:

* https://vscodium.com/[VSCodium], avec les plugins https://marketplace.visualstudio.com/items?itemName=ms-python.python[Python]et https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens[GitLens]
* https://www.jetbrains.com/pycharm/[PyCharm]
* https://www.vim.org/[Vim] avec les plugins https://github.com/davidhalter/jedi-vim[Jedi-Vim] et https://github.com/preservim/nerdtree[nerdtree]

Si vous hésitez, et même si Codium n'est pas le plus léger (la faute à https://www.electronjs.org/[Electron]...), il fera correctement son travail (à savoir: faciliter le vôtre), en intégrant suffisament de fonctionnalités qui gâteront les papilles émoustillées du développeur impatient.

.Codium en action
image::images/environment/codium.png[]

=== Un terminal

_A priori_, les IDE footnote:[Integrated Development Environment] proposés ci-dessus fournissent par défaut ou _via_ des greffons un terminal intégré.
Ceci dit, disposer d'un terminal séparé facilite parfois certaines tâches.

A nouveau, si vous manquez d'idées:

. Si vous êtes sous Windows, téléchargez une copie de https://cmder.net/[Cmder]. Il n'est pas le plus rapide, mais propose une intégration des outils Unix communs (`ls`, `pwd`, `grep`, `ssh`, `git`, ...) sans trop se fouler.
. Pour tout autre système, vous devriez disposer en natif de ce qu'il faut.

.Mise en abîme
image::images/environment/terminal.png[]

=== Un gestionnaire de base de données

Django gère plusieurs moteurs de base de données.
Certains sont gérés nativement par Django (PostgreSQL, MariaDB, SQLite); _a priori_, ces trois-là sont disponibles pour tous les systèmes d'exploitation. D'autres moteurs nécessitent des librairies tierces (Oracle, Microsoft SQL Server).

Il n'est pas obligatoire de disposer d'une application de gestion pour ces moteurs: pour les cas d'utilisation simples, le shell Django pourra largement suffire (nous y reviendrons).
Mais pour faciliter la gestion des bases de données elles-même, et si vous n'êtes pas à l'aise avec la ligne de commande, choisissez l'une des applications d'administration ci-dessous en fonction du moteur de base de données que vous souhaitez utiliser.

* Pour *PostgreSQL*, il existe https://www.pgadmin.org/[pgAdmin]
* Pour *MariaDB* ou *MySQL*, partez sur https://www.phpmyadmin.net/[PHPMyAdmin]
* Pour *SQLite*, il existe https://sqlitebrowser.org/[SQLiteBrowser]
PHPMyAdmin ou PgAdmin.


=== Un gestionnaire de mots de passe

Nous en auront besoin pour gé(né)rer des phrases secrètes pour nos applications.
Si vous n'en utilisez pas déjà un, partez sur https://keepassxc.org/[KeepassXC]: il est multi-plateformes, suivi et s'intègre correctement aux différents environnements, tout en restant accessible.

image::images/environment/keepass.png[]


=== Un système de gestion de versions

Il existe plusieurs systèmes de gestion de versions.
Le plus connu à l'heure actuelle est https://git-scm.com/[Git], notamment pour sa (très) grande flexibilité et sa rapidité d'exécution.
Il est une aide précieuse pour développer rapidement des preuves de concept, switcher vers une nouvelle fonctionnalité, un bogue à réparer ou une nouvelle release à proposer au téléchargement.
Ses deux plus gros défauts concerneraient peut-être sa courbe d'apprentissage pour les nouveaux venus et la complexité des actions qu'il permet de réaliser.

.https://xkcd.com/1597/
image::images/xkcd-1597-git.png[]

Même pour un développeur solitaire, un système de gestion de versions (quel qu'il soit) reste indispensable.

Chaque "*branche*" correspond à une tâche à réaliser: un bogue à corriger (_Hotfix A_), une nouvelle fonctionnalité à ajouter ou un "_truc à essayer_" footnote:[Oui, comme dans "Attends, j'essaie vite un truc, si ça marche, c'est beau."] (_Feature A_ et _Feature B_).
Chaque "*commit*" correspond à une sauvegarde atomique d'un état ou d'un ensemble de modifications cohérentes entre elles.footnote:[Il convient donc de s'abstenir de modifier le CSS d'une application et la couche d'accès à la base de données, sous peine de se faire huer par ses relecteurs au prochain stand-up.]
De cette manière, il est beaucoup plus facile pour le développeur de se concenter sur un sujet en particulier, dans la mesure où celui-ci ne doit pas obligatoirement être clôturé pour appliquer un changement de contexte.

.Git en action
image::images/diagrams/git-workflow.png[]

Cas pratique: vous développez cette nouvelle fonctionnalité qui va révolutionner le monde de demain et d'après-demain, quand, tout à coup (!), vous vous rendez compte que vous avez perdu votre conformité aux normes PCI parce les données des titulaires de cartes ne sont pas isolées correctement.
Il suffit alors de

. sauver le travail en cours (`git add . && git commit -m [WIP]`)
. revenir sur la branche principale (`git checkout main`)
. créer un "hotfix" (`git checkout -b hotfix/pci-compliance`)
. solutionner le problème (sans doute un `;` en trop ?)
. sauver le correctif sur cette branche (`git add . && git commit -m "Did it!"`)
. récupérer ce correctif sur la branche principal (`git checkout main && git merge hotfix/pci-compliance`)
. et revenir tranquillou sur votre branche de développement pour fignoler ce générateur de noms de dinosaures rigolos que l'univers vous réclame à cor et à a cri (`git checkout features/dinolol`)

Finalement, sachez qu'il existe plusieurs manières de gérer ces flux d'informations.
Les plus connus sont https://www.gitflow.com/[Gitflow] et https://www.reddit.com/r/programming/comments/7mfxo6/a_branching_strategy_simpler_than_gitflow/[Threeflow].