• Aucun résultat trouvé

Programmation C avanc´ee Portabilit´e, maintenabilit´e et r´eutilisabilit´e

N/A
N/A
Protected

Academic year: 2022

Partager "Programmation C avanc´ee Portabilit´e, maintenabilit´e et r´eutilisabilit´e"

Copied!
40
0
0

Texte intégral

(1)

Programmation C avanc ´ee

Portabilit ´e, maintenabilit ´e et r ´eutilisabilit ´e

Licence informatique 3`emeann ´ee

Universit ´e de Marne-la-Vall ´ee

(2)

Portabilit ´e

I qu’est-ce qu’un code portable ?

I ind ´ependance vis- `a-vis : - du compilateur

- du syst `eme - de la machine

I pourquoi le faire ?

- force `a coder proprement en prenant du recul - facilite la diffusion des applications

(3)

Un code qui compile partout

I pour qu’un code compile toujours, il faut : - ´eviter les choses exotiques comme #pragma - respecter les normes-ansi -Wall

- cerner le code qui d ´epend du compilateur, du syst `eme, de la machine

- ´eviter les d ´ependances vers des biblioth `eques non portables

- faire des Makefile portables

(4)

Cerner le code variable

I tout code pouvant varier doit ˆetre cern ´e avec des directives pr ´eprocesseurs, et si possible, isol ´e dans des fichiers `a part

1 / Systemdependent f u n c t i o n

2 t h a t compares f i l e s names /

3 i n t fcompare (const char a , const char b ){

4 # i f d e f WINDOWS LIKE

5 r e t u r n s t r c m p i g n o r e c a s e ( a , b ) ;

6 # else

7 r e t u r n strcmp ( a , b ) ;

8 # e n d i f

9 }

(5)

Cerner le code variable

I m ˆeme chose pour les inclusions, les types, les constantes, etc.

1 # i f d e f WINDOWS LIKE

2 # include ” mygetopt . h ”

3 # else

4 # include <g e t o p t . h>

5 # e n d i f

1 # i f d e f WINDOWS LIKE

2 # d e f i n e PATH SEPARATOR CHAR ’ / ’

3 # d e f i n e PATH SEPARATOR CHAR ” / ”

4 # else

5 # d e f i n e PATH SEPARATOR CHAR ’\ \

6 # d e f i n e PATH SEPARATOR CHAR ”\ \

7 # e n d i f

(6)

Noms de fichiers

I casse importante sous certains syst `emes

I il faut ˆetre soigneux:

motor.c :

1 # include ” Motor . h ”

2

3 / . . . / motor.h :

1 # i f n d e f motorH

2 # d e f i n e motorH

3 / . . . /

4 # e n d i f

compile souswindows, pas souslinux

(7)

D ´ependances au syst `eme

I 2 types de d ´ependances :

- valeurs/types (s ´eparateur de fichier /ou\) - comportementales (casse des noms de fichiers)

I pour le premier type, la gestion par#ifdef suffit

I pour le second, pas toujours

(8)

D ´ependances au syst `eme

I chaque fois que quelque chose d ´epend du syst `eme, il faut l’expliciter

I exemple : longueur des noms de fichiers - mauvaise solution : constante arbitraire

- bonne solution : utiliser la constante FILENAME MAX (stdio.h) adapt ´ee au syst `eme courant.

(9)

Tailles des types

I anticiper les diff ´erences d’architecture

I utiliser les constantes de limits.h

I utilisersizeof

I exemple non portable :

1 void∗ ∗ n e w p t r a r r a y (i n t n ){

2 void∗ ∗ p t r = m a l l o c ( n4 ) ;

3 i f ( p t r == NULL ){

4 / . . . /

5 }

6 r e t u r n p t r ;

7 }

(10)

Tailles des types

I si on a besoin d’un type avec une taille en octets fixe, utilisez les constantes et types de stdint.h

I exemple : si on veut g ´erer Unicode non ´etendu, on a besoin d’un type sign ´e sur 2 octets

1 # include <s t d i n t . h>

2

3 typedef u i n t 1 6 t u n i c h a r ;

(11)

Les sauts de ligne

I Windows : \r \n

I Linux : \n

I MacOS :\r

I il ne suffit pas que le programme soit portable

I est-ce que les donn ´ees doivent l’ ˆetre ?

- comment faire pour lire/ ´ecrire un fichier texte multi-plateforme ?

(12)

Endianness

I x86-like : little-endian

I Motorola-like : big-endian

I il ne suffit pas que le programme soit portable

I est-ce que les donn ´ees doivent l’ ˆetre ?

- comment lire/ ´ecrire un fichier binaire contenant des int d’une fac¸on multi-plateforme ?

- exemple de solution : encodage utf8

(13)

Makefile

I ´ecrire des Makefile portables avec une variable qui d ´epend du syst `eme

I informations concern ´ees : - compilateur `a utiliser - options de compilation - r ´epertoire (include, lib, etc)

- commandes d’installation et de nettoyage - noms des sorties (exemple: .exeou pas ?) - et bien d’autres...

(14)

Makefile

CCFLAGS=-Wall -ansi ifeq ($(OS),Windows_NT)

CCFLAGS += -D WIN32

ifeq ($(PROCESSOR_ARCHITECTURE),AMD64) CCFLAGS += -D AMD64

endif

ifeq ($(PROCESSOR_ARCHITECTURE),x86) CCFLAGS += -D IA32

endif else

UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux)

CCFLAGS += -D LINUX endif

ifeq ($(UNAME_S),Darwin) CCFLAGS += -D OSX endif

UNAME_P := $(shell uname -p) ifeq ($(UNAME_P),x86_64)

CCFLAGS += -D AMD64 endif

ifneq ($(filter %86,$(UNAME_P)),) CCFLAGS += -D IA32

endif endif

(15)

Makefile

I les versions de windows depuis 2000 poss `edent une variable d’environnement OSdont la valeur est

Windows NT

I les syst `emes bas ´es sur Unixont une commande shell uname qui donne une chaˆıne d ´ecrivant le syst `eme

I en stockant dans une variable du Makefile la description de l’OS, on peut alors donner des instructions d ´edi ´ees pour chaque OS (-fPICest inutile sous Windows pour les biblioth `eques dynamiques par exemple...)

I une entreprise commercialisant des softs a tout int ´er ˆet

`a ne pas d ´evelopper deux fois le m ˆeme logiciel

(16)

De l’art de d ´evelopper rapidement et efficacement

I science appel ´ee le g ´enie logiciel

I pour d ´evelopper un logiciel : - on r ´efl ´echit

- on produit du code

I La production du code :

- implantation de l’application avec ses fonctionnalit ´es (10% du temps de travail)

- d ´ebogage, documentation, affinement, tests, optimisations (90% du temps de travail)

fait : La seconde partie de la production est d’autant plus r ´eduite que l’on a bien r ´efl ´echit avant de passer `a l’action

(17)

Dans l’imaginaire collectif

“Pour ˆetre un bon d ´eveloppeur en langagefoo, il suffit d’ ˆetre bon en algo et de maˆıtriser la syntaxe defoo”

Proverbe ´etudiant

“Quand on est con, on est con”

Georges Brassens

(18)

Qu’est ce que le g ´enie logiciel ?

I ensemble de bonnes pratiques et de conseils `a m ´editer

I objectifs : d ´evelopper mieux et plus vite*

- mieux = moins de bugs, code r ´eutilisable, ´evolutif, etc.

- plus vite = acc ´el ´erer le d ´ebogage, ´eviter de tout casser tout le temps, etc.

*(comment devenir des feignants efficaces)

(19)

R `egle de modularit ´e

´ecrire des ´el ´ements simples et les relier par des interfaces propres

I pour faire des applications complexes, il faut pouvoir contr ˆoler la complexit ´e du code

I principes d’encapsulation en biblioth `equesboˆıtes noires

(20)

R `egle de clart ´e

pr ´ef ´erer la clart ´e `a l’intelligence

I penser `a celui qui relira le code

I un algorithme trop rus ´e a moins de chance d’ ˆetre lisible qu’un classique

- risque plus ´elev ´e de bugs - moins facile `a entretenir

I style obscurantiste `a bannir absolument

(21)

R `egle de composition

concevoir des programmes `a connecter `a d’autres programmes

I ´eviter les programmes ”Dieu” qui font tout

I esprit d’Unix: de multiples petits programmes bien taill ´es assemblables facilement via des pipes

I ne pas r ´einventer la roue, la plupart du temps on en fait une roue carr ´ee

- utilisez les choses faites par ceux qui savent - utiliser les d ´ependances proprement

(22)

R `egles de s ´eparation

s ´eparer m ´ethodes et m ´ecanismes s ´eparer moteur et interfaces

I bonne pratique : ne rendre visible que les interfaces et pas les impl ´ementations en utilisantstatic

I exemple : frontal GUI (Graphical User Interface) dissoci ´e des t ˆaches de fond (affichages et calculs sont deux choses diff ´erentes)

I 1 module = 1 responsabilit ´e

(23)

R `egles de transparence

concevoir un comportement lisible pour faciliter l’investigation et le d ´ebogage

I n’utiliser que de bonnes interfaces

I tout ce qui facilite le d ´ebogage est bon

I mettre des sorties de debug

I ne pas l ´esiner sur les tests

I ne pas cacher les bugs

(24)

R `egle de robustesse

engendrer de la robustesse par la transparence et la simplicit ´e

I penser aux conditions d’utilisation non normales - contr ˆoles des plages de valeurs, corner cases, ...

- tester, tester, tester

I pas de donn ´ees cach ´ees en dur:

- fichiers de configuration

I ´eviter les cas particuliers dans le code

(25)

R `egle de robustesse

I exemple : les jeux de plateau

I comment tester les voisins dans un 8x8 ?

Cas g ´en ´eral cas particulier 1

cas particulier 2 cas particulier 3

cas particulier 4 cas particulier 5

cas particulier 6 cas particulier 7 cas particulier 8

(26)

R `egle de robustesse

I bonne solution : ajouter une bordure inerte (des cases vides par exemple)

I taille du jeu = 8x8

I taille du tableau = 10x10

un seul cas : le cas g ´en ´eral avec 8 voisins bordure inerte

(27)

R `egle de repr ´esentation

placer le savoir dans les donn ´ees, afin d’obtenir des algorithmes disciplin ´es et

robustes

I pr ´evoir de bonnes structures de donn ´ees

I si l’on utilise des structures, l’ajout d’une information (d’un champ...) ne modifie pas le code

1 void m i n i m i z e ( S t a t e s [ ] , i n t n s t a t e s , T r a n s i t i o n t [ ] ) ;

1 t y p d e f s t r u c t{ 2 S t a t e s [ ] ; 3 i n t n s t a t e s ; 4 T r a n s i t i o n t [ ] ; 5 }Automaton ;

6 void m i n i m i z e ( Automaton a ) ;

(28)

R `egle de la moindre surprise

´eviter les surprises dans la conception des interfaces

I ´eviter les nouveaut ´es inutiles

I respecter les habitudes :

- des programmeurs (pourquoi changer si for(i=0;i<n;i++)convient ?)

- des utilisateurs (ne pas appeler .txtun fichier binaire)

(29)

R `egle de silence

n’afficher des informations que si n ´ecessaire

I informations inutiles = pollution

I les informations internes (debug) doivent pouvoir ˆetre d ´esactiv ´ees

I contre-exemple : un programme qui peut durer

longtemps peut donner des signaux pour montrer qu’il n’est pas plant ´e (ex: gros calcul qui affiche un

progression...)

(30)

R `egle de r ´eparation

r ´eparer ce qui est possible, mais en cas de probl `eme, faire ´echouer rapidement et

clairement

I “ ˆetre tol ´erant avec ce qu’on rec¸oit, exigeant avec ce qu’on envoie” (J. Postel)

I mais : `a vouloir trop g ´erer les erreurs, on cr ´ee des usines `a gaz

I ne pas h ´esiter `a faire exit lors d’une erreur fatale - erreur d’allocation du plateau pour un jeu de dames

⇒ rien ne sert de continuer

- erreur d’allocation du nom du joueur en fin de partie

⇒ tant pis, on ne sauvegarde rien mais on termine normalement

(31)

R `egle d’ ´economie

pr ´ef ´erer l’ ´economie du temps de programmation `a celle du temps machine

I automatiser autant que possible

I exemple : inutile de garder en cache la taille des chaˆınes de caract `eres

- dans l’immense majorit ´e des cas,strlen suffit

(32)

R `egle de g ´en ´eration

´eviter le travail manuel, ´ecrire plut ˆot des programmes de g ´en ´eration (de programme,

de donn ´ees, etc)

I exemples : flex,bison,automake,doxygen, etc

I si un programme utilise un fichier d’entiers, ´ecrire un autre programme pour g ´en ´erer des fichiers de tests pour le premier

(33)

R `egle d’optimisation

cr ´eer des prototypes avant d’affiner;

rechercher un bon fonctionnement avant d’optimiser

I “on devrait repousser les petites am ´eliorations de l’efficacit ´e dans environ 97% des cas, car une optimisation pr ´ematur ´ee est la racine de tout le mal”

(C. A. R. Hoare)

I “dans 90% des cas, la meilleure optimisation consiste

`a ne rien faire”

I L’intuition est mauvaise conseill `ere - Il faut utiliser des outils de profilage

(34)

R `egle de diversit ´e

se m ´efier de la bonne solution unique

I en utilisant des interfaces propres, on laisse la possibilit ´e d’utiliser un jour une autre impl ´ementation (plus rapide, mois gourmande, dans un autre langage, etc)

1 void f o o ( Automaton a ){ 2 S t a t e s=a>s t a t e s [ 0 ] ; 3 i f ( s>c o n t r o l & FINAL ){

4 / . . . /

5 }

6 }

1 void f o o ( Automaton a ){ 2 S t a t e s= g e t s t a t e ( a , 0 ) ; 3 i f ( i s f i n a l ( s ) ){

4 / . . . /

5 }

6 }

(35)

R `egle de simplicit ´e

concevoir des syst `emes simples;

n’introduire de la complexit ´e que si n ´ecessaire

I “La simplicit ´e est la sophistication supr ˆeme” (L ´eonard de Vinci)

I pas d’abstraction inutile

- pas de hashtable g ´en ´erique si on ne manipule que des entiers

I ne pas trop anticiper

- pas de param `etres inutiles, au cas o `u, plus tard, ...

(36)

R `egle d’extensibilit ´e

concevoir en pensant `a l’avenir, qui sera l `a plus t ˆot qu’on ne l’imagine

I format de fichiers g ´en ´eriques

I utilisation de num ´eros de version

I exemples : gestion des encodages de caract `eres

(37)

R `egle d’extensibilit ´e

I bonne solution : utiliser une biblioth `eque qui les g `ere avec possibilit ´e d’en ajouter, ´eventuellement par plugins.

1 / T h i s l i b r a i r y i s designed t o manage 2 v a r i o u s i m p l e m e n t a t i o n s o f

3 f p u t c f o r v a r i o u s encoding . / 4 # i f n d e f encodings H

5 # d e f i n e encodings H 6

7 t y p d e f i n t (encoder ) (i n t, FILE) ; 8

9 void add encoder (char name , encoder f ) ; 10 encoder g e t e n c o d e r (char name ) ;

11 # e n d i f

(38)

Plugins automatiques

I Lorsque des plugins poss `edent tous les m ˆemes sp ´ecificit ´es (m ˆemes symboles pour le linker) visant `a enrichir une application, ces derniers peuvent ˆetre charg ´es automatiquement.

- on d ´eclare les types pointeurs de fonctions

correspondants aux symboles `a r ´ecup ´erer dans les .so

- on r ´ecup `ere tous les fichiers .socontenu dans un joli r ´epertoire pluginsavecscandir

- on remplit un tableau de symboles (pointeurs de fonctions) r ´ecup ´er ´es avecdlsym

- lors de l’utilisation d’une fonctionnalit ´e, on recherche si elle est disponible dans le tableau des plugins charg ´es.

(39)

exemple : dc avec plugins

I dcpour Desk Calculator est la fameuse calculatrice en Polonais invers ´e d’Unix.

I toutes les op ´erations arithm ´etiques dedcd ´epilent un certain nombre d’arguments, calculent un r ´esultat et empilent ce r ´esultat

I on peut imaginer un m ´ecanisme de plugins automatiques recherchant toute les op ´erations disponibles pour l’application

I Une op ´eration est d ´efinie par :

- une fonction d’ ´evaluation :int eval(int* args);

return args[0] + args[1];

- une arit ´e :int arity(void);

return 2;

- un symbole :char symbole(void);

return ’+’;

(40)

Et tout le reste...

I coder et commenter en anglais

I utiliser des formats lisibles, et si possible standards et ouverts

I toujours penser `a ceux qui reliront le code (m ˆeme si c’est vous...)

I penser `a l’utilisateur qui n’a pas forcement les m ˆemes rep `eres

I respecter les sp ´ecifications donn ´ees

Références

Documents relatifs

Em sua narrativa, os mistérios aparecem como entidades objetificadas (são os quadros usados pelos seres humanos) e ativas (o uso de tais artefatos tem implicações para as

Les premi`eres mesures pr´ecises des ´ecarts relatifs entre masses inertielle et grave, ont ´et´e obtenues par comparaison des p´eriodes de deux pendules simples de masse et

Valor estilístico do artigo definido ou nulo no caso dos antropónimos É nosso objectivo sugerir um método de análise das interpretações semântico- estilísticas do artigo

Márcia Wayna Kambeba, «COVID 19 e os povos originários», Geografares [Online], 32 | 2021, posto online no dia 21 julho 2021, consultado o 11 setembro 2021..

Em lugares como o recém incorporado território do Acre 1 e o Estado de Goiás, que neste período carregavam o fardo simbólico do abandono, do isolamento,

Nous voulons maintenant un algorithme Union(A, B) qui nous renvoie l’union des deux ensembles qui lui sont pass´ es en argument.. (a) Cas des ensembles non tri´ es

L’algorithme Intersection est appel´ e longueur (B) fois, chacun de ces appels effectuant un appel ` a Recherche sur A, dont le coˆ ut au pire est en longueur(A)?. Quelle est

Au- delà de ces personnes très averties, de ces institutions connaisseuses qui savent où trouver la bonne source et avec lesquelles on constitue progressivement une sorte de réseau,