Cours de C. Portabilité, maintenabilité & réutilisabilité. Sébastien Paumier



Documents pareils
Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Cours Langage C/C++ Programmation modulaire

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie

Quelques éléments de compilation en C et makefiles

Introduction au langage C

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Bases de programmation. Cours 5. Structurer les données

Systeme d'exploitation

Les structures. Chapitre 3

Cours de C. Allocation dynamique. Sébastien Paumier

Le prototype de la fonction main()

I. Introduction aux fonctions : les fonctions standards

Plan du cours. Historique du langage Nouveautés de Java 7

Conventions d écriture et outils de mise au point

INF2015 Développement de logiciels dans un environnement Agile. Examen intra 20 février :30 à 20:30

Compression de Données - Algorithme de Huffman Document de Conception

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

Programmation C. Apprendre à développer des programmes simples dans le langage C

Algorithmique et Programmation, IMA


Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

Le langage C. Séance n 4

Archivage Messagerie Evolution pour usage HTML en utilisant Hypermail

UE Programmation Impérative Licence 2ème Année

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Programmation en langage C

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

SUPPORT DE COURS. Langage C

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

Programmation système I Les entrées/sorties

Les structures de données. Rajae El Ouazzani

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Testez votre installation. Créer un répertoire vide

as Architecture des Systèmes d Information

Chap III : Les tableaux

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

INITIATION A LA PROGRAMMATION

PROJET ALGORITHMIQUE ET PROGRAMMATION II

UE C avancé cours 1: introduction et révisions

Initiation. àl algorithmique et à la programmation. en C

Cours d initiation à la programmation en C++ Johann Cuenin

Programmation système de commandes en C

Cours Programmation Système

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Analyse de sécurité de logiciels système par typage statique

Cours 1: Java et les objets

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Le langage C. Introduction, guide de reference

Dans le chapitre 1, nous associions aux fichiers ouverts des descripteurs de fichiers par lesquels nous accédions aux fichiers.

Processus d Informatisation

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

3IS - Système d'exploitation linux - Programmation système

Programmer en JAVA. par Tama

The Mozilla Art Of War. David Teller. 20 septembre Laboratoire d Informatique Fondamentale d Orléans. La sécurité des extensions.

Projet d informatique M1BI : Compression et décompression de texte. 1 Généralités sur la compression/décompression de texte

OS Réseaux et Programmation Système - C5

Les fichiers. Chapitre 4

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Les arbres binaires de recherche

Cours de programmation avancée. Le langage C. Université du Luxembourg

Assurance Qualité. Cours de génie logiciel. Renaud Marlet. LaBRI / INRIA (d'après A.-M. Hugues) màj 23/04/2007

Chapitre 1 : La gestion dynamique de la mémoire

Programmation impérative

Les chaînes de caractères

Langage Éric Guérin 5 octobre 2010

Programmation C++ (débutant)/instructions for, while et do...while

Cours de Programmation 2

Notes du cours 4M056 Programmation en C et C++ Vincent Lemaire et Damien Simon

Apprendre Java et C++ avec NetBeans

Mon premier rpm. 7 juin Avant de commencer RPM URPMI RPMBUILD... 2

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

Langage Java. Classe de première SI

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

La programmation orientée objet et le langage C++

WINDOWS NT 2000: Travaux Pratiques. -Boîtier partage d'imprimante- Michel Cabaré Janvier 2002 ver 1.0

Chapitre I Notions de base et outils de travail

Algorithmique, Structures de données et langage C

Généralités sur le Langage Java et éléments syntaxiques.

Cours de C/C++ par la pratique. Hugues Talbot

Titre: Version: Dernière modification: Auteur: Statut: Licence:

Algorithmique & Langage C IUT GEII S1. Notes de cours (première partie) cours_algo_lgc1.17.odp. Licence

TP1. Outils Java Eléments de correction

Java Licence Professionnelle CISII,

Module.NET 3 Les Assemblys.NET

Installation et prise en main

Auto-évaluation Programmation en Java

Mysql. Les requêtes préparées Prepared statements

Cahier des charges. driver WIFI pour chipset Ralink RT2571W. sur hardware ARM7

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Arguments d un programme

Modernisation, développement d applications et DB2 sous IBM i Technologies, outils et nouveautés Volubis.fr

Transcription:

Cours de C Portabilité, maintenabilité & réutilisabilité Sébastien Paumier paumier@univ-mlv.fr Illustrations provenant du site http://tux.crystalxp.net/ 1

Portabilité qu'est-ce qu'un code portable? indépendance vis-à-vis: du compilateur du système de la machine pourquoi le faire? force à coder proprement en prenant du recul facilite la diffusion des applications paumier@univ-mlv.fr 2

Un code qui compile partout pour qu'un code compile toujours, il faut: éviter les trucs exotiques comme #pragma respecter les normes (-ansi -Wall) cerner le code qui dépend du compilateur, du système ou de la machine éviter les dépendances vers des bibliothèques non portables faire des Makefile portables paumier@univ-mlv.fr 3

Cerner le code variable tout code pouvant varier doit être cerné avec des directives préprocesseur, et si possible isolé dans des fichiers à part /** * System-dependent function that compares * file names. */ int fcompare(const char* a,const char* b) { #ifdef WINDOWS_LIKE /* case doesn't matter under windows */ return strcmp_ignore_case(a,b); #else return strcmp(a,b); #endif } paumier@univ-mlv.fr 4

Cerner le code variable même chose pour les inclusions, les types, les constantes, etc. #ifdef WINDOWS_LIKE #include "mygetopt.h" #else #include <getopt.h> #endif #ifndef WINDOWS_LIKE #define PATH_SEPARATOR_CHAR '/' #define PATH_SEPARATOR_STRING "/" #else #define PATH_SEPARATOR_CHAR '\\' #define PATH_SEPARATOR_STRING "\\" #endif paumier@univ-mlv.fr 5

Noms de fichiers casse importante sous certains systèmes il faut être soigneux: motor.c #include "Motor.h" /*... */ motor.h #ifndef motorh #define motorh /*... */ #endif compile sous Windows, pas sous Linux paumier@univ-mlv.fr 6

Dépendances au système 2 types de dépendances: valeurs/types (séparateur de fichier / ou \) comportements (casse des noms de fichiers) pour le 1 er type, la gestion par #ifdef suffit pour le second, pas toujours paumier@univ-mlv.fr 7

Dépendances au système chaque fois que quelque chose dépend du système, il faut l'expliciter exemple: longueur des noms de fichiers mauvaise solution: constante arbitraire bonne solution: utiliser la constante FILENAME_MAX (stdio.h) adaptée au système courant paumier@univ-mlv.fr 8

Tailles des types anticiper les différences d'architecture utiliser les constantes de limits.h utiliser sizeof exemple non portable: void** new_ptr_array(int n) { void** ptr=malloc(n*4); if (ptr==null) { /*... */ } return ptr; } sur une machine 64 bits, sizeof(void*) vaut 8 paumier@univ-mlv.fr 9

Tailles des types si on a besoin d'un type avec une taille en octets fixe, utiliser les constantes de stdint.h exemple: si on veut gérer Unicode non étendu, on a besoin d'un type non signé sur 2 octets #include <stdint.h> typedef uint16_t unichar; paumier@univ-mlv.fr 10

Les sauts de lignes Windows: \r\n Linux: \n MacOS: \r il ne suffit pas que le programme soit portable est-ce que les données doivent l'être? comment lire/écrire un fichier texte multiplateforme? paumier@univ-mlv.fr 11

Endianness x86-like: little-endian Motorola-like: big-endian il ne suffit pas que le programme soit portable est-ce que les données doivent l'être?* comment lire/écrire un fichier binaire contenant des int d'une façon multiplateforme? exemple de solution: encodage utf8 * (toute ressemblance avec un transparent existant serait forfuite et involontaire) paumier@univ-mlv.fr 12

Makefile écrire des Makefile portables avec une variable qui dépend du système informations concernées: compilateur à utiliser options de compilation répertoires (include, lib, etc) commandes d'installation et de nettoyage noms des sorties (exemple:.exe ou pas?) etc. paumier@univ-mlv.fr 13

Makefile exemple: compilation portable d'une bibliothèque test sur une variable d'environnement pour savoir si on est sous Windows (à vérifier...) définitions dépendant du système ifeq ($(strip $(PATHEXT)),) SYSTEM = linux-like else SYSTEM = windows endif CC = gcc CFLAGS = -fpic OBJS = utf8.o ifeq ($(SYSTEM),linux-like) CLEAN = rm -f OUTPUT = libutf8.so else CLEAN = del OUTPUT = utf8.dll endif paumier@univ-mlv.fr 14

Makefile instructions pour Linux instructions pour Windows all: $(OUTPUT) %.o: %.c $(CC) -c $< $(CFLAGS) ifeq ($(SYSTEM),linux-like) $(OUTPUT): $(OBJS) $(CC) -shared $(OBJS) -o $(OUTPUT) else $(OUTPUT): $(OBJS) $(CC) -shared $(OBJS) -Wl,--export-all-symbols -o $(OUTPUT) endif clean: $(CLEAN) *.o $(CLEAN) $(OUTPUT) paumier@univ-mlv.fr 15

Maintenabilité & réutilisabilité ou introduction au génie logiciel Référence: L'art de la programmation UNIX, Eric S. Raymond, Vuibert paumier@univ-mlv.fr 16

"Pour être un bon développeur en biniou, il suffit d'être bon en algo et de maîtriser la syntaxe de biniou " Proverbe étudiant "Quand on est con, on est con" Georges Brassens paumier@univ-mlv.fr 17

Qu'est-ce que le GL? ensemble de bonnes pratiques et de conseils à méditer objectifs: développer mieux et plus vite* mieux=moins de bugs, code réutilisable, évolutif, etc. plus vite=accélérer le débogage, éviter de tout casser tout le temps, etc. *(comment devenir des feignants efficaces) paumier@univ-mlv.fr 18

Règle de modularité écrire des éléments simples et les relier par des interfaces propres pour faire des applications complexes, il faut pouvoir contrôler la complexité du code principe d'encapsulation en bibliothèques boîtes noires paumier@univ-mlv.fr 19

Règle de clarté préférer la clarté à l'intelligence penser à celui qui relira le code un algorithme très rusé a moins de chances d'être lisible qu'un classique risque plus élevé de bugs moins facile à entretenir style gourou à bannir absolument!!! paumier@univ-mlv.fr 20

Règle de composition concevoir des programmes à connecter à d'autres programmes éviter les programmes "dieu" qui font tout ne pas réinventer la roue: utiliser les choses faites par ceux qui savent (vous gérez les.pnm? utilisez anytopnm pour les autres formats) utiliser les dépendances paumier@univ-mlv.fr 21

Règle de séparation séparer méthode et mécanismes; séparer moteur et interfaces bonne pratique: ne rendre visible que les interfaces et pas les implémentations en utilisant static exemple: frontal GUI dissocié des tâches de fond (affichage et calcul=tâches différentes) 1 module=1 responsabilité paumier@univ-mlv.fr 22

Règle de transparence concevoir un comportement lisible pour faciliter l'investigation et le débogage n'utiliser que de bonnes interfaces toute ce qui facilite le débogage est bon mettre des sorties de debug ne pas lésiner sur les tests ne pas cacher les bugs void foo(int t[],int n) { if (n<=0) { /* should not happen */ fprintf(stderr,"n<=0 in foo!\n"); return; } /*... */ } paumier@univ-mlv.fr 23

Règle de robustesse engendrer de la robustesse par la transparence et la simplicité penser aux conditions d'utilisation non normales: tester, tester, tester pas de données cachées en dur: fichiers de configuration éviter les cas particuliers dans le code paumier@univ-mlv.fr 24

Règle de robustesse exemple: les jeux de plateau comment tester les voisins dans un 8x8? cas particulier 6 cas particulier 7 cas particulier 8 cas particulier 5 cas général cas particulier 1 cas particulier 4 cas particulier 3 cas particulier 2 paumier@univ-mlv.fr 25

Règle de robustesse bonne solution: ajouter une bordure inerte (des cases vides, par exemple) taille du jeu=8x8 taille du tableau=10x10 bordure inerte un seul cas: le cas général avec 8 voisins paumier@univ-mlv.fr 26

Règle de représentation placer le savoir dans les données, afin d'obtenir des algorithmes disciplinés et robustes prévoir de bonnes structures de données si l'on utilise des structures, l'ajout d'une information ne modifie pas le code void minimize(state s[], int n_states, Transition t[]); typedef struct { State* s; int n_states; Transition* t; } Automaton; void minimize(automaton* a); paumier@univ-mlv.fr 27

Règle de la moindre surprise éviter les surprises dans la conception des interfaces éviter les nouveautés inutiles respecter les habitudes: des programmeurs (pourquoi changer si for(i=0;i<n;i++) convient?) des utilisateurs (ne pas appeler.txt un fichier binaire) paumier@univ-mlv.fr 28

Règle de silence n'afficher des informations que si nécessaires informations inutiles=pollution les informations internes (debug) doivent pouvoir être désactivées contre-exemple: un programme qui peut durer longtemps peut afficher pour montrer qu'il n'est pas planté (ex: gros calcul) paumier@univ-mlv.fr 29

Règle de réparation réparer ce qui est possible, mais en cas de problème, faire échouer clairement et rapidement "être tolérant avec ce qu'on reçoit, exigeant avec ce qu'on envoie" (J. Postel) mais: à vouloir trop gérer les erreurs, on crée des usines à gaz if (n<=0) { /* should not happen */ fprintf(stderr,"n<=0 in foo!\n"); return; } prévenir clairement si l'erreur est fatale, ne pas hésiter à faire exit paumier@univ-mlv.fr 30

Règle d'économie préférer l'économie du temps de programmation à celle du temps machine automatiser autant que possible exemple: inutile de garder en cache la taille des chaînes de caractères dans l'immense majorité des cas, strlen suffit paumier@univ-mlv.fr 31

Règle de génération éviter le travail manuel; écrire plutôt des programmes de génération (de programmes, de données, etc.) exemples: flex, bison, automake si un programme utilise un fichier d'entiers, écrire un autre programme pour générer les fichiers de test du 1 er paumier@univ-mlv.fr 32

Règle d'optimisation créer des prototypes avant d'affiner; rechercher un bon fonctionnement avant d'optimiser "l'optimisation prématurée est la source de tout mal " (C.A.R. Hoare) "dans 90% des cas, la meilleure optimisation consiste à ne rien faire" intuition mauvaise conseillère utiliser des outils de profiling paumier@univ-mlv.fr 33

Règle de diversité se méfier de la bonne solution unique en utilisant des interfaces propres, on laisse la possibilité d'utiliser un jour une autre implémentation (plus rapide, moins gourmande, dans un autre langage, etc.) void foo(automaton* a) { State* s=a->states[0]; if (s->control & FINAL) { /*... */ } /*... */ } void foo(automaton* a) { State* s=get_state(a,0); if (is_final(s)) { /*... */ } /*... */ } paumier@univ-mlv.fr 34

Règle de simplicité concevoir des systèmes simples; n'introduire de la complexité que si nécessaire "La simplicité est la sophistication suprême " (Léonard de Vinci) pas d'abstraction inutile pas de hashtable générique si l'on ne manipule que des entiers ne pas trop anticiper pas de param. inutiles, au cas où, plus tard... paumier@univ-mlv.fr 35

Règle d'extensibilité concevoir en pensant à l'avenir, qui sera là plus tôt qu'on ne l'imagine formats de fichiers génériques utilisation de numéros de version exemple: gestion d'encodages typedef enum {ASCII,UTF8,UTF16LE} Encoding; typedef int (*encoder) (int,file*); encoder get_fputc(encoding encoding) { if (encoding==ascii) return fputc_ascii; if (encoding==utf8) return fputc_utf8; if (encoding==utf16le) return fputc_utf16le; return NULL; } pas évolutif paumier@univ-mlv.fr 36

Règle d'extensibilité bonne solution: utiliser une bibliothèque qui les gère avec possibilité d'en ajouter, éventuellement dynamiquement encodings.h : /* This library is designed to * manage various implementations * of fputc for various encodings. * Defaults = "ASCII" "UTF8" */ #ifndef encodings_h #define encodings_h #include <stdio.h> typedef int (*encoder) (int,file*); interface très simple void add_encoder(char* name,encoder f); encoder get_encoder(char* name); #endif paumier@univ-mlv.fr 37

Règle d'extensibilité début de encodings.c : #include "encodings.h" #include "utf8.h" #include <stdlib.h> #include <string.h> static int init(); static int n=init(); static int init() { n=0; add_encoder("ascii",fputc); add_encoder("utf8",fputc_utf8); return n; } #define ENC_MAX 256 typedef struct { char* name; encoder f; } Encoding; static Encoding enc[enc_max]; initialisation automatique au chargement du code, pour mettre des encodages par défaut implémentation cachée paumier@univ-mlv.fr 38

Règle d'extensibilité fin de encodings.c : void add_encoder(char* s,encoder f) { if (n==enc_max) { fprintf(stderr,"too much encodings!\n"); exit(1); } enc[n].name=strdup(s); enc[n].f=f; n++; } encoder get_encoder(char* name) { int i; for (i=0;i<n;i++) { if (!strcmp(enc[i].name,name)) { return enc[i].f; } } return NULL; } est-ce la peine de gérer les doublons? pas la peine d'optimiser en utilisant des constantes au lieu de chaînes paumier@univ-mlv.fr 39

Et tout le reste... coder et commenter en anglais utiliser des formats lisibles, et si possible standards et ouverts toujours penser à ceux qui reliront le code penser à l'utilisateur qui n'a pas forcément les mêmes repères respecter les spécifications données! paumier@univ-mlv.fr 40