formations/algorithmique/cours/fondement.txt
2017-05-03 09:26:24 +02:00

199 lines
8.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Présentation de l'art de programmer
====================================
Qu'est-ce que la programmation ?
--------------------------------
programmation
Description dun calcul (traitement) dans
un langage compréhensible par la machine
(langage de programmation)
Le processus d'abstraction
--------------------------
Débuter en programmation n'est pas une chose aisée. Aujourd'hui, la tendance est au
"bas niveau". Souvent, on se jette dans le grand bain :
- soit en s'approchant au maximum de la machine (admin système et réseau, noyau
linux, langage C)
- soit en faisant du dev web côté backend, ce qui ramène à une administration réseau
de bas niveau (microservices, monde nodeJS/javascript, etc...)
Soit on suit un cursus scolaire traditionnel qui commence souvent par une
explication du fonctionnement d'une machine abstraite de bas niveau, puis en
allant de plus en plus haut, mais étant sous-entendu qu'il faut rester connecté au
bas niveau (comprendre comment ça se passe derrière la scène).
Dans ces deux cas, il est sous-entendu qu'on apprend plus de choses et plus rapidement en mettant
les mains dans le cambouis, ce qui est vrai bien sûr. Mais cela sous-entend qu'un développeur doit
rester le nez dans le guidon. Qu'il doit être un expert de son domaine en accumulant des technologies
sans aucun recul. Bien sûr il se doit d'être un expert du système dans lequel il évolue
(connaissance du système d'exploitation, binding avec le C, du ramasse miette (garbage
collector), interaction avec les différentes librairies, gestion et optimisation de la mémoire,
architecture par microservices, threads...) mais il doit aussi être capable de prendre du recul.
L'approche algorithmique (algorithmique de pseudo code, algorithmique algébrique et modulaire)
est un véritable moyen pour le programmeur de prendre du recul : elle commence par se placer du
côté de l'esprit humain et de ses capacités de compréhension et d'abstraction, elle autorise une
pensée rationnelle sur l'art de programmer et permet au programmeur d'effectuer les bons choix,
en connaissance de sa discipline.
Le lien est fait ensuite avec le plus bas niveau grâce une implémentation effective
des langages à partir des paradigmes de rationalisation de la penseée (modules,
objects, généricité, polymorphisme paramétrique...) et d'un outil de communication
avec la machine qu'on appelle compilateur (dont la description est en dehors de
l'objectif de ce cours).
La tendance générale de l'évolution des langages est de se libérer de ces
contraintes de bas niveau, un peu comme en sciences physiques où les lois physiques
dépendent de l'échelle d'en dessous (du niveau microscopique/quantique) mais qu'à
l'échelle du dessus, on n'a pas affaire à des effets de bas niveau (pas d'effets
quantiques à un niveau macroscopique en général). Ce processus d'évolution est vrai
aussi dans le monde de la technique informatique lui-même (modèle OSI, comment est
construite une trame IP, indépendances de chaque couche (transport, payload) entre
elles). Même la tendance système est à la virtualisation qui accentue encore la
tendance à s'affranchir du bas niveau (le niveau système), le séparer nettement du
haut niveau (le niveau applicatif).
Il apparaît régulièrement de nouveaux langages. Comment s'orienter ? Quel(s)
langage(s) choisir pour un projet de développement ? Au delà de leurs disparités, la
conception et la genèse de chacun d'eux procèdent d'une motivation partagée : la
volonté d'abstraire.
- **s'abstraire de la machine** : un langage de programmation permet de
négliger l'aspect *mécanique* de l'ordinateur. On oublie le modèle du
microprocesseur, jusqu'au système d'exploitation sur lequel sera exécuté
le programme.
- **abstraire les erreurs** : Il s'agit ici de garantir la sûreté d'exécution; un
programme ne doit pas se terminer brutalement ou devenir incohérent en cas d'erreur.
Un des moyens pour y parvenir est le typage des programmes et la mise
en oeuvre d'un mécanisme d'exceptions.
- **abstraire le mode opératoire** : Il s'agit de choisir une représentation, un
paradigme d'implémentation qui est indépendant du domaine considéré (paradigme
objet, modulaire, générique, composants...)
- **abstraire les composants** : Les langages de programmation donnent la
possibilité de découper une application en différents composants logiciels, plus ou
moins indépendants et autonomes. La modularité permet une structuration de plus haut
niveau de l'ensemble d'une application complexe. Les langages à objets constituent
une autre approche de la réutilisabilité permettant la réalisation très rapide de
prototypes.
Description des niveaux d'abstraction par rapport à la machine
---------------------------------------------------------------
Les langages de haut niveau simplifient le travail du
programmeur là où les langages de bas niveau permettent de produire un code
plus efficace.
- **niveau 0** : le langage machine. Illisible, c'est une suite d'optcode.
impossible de coder dans ce langage.
- **niveau 1** : langage d'assemblage. Il reste très dépendant de la machine
et aujourd'hui il est rare d'en faire, sauf si on code un bootloader par exemple,
la gestion de l'accès à la mémoire est en réel (le mode protégé n'apparaît que après).
Il faut gérer les ressources,le langage est très optimisé mais presque impossible
à maintenir et rendre générique. Aujourd'hui plus personne ne code en assembleur.
- **niveau 2** : langages dits de **bas niveau** : (exemple : le C, le C++)
indépendance par rapport à la machine, grande structuration mais très verbeux
- **niveau 3** : langages dits de **haut niveau** : le raisonnement dans ces
langages ne dépent plus de la machine, et ils implémentent des paradigmes de
programmation indépendant de l'état de la mémoire de l'ordinateur,
ils sont indépendant même du système d'exploitation.
Qu'est-ce qu'une machine ?
---------------------------
Une machine, ce truc apparemment si complexe, est en fait
un assemblage de bric et de brac.
L'assemblage des connecteurs permet de simuler un additionneur,
en prenant en compte les propriétés de **reste euclidien**
de l'addition.
La structure électronique est composée de :
- un ordonnanceur.
- le stockage d'un **état**.
- une pile d'instruction
.. glossary::
adressage
Dès lors qu'on dispose de ces bases électronique au dessus du processeur,
un langage d'assemblage est possible, c'est le langage de calcul sur les registres.
registre
machines ont un espace mémoire et un espace de calcul (registres)
Un ordinateur, c'est très très stupide, mais ça permet de disposer de :
- une mémoire très grande et ordonnée,
- une capacité à effectuer inlassablement des tâches répétitives
- une grande rapidité de calcul
Apprendre à programmer, c'est-à-dire être capable de
contrôler la machine.
.. important:: Apprendre à programmer, c'est-à-dire apprendre à penser de manière structurée,
pour pouvoir accessoirement ensuite communiquer avec une machine.
Compilateur
-----------
Schématiquement, un compilateur est un programme qui traduit un
programme dun langage source vers un langage cible, en signalant
déventuelles erreurs.
Quand on parle de compilation, on pense typiquement à la traduction dun
langage de haut niveau (C, Java, Caml, ...) vers le langage machine dun
processeur (Intel Pentium, PowerPC, ...)
- xml (libre office, word) -> postscript (imprimante)
- postcript -> image
- syntaxe wiki -> html (Wikipédia...)
compilation graphique
passer une description, ça donne un dessin genre ocaml Quilt < mon_dessin.txt
passer par une api qui permet de causer avec une interface
**transpiler** : transformation d'un langage de haut niveau vers un autre
langage de haut niveau.
- cofee script, typescript -> javascript
- (babel) javascript -> javascript ES 6
- python -> javascript
Un compilateur traduit un programme P en un programme Q tel que
pour toute entrée x , la sortie de `Q(x)` soit la même que celle de `P(x)`
Un interprète est un programme qui, étant donné un programme `P` et une
entrée x , calcule la sortie s de `P(x)`
Le compilateur fait un travail complexe une seule fois, pour produire un
code fonctionnant pour nimporte quelle entrée
Linterprète effectue un travail plus simple, mais le refait sur chaque entrée
Autre différence : le code compilé est généralement bien plus efficace que
le code interprété
Typiquement, le travail dun compilateur se compose dune phase danalyse
- reconnaît le programme à traduire et sa signification
- signale les erreurs et peut donc échouer (erreurs de syntaxe, de portée, de typage, etc.)
Puis dune phase de synthèse
- production du langage cible
- utilise de nombreux langages intermédiaires
- néchoue pas