programmation modulaire
This commit is contained in:
parent
eb3daeae4e
commit
15fd0fa136
|
@ -0,0 +1,14 @@
|
||||||
|
Structures de données simples
|
||||||
|
=============================
|
||||||
|
|
||||||
|
- tableaux
|
||||||
|
- listes
|
||||||
|
- piles
|
||||||
|
- files
|
||||||
|
|
||||||
|
Structures de données complexes
|
||||||
|
================================
|
||||||
|
|
||||||
|
- graphes
|
||||||
|
- arbres
|
||||||
|
- hachages
|
|
@ -0,0 +1,295 @@
|
||||||
|
Les fonctions et les procédures
|
||||||
|
================================
|
||||||
|
|
||||||
|
Préliminaire : rappel de théorie de l'information
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Théorie de l'information (Claude Shannon, 1949), (ou théorie de la communication)
|
||||||
|
|
||||||
|
Canal de transmission::
|
||||||
|
|
||||||
|
entrée -> récepteur -> émetteur -> sortie
|
||||||
|
|
||||||
|
Description d'une procédure
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
En programmation impérative, un programme est une suite d’instructions qui font
|
||||||
|
évoluer l’état mémoire, le résultat est dans l’état final de la mémoire.
|
||||||
|
|
||||||
|
- une procédure peut prendre des paramètres
|
||||||
|
- elle modifie l'état courant du système
|
||||||
|
|
||||||
|
- Déclaration des paramètes
|
||||||
|
- Déclaration du corps
|
||||||
|
- Appel de la procédure
|
||||||
|
|
||||||
|
.. raw:: latex
|
||||||
|
|
||||||
|
\begin{algorithm}
|
||||||
|
\caption{Procédure de permutation de deux entiers}\label{permutation}
|
||||||
|
\begin{algorithmic}[1]
|
||||||
|
\Procedure{permuter}{$a,b$}{}
|
||||||
|
\BState \emph{parametres}:
|
||||||
|
\State $a: \textit{int}$
|
||||||
|
\State $b: \textit{int}$
|
||||||
|
\BState \emph{locales}:
|
||||||
|
\State $z: \textit{int}$ \Comment{Une variable intermédiaire est nécessaire}
|
||||||
|
\BState \emph{corps}:
|
||||||
|
\State $z \gets a$
|
||||||
|
\State $a \gets b$
|
||||||
|
\State $b \gets z$
|
||||||
|
\EndProcedure
|
||||||
|
\State \Call{permuter}{10, 12} \Comment{appel de la procédure}
|
||||||
|
\end{algorithmic}
|
||||||
|
\end{algorithm}
|
||||||
|
|
||||||
|
effet de bord
|
||||||
|
|
||||||
|
toute modification de la mémoire ou modification d'un support externe
|
||||||
|
|
||||||
|
instruction
|
||||||
|
|
||||||
|
commande ou phrase en mesure de modifier l'état du programme ou de la machine hôte
|
||||||
|
(allocation mémoire, support externe, disque, écran...)
|
||||||
|
|
||||||
|
Une procédure ne renvoie pas de valeur, mais provoque un 'effet de bord' (écriture dans une globale, dans un flux sortant etc.).
|
||||||
|
|
||||||
|
Une procédure permet de créer une instruction nouvelle qui deviendra une primitive pour le programmeur.
|
||||||
|
Cela permet de structurer le texte source du programme et améliorer sa
|
||||||
|
lisibilité. Cela permet aussi d'appeler plusieurs fois, et à plusieurs endroit
|
||||||
|
dans le code, cette primitive.
|
||||||
|
|
||||||
|
Appel d'une procédure
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
(ex: pseudo-pascal)
|
||||||
|
|
||||||
|
**déclaration de procédure**
|
||||||
|
|
||||||
|
.. raw:: latex
|
||||||
|
|
||||||
|
\begin{algorithm}
|
||||||
|
\caption{Procédure de permutation de deux entiers}\label{permutation}
|
||||||
|
\begin{algorithmic}[1]
|
||||||
|
\Procedure{permuter}{$a,b$}{}
|
||||||
|
\BState \emph{parametres}:
|
||||||
|
\State $a: \textit{int}$ \Comment{paramètres formels de la procédure}
|
||||||
|
\State $b: \textit{int}$
|
||||||
|
\BState \emph{locales}:
|
||||||
|
\State $z: \textit{int}$ \Comment{les variables locales de la procédure}
|
||||||
|
\BState \emph{corps}:
|
||||||
|
\State ... \Comment{Le corps de la procedure}
|
||||||
|
\EndProcedure
|
||||||
|
\State \Call{permuter}{10, 12} \Comment{l'appel de la procédure}
|
||||||
|
\end{algorithmic}
|
||||||
|
\end{algorithm}
|
||||||
|
|
||||||
|
|
||||||
|
- les variables x1,...,xn sont appelées *paramètres formels* de p
|
||||||
|
- les variables v1,...,vm sont appelées *les variables locales* de p
|
||||||
|
|
||||||
|
les valeurs effectivement passées en paramètres, ici `10, 12`
|
||||||
|
sont appelées **paramètres effectifs** de p
|
||||||
|
|
||||||
|
signature
|
||||||
|
|
||||||
|
C'est l'ensemble paramètre formel + resultat de l'appel
|
||||||
|
|
||||||
|
fermeture
|
||||||
|
|
||||||
|
L'ensemble procédure + variables locales + signature + parametres effectifs
|
||||||
|
est appelé une **fermeture**. C'est la procédure + son contexte qui permet
|
||||||
|
de l'instancier dans un programme.
|
||||||
|
|
||||||
|
Environnement
|
||||||
|
|
||||||
|
Contexte d’évaluation d'une expression ou d'une fonction
|
||||||
|
|
||||||
|
Portée
|
||||||
|
|
||||||
|
La portée d'une variable est sa condition d'utilisation dans un contexte donné
|
||||||
|
(utilisation locale uniquement, ou bien globale, ou bien locale et globale)
|
||||||
|
|
||||||
|
.. ifconfig:: exercice
|
||||||
|
|
||||||
|
**Exercice** : Que donne ce code ?
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
# let x = 42 in
|
||||||
|
let y = x - 1 in x - y ;;
|
||||||
|
|
||||||
|
.. ifconfig:: correction
|
||||||
|
|
||||||
|
**Correction** :
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
- : int = 1
|
||||||
|
|
||||||
|
Exemple de variable globale modifiée localement (** attention, mauvaise pratique ** !) :
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> a = 5
|
||||||
|
>>> def print_a():
|
||||||
|
... print("La variable a = {0}.".format(a))
|
||||||
|
...
|
||||||
|
>>> print_a()
|
||||||
|
La variable a = 5.
|
||||||
|
>>> a = 8
|
||||||
|
>>> print_a()
|
||||||
|
La variable a = 8.
|
||||||
|
>>>
|
||||||
|
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
|
||||||
|
L’ordre d’évaluation dans un let ... in ... est bien déterminé,
|
||||||
|
sans grande importance dans un cadre purement fonctionnel, mais important
|
||||||
|
en cas d’effets de bord
|
||||||
|
|
||||||
|
niveau
|
||||||
|
|
||||||
|
Le niveau d’une déclaration (de variable ou de procédure) est le nombre
|
||||||
|
de procédures sous lesquelles elle est déclarée. Le programme principal
|
||||||
|
a le niveau 0.
|
||||||
|
|
||||||
|
Description d'une fonction
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Une fonction renvoie une valeur et ne modifie pas l'état courant du programme
|
||||||
|
en cours d'exécution ni ne réalise d'effets de bord. Elle renvoie
|
||||||
|
**toujours** quelque chose (même la valeur ``None`` qui n'est pas rien)
|
||||||
|
|
||||||
|
- une procédure peut prendre des paramètres
|
||||||
|
- elle modifie l'état courant du système
|
||||||
|
|
||||||
|
- Déclaration des paramètes
|
||||||
|
- Déclaration du corps
|
||||||
|
- Appel de la fonction
|
||||||
|
|
||||||
|
En programmation fonctionnelle, programme est un ensemble de définitions de fonctions,
|
||||||
|
un résultat est l'application d’une fonction à une structure de données effective.
|
||||||
|
|
||||||
|
- composant de base : la fonction
|
||||||
|
- opération de base : l’application
|
||||||
|
|
||||||
|
.. raw:: latex
|
||||||
|
|
||||||
|
\begin{algorithm}
|
||||||
|
\caption{Exemple de fonction}\label{fonction}
|
||||||
|
\begin{algorithmic}[1]
|
||||||
|
\Function{permuter}{$a,b$}{} \Comment{définition de la fonction}
|
||||||
|
\BState \emph{parametres}: \Comment{déclaration (noms, types) des paramètres formels}
|
||||||
|
\State $a: \textit{int}$
|
||||||
|
\State $b: \textit{int}$
|
||||||
|
\BState \emph{locales}: \Comment{déclaration (noms, types) des valeurs locales}
|
||||||
|
\State $z: \textit{int}$
|
||||||
|
\BState \emph{corps}:
|
||||||
|
\State $z \gets a$
|
||||||
|
\State $a \gets b$
|
||||||
|
\State $b \gets z$
|
||||||
|
\BState \emph{return}: \Comment{La valeur, le résulat renvoyé par la fonction}
|
||||||
|
\EndFunction
|
||||||
|
\State \Call{permuter}{10, 12} \Comment{appel de la fonction}
|
||||||
|
\BState \emph{result}:
|
||||||
|
\State (12, 10) \Comment{Le résultat effectif de la fonction après appel}
|
||||||
|
\end{algorithmic}
|
||||||
|
\end{algorithm}
|
||||||
|
|
||||||
|
Définition mathématique
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
fonction
|
||||||
|
|
||||||
|
Une fonction f d’un ensemble E vers un ensemble F est une
|
||||||
|
correspondance qui associe à chaque élément de E au plus
|
||||||
|
un élément de F.
|
||||||
|
|
||||||
|
- E est appelé le domaine de définition
|
||||||
|
- F est appelé codomaine
|
||||||
|
- la **signature** de la fonction : `E → F (int -> int = <fun>)`
|
||||||
|
|
||||||
|
curryfication
|
||||||
|
|
||||||
|
évaluation de l'application d'une fonction
|
||||||
|
|
||||||
|
- évaluter `(f x y)`
|
||||||
|
- peut donner une **valeur fonctionnelle**
|
||||||
|
- évaluation de la valeur fonctionnelle sur une valeur des types de base
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
let g = function n -> (function p -> p + 1) n;;
|
||||||
|
|
||||||
|
typage d'une fonction
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
# let f x y z = if x > 0 then y + x else z - x;;
|
||||||
|
val f : int -> int -> int -> int = <fun>
|
||||||
|
|
||||||
|
c’est en fait une fonction à un argument qui retourne une fonction::
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
val f : int -> (int -> (int -> int)) = <fun>
|
||||||
|
|
||||||
|
application de f à trois valeurs
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
# f 1 2 3;;
|
||||||
|
- : int = 3
|
||||||
|
|
||||||
|
en programmation fonctionnelle,
|
||||||
|
les fonctions sont des valeurs comme les autres
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
# fun x -> x * x;;
|
||||||
|
- : int -> int = <fun>
|
||||||
|
|
||||||
|
récursivité
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
let rec fact n =
|
||||||
|
if n=0 then 1 else n * fact (n-1)
|
||||||
|
|
||||||
|
|
||||||
|
équivalent impératif utilisant une boucle
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
int fact(int n){
|
||||||
|
int f = 1 ;
|
||||||
|
int i = n ;
|
||||||
|
while (i>0){
|
||||||
|
f = f * i;
|
||||||
|
i-- ;
|
||||||
|
} ;
|
||||||
|
return f ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Définitions par cas
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
let rec fact n =
|
||||||
|
match n with
|
||||||
|
0 -> 1
|
||||||
|
| -> n * fact (n-1)
|
||||||
|
|
||||||
|
**exemple** : la fonction puissance
|
||||||
|
|
||||||
|
.. code-block:: ocaml
|
||||||
|
|
||||||
|
let rec puissance x n = match n with
|
||||||
|
0 -> 1
|
||||||
|
| -> x * puissance x (n-1)
|
|
@ -11,6 +11,8 @@ Introduction à l'algorithmique
|
||||||
programme
|
programme
|
||||||
fonctions
|
fonctions
|
||||||
control
|
control
|
||||||
|
donnees
|
||||||
apercu
|
apercu
|
||||||
modularite
|
modularite
|
||||||
|
modules
|
||||||
annexes/index
|
annexes/index
|
||||||
|
|
|
@ -60,6 +60,39 @@ traitements et les données.**
|
||||||
Structuration et sûreté d'exécution
|
Structuration et sûreté d'exécution
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
La programmation raisonnée
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Un **programme** est le codage d'un algorithme dans un langage de programmation.
|
||||||
|
La programmation consiste à modéliser un problème du monde réel sous une forme
|
||||||
|
symbolique (pour faire résoudre ce problème par un ordinateur).
|
||||||
|
|
||||||
|
Certains problèmes sont **indécidables** ou **ouverts**.
|
||||||
|
On utilise un langage de programmation pour décrire la **solution** du programme.
|
||||||
|
La sémantique du programme est le sens de chacune des constructions du langage.
|
||||||
|
**Comment passer de l'énoncé d'un problème à un programme de bonne qualité ?**
|
||||||
|
|
||||||
|
spécifier
|
||||||
|
|
||||||
|
décrire de manière complète et rigoureuse le problème à résoudre
|
||||||
|
|
||||||
|
modéliser
|
||||||
|
|
||||||
|
proposer une représentation du réel qui soit accessible au calcul
|
||||||
|
algorithmique
|
||||||
|
|
||||||
|
transcrire
|
||||||
|
|
||||||
|
La transcription du modèle algorithmique se fait dans un langage
|
||||||
|
de programmation cible adapté au problème
|
||||||
|
|
||||||
|
valider
|
||||||
|
|
||||||
|
La validation du programme est une étape qui permet de s'assurer plus ou
|
||||||
|
moins fortement que le programme produit les résultats attendus.
|
||||||
|
La validation va de la série de tests unitaires (validation faible)
|
||||||
|
à la preuve de programme (validation mathématique forte).
|
||||||
|
|
||||||
La preuve de programme
|
La preuve de programme
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -90,19 +123,30 @@ système lors de ses exécutions possibles et permetent de dire si globalement,
|
||||||
donné, le programme va fonctionner correctement. Encore très lourdes, ces techniques ne sont
|
donné, le programme va fonctionner correctement. Encore très lourdes, ces techniques ne sont
|
||||||
utilisées que dans un contexte industriel de haute sécurité.
|
utilisées que dans un contexte industriel de haute sécurité.
|
||||||
|
|
||||||
|
|
||||||
Les tests d'acceptation
|
Les tests d'acceptation
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
C'est sont les tests unitaires et fonctionnels
|
Il y a plusieurs types de tests
|
||||||
|
|
||||||
|
- unitaires
|
||||||
|
- fonctionnels
|
||||||
|
- acceptation
|
||||||
|
|
||||||
Très utilisés dans l'industrie, les tests unitaires et fonctionnels ne testent que certaines
|
Très utilisés dans l'industrie, les tests unitaires et fonctionnels ne testent que certaines
|
||||||
parties du programme et permettent de dire que le programme va marcher grosso-modo à peu près.
|
parties du programme et permettent de dire que le programme va marcher grosso-modo à peu près.
|
||||||
Beaucoup moins coûteux à installer, ce sont des éléments cléfs des méthodes agiles.
|
Beaucoup moins coûteux à installer, ce sont des éléments cléfs des méthodes agiles.
|
||||||
|
|
||||||
|
Les Outils de linting (validation)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
la dette technique
|
- vérifications syntaxiques
|
||||||
|
- vérification sémantiques
|
||||||
|
- vérification sur les imports inutiles ou mal formés (imports croisés
|
||||||
|
|
||||||
|
Exemple en python : pylint
|
||||||
|
|
||||||
|
|
||||||
|
La dette technique
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Au bout d'un moment le code devient du code spaghetti et les techniques sont obsolètes.
|
Au bout d'un moment le code devient du code spaghetti et les techniques sont obsolètes.
|
||||||
|
@ -114,7 +158,6 @@ sinon il peut y avoir un coût à payer qui sera pohibitoire.**
|
||||||
On solde la dette technique parce que à un moment ça va devenir beaucoup trop
|
On solde la dette technique parce que à un moment ça va devenir beaucoup trop
|
||||||
cher à payer.
|
cher à payer.
|
||||||
|
|
||||||
|
|
||||||
Les méthodologies agiles
|
Les méthodologies agiles
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -141,30 +184,44 @@ sprint. Un sprint aboutit toujours sur la livraison d'un produit partiel fonctio
|
||||||
temps, le facilitateur a la charge de réduire au maximum les perturbations extérieures et de
|
temps, le facilitateur a la charge de réduire au maximum les perturbations extérieures et de
|
||||||
résoudre les problèmes non techniques de l'équipe.
|
résoudre les problèmes non techniques de l'équipe.
|
||||||
|
|
||||||
|
Conception descendante d'un programme
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
Les Outils de linting (validation)
|
Il s'agit d'une méthode de résolution d'un problème. On le découpe en tâches
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
de plus en plus fines, de plus en plus détaillées, qui aboutiront au programme final.
|
||||||
|
|
||||||
- vérifications syntaxiques
|
On met des *trous* dans les algorithmes de plus haut niveau,
|
||||||
- vérification sémantiques
|
c'est-à-dire des phrases en langage naturel.
|
||||||
- vérification sur les imports inutiles ou mal formés (imports croisés
|
|
||||||
|
|
||||||
Exemple en python : pylint
|
.. ifconfig: exercice
|
||||||
|
|
||||||
Les modules
|
**Exercice** : **Calculer la date du lendemain**
|
||||||
-----------
|
|
||||||
|
|
||||||
Il s'agit de décomposer un grand programme en
|
.. ifconfig: correction
|
||||||
morceaux (**modules**) connectés entre eux par des **interfaces** bien
|
|
||||||
définies.
|
|
||||||
|
|
||||||
Ces modules doivent être aussi indépendants que possible.
|
- l'algorithme de plus bas niveau
|
||||||
|
|
||||||
module
|
::
|
||||||
|
|
||||||
ensemble de ressources liées sémantiquement
|
lendemain jour =
|
||||||
|
si jour [est le dernier jour du mois] alors
|
||||||
|
resultat = [calculer le 1er janvier de l'année suivante]
|
||||||
|
sinon
|
||||||
|
resultat = lendemain_dansl'année jour
|
||||||
|
|
||||||
interface
|
- les algorithmes de plus bas niveau
|
||||||
|
|
||||||
mode d’emploi du module, avec en plus un principe de masquage
|
::
|
||||||
des informations (partie publique, partie secrète)
|
|
||||||
|
lendemain_dans_l'année jour =
|
||||||
|
si jour [est le dernier jour du mois] alors
|
||||||
|
resultat = [calculer le premier jour du mois suivant]
|
||||||
|
sinon
|
||||||
|
resultat = jour suivant jour
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
jour_suivant jour =
|
||||||
|
jour + 1
|
||||||
|
|
||||||
|
et ainsi de suite jusqu'à ce que toutes les phrases soient calculables.
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
Les modules
|
||||||
|
============
|
||||||
|
|
||||||
|
Il s'agit de décomposer un grand programme en
|
||||||
|
morceaux (**modules**) connectés entre eux par des **interfaces** bien
|
||||||
|
définies.
|
||||||
|
|
||||||
|
Ces modules doivent être aussi indépendants que possible.
|
||||||
|
|
||||||
|
module
|
||||||
|
|
||||||
|
ensemble de ressources liées sémantiquement
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
mode d’emploi du module, avec en plus un principe de masquage
|
||||||
|
des informations (partie publique, partie secrète)
|
||||||
|
|
||||||
|
Exemples d'interface
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
type: son type
|
||||||
|
arguments
|
||||||
|
arg1 : description de l'argument 1
|
||||||
|
arg2 : description de l'argument 2
|
||||||
|
préconditions:
|
||||||
|
arg1 > 10
|
||||||
|
postconditions:
|
||||||
|
result < 19
|
||||||
|
raises: TypeError, AssertionError, SystemError...
|
||||||
|
test: tests nominaux pour chaque cas spécifié
|
||||||
|
|
||||||
|
- L'interface racine carrée
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
racine:
|
||||||
|
type: float -> float
|
||||||
|
arguments x: float, flottant dont on veut calculer la racine
|
||||||
|
pré: x >= 0
|
||||||
|
test: racine 25.0 -> 5.0 ; racine (-25) -> raises TypeError
|
||||||
|
|
||||||
|
- L'interface `lendemain`
|
||||||
|
|
||||||
|
Il faut définir auparavant un type spécifique appelé `date`
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
lendemain: le lendemain est la date qui désigne
|
||||||
|
le jour suivant de la date passée en argument
|
||||||
|
type: date -> date
|
||||||
|
arguments :
|
||||||
|
d: date
|
||||||
|
description: la date dont on veut calculer le lendemain
|
Loading…
Reference in New Issue