L'informatique est avant tout une science de l'abstraction --- il
s'agit de créer le bon modèle pour un problème et d'imaginer les
bonnes techniques automatisables et appropriées pour le résoudre.
Toutes les autres sciences considèrent l'univers tel qu'il est. Par
exemple, le travail d'un physicien est de comprendre le monde et non
pas d'inventer un monde dans lequel les lois de la physique seraient
plus simples et auxquelles il serait plus agréable de se conformer.
À l'opposé, les informaticiens doivent créer des abstractions des
problèmes du monde réel qui pourraient être représentées et
manipulées dans un ordinateur.
Aho & Ullman [1]
1.1 Informatique = mécanisation de l'abstraction
Un programme est une suite d'instructions définissant des
opérations à réaliser sur des données.
Les instructions du programme sont exécutées les unes après les
autres, le plus souvent dans l'ordre séquentiel dans lequel elles sont
données dans le programme -- on dit que le flot d'exécution, ou flot
de contrôle, est séquentiel.
Pour écrire des programmes, on se sert d'une notation,
appelée langage de programmation.
Les langages de programmation les plus rudimentaires sont ceux qui
"collent" au jeu d'instructions de l'ordinateur ; on les appelle
les langages d'assemblage (cf. annexe A).
Un langage d'assemblage est par définition propre à un processeur
donné (ou au mieux à une famille de processeurs) ; l'évolution de la
programmation vers des projets à la fois complexes et portables a créé
le besoin de langages de plus haut niveau. Ces langages permettent de
gérer la complexité des problèmes traités grâce à la structuration,
qu'on définira dans un premier temps, de manière très générale, comme
le regroupement d'entités élémentaires en entités plus complexes
(enregistrements regroupant plusieurs données, modules ou procédures
regroupant plusieurs instructions élémentaires...).
Un bon programme doit être facile à écrire, à lire, à comprendre et à
modifier. Il faut savoir que la mémoire humaine est limitée par le
nombre plus que par la taille des structures à manipuler. Il devient
donc vite difficile pour un programmeur de maîtriser de nombreuses lignes
de code, si celles-ci ne sont pas regroupées en modules ou autres
structures.
Les avantages de l'utilisation d'un langage de haut niveau sont multiples :
-
Un programme n'est pas seulement destiné à être lu une fois ;
plusieurs intervenants risquent de se pencher sur lui au cours de
son existence, d'où la nécessité de la lisibilité.
- L'existence de
langages évolués a permis la création de logiciels par des
programmeurs qui n'auraient jamais appris un langage d'assemblage.
Il faut noter à ce propos la puissance et la popularité croissante
des langages dits de scriptage (Visual
Basic, TCL/TK...) et des générateurs de programmes de gestion.
- Un
programme en langage évolué peut être "porté" sur différentes
architectures et réutilisé au fil de l'évolution du matériel.
- Un
module clairement spécifié peut être réutilisé comme une brique de
construction, dans divers contextes.
- Un langage peut choisir de
laisser transparaître la machine sous-jacente, ou au contraire
fournir un autre modèle de calcul (cf. parallélisme par exemple,
même s'il y a un seul processeur physique, ainsi que la
programmation fonctionnelle ou la programmation logique).
- Les langages de
programmation offrent des outils pour l'abstraction, la modélisation
et la structuration des données et des opérations. Ils permettent
aussi la vérification de type, qui évite beaucoup d'erreurs
(elle permet par exemple de refuser un programme qui voudrait
additionner 1 et "z").
1.2 Traduction
À partir du moment où l'on utilise un langage différent de celui de la
machine, il devient nécessaire de lui traduire les programmes écrits
dans ce langage. Deux approches sont possibles pour cela. La première
consiste à lancer un programme de traduction simultanée, appelé
interprète, qui traduit et exécute au fur et à mesure les instructions
du programme à exécuter. La deuxième approche consiste à analyser l'ensemble du
programme et à le traduire d'avance en un programme en langage
machine, qui est ensuite directement exécutable. C'est la
compilation.
Java fait partie des langages qui choisissent une
approche hybride : un programme en Java est analysé et compilé, mais
pas dans le langage de la machine physique. Pour des raisons de
portabilité, le compilateur Java traduit dans un langage
intermédiaire, universel et portable, le byte-code, qui est le
langage d'une machine
virtuelle, la JVM (Java Virtual Machine). Cette "machine"
est exécutée sur une machine physique et un interprète le byte-code.
Pour traduire un langage, il faut tenir compte de ses trois niveaux :
-
le niveau lexical, qui concerne le vocabulaire du
langage, les règles d'écriture des mots du langage (identificateurs
de variables ou fonctions), les mots clés,
c'est-à-dire les éléments de structuration du discours, et les
caractères spéciaux, utilisés par exemple pour les opérateurs ;
- le niveau syntaxique, qui spécifie la manière de
construire des programmes dans ce langage, autrement dit les règles
grammaticales propres au langage ;
- le niveau sémantique, qui spécifie la signification de la
notation.
1.3 La programmation : du problème au programme
Nous attaquons ici toute la problématique de la programmation. On peut
distinguer les étapes suivantes dans la vie d'un logiciel [1]:
-
Définition du problème et spécification, incluant éventuellement
plusieurs itérations de spécification avec les futurs utilisateurs
du logiciel, un prototypage du produit final, et une modélisation
des données.
- Conception, avec création de l'architecture de haut
niveau du système, réutilisant si possible des composants déjà
disponibles.
- Réalisation des composants et test de chacun d'eux
pour vérifier qu'ils se comportent comme spécifié.
- Intégration et test du système : une fois chaque composant testé
et validé, encore faut-il que le système intégré le soit.
- Installation et test "sur le terrain", c'est-à-dire en situation
réelle.
- Maintenance : elle représente souvent plus de la moitié du coût
de développement. Le système doit être purgé d'effets
imprévisibles ou imprévus, ses performances doivent être corrigées
ou améliorées, le monde réel dans lequel il est implanté n'étant pas
immuable, il faut modifier le programme ou lui ajouter de nouvelles
fonctionnalités, le système doit souvent être porté sur de nouvelles
plateformes physiques, etc.
Tous ces aspects de maintenance soulignent l'importance d'écrire des
programmes lisibles, corrects, robustes, efficaces, modifiables et
portables !
Nous voyons donc que l'activité d'analyse et de programmation, bien
qu'elle soit au coeur de notre cours, ne représente qu'une des
étapes dans le cycle logiciel.
Ceci étant, nous allons essentiellement nous arrêter sur les phases
qui permettent d'aller d'un problème bien spécifié à un programme, en
passant par la réalisation d'un algorithme précis, c'est-à-dire de la
conception d'une démarche opératoire pour résoudre le problème donné,
cette démarche étant ensuite transcrite dans un langage de
programmation, en l'occurrence Java.
Dans ce cours, nous adoptons une démarche pragmatique, l'apprentissage
des différentes notions se faisant par l'exemple, en l'occurrence le
développement tout au long des chapitres d'un exemple de programme de
gestion bancaire, que nous allons peu à peu enrichir de nouvelles
fonctionnalités, qui illustrent les notions nouvelles introduites à
chaque fois.
Plutôt que de remplir de longues pages sur la syntaxe et les règles de
programmation, nous avons préféré mettre beaucoup d'exemples complets
de programmes, comptant sur votre capacité d'apprentissage par
analogie.
Le chapitre 2 donne les premières bases nécessaires pour
écrire un programme Java élémentaire.
Le chapitre 3 introduit les outils fondamentaux
de structuration des données et des instructions, à savoir les classes
d'un côté et les fonctions et procédures de l'autre.
Au chapitre 4, nous revenons sur la classe, mais pour
introduire les bases de la programmation objet, méthodologie devenue
quasiment incontournable à l'heure actuelle.
Le chapitre 5, quant à lui, vous présente
quelques exemples de modèles de données et la manière dont ils peuvent
être représentés et manipulés.
Il resterait tant à étudier, et le temps nous fait défaut ; j'ai donc
réuni au chapitre 6 un ensemble probablement un peu
disparate d'éléments supplémentaires, qui nous permettront cependant
de compléter la partie programmation de ce cours par un programme qui
dépasse légèrement la banalité habituelle des exercices d'école.
Enfin, pour que vous n'ayez pas l'impression que l'informatique se résume à
la programmation, nous apportons également au chapitre 7
un court éclairage sur le monde des bases de données.
J'ai choisi de reporter en annexes plusieurs ensembles d'informations
utiles en soi, mais dont la présence directe dans le fil du polycopié
aurait nui à la progression de la lecture. Je vous invite cependant à
vous reporter aussi souvent que nécessaire à ces annexes.
Vous y trouverez en particulier un glossaire (annexe C)
que je vous conseille de consulter tout au long de votre lecture.
Vous trouverez peut-être également intéressant de recourir parfois à
l'aide-mémoire de programmation (annexe E) lors de vos
séances de TD.