Modularisation
Applications C/C++
Bonnes pratiques
“Parce que nous avons tous...
...rencontré ce type d’application….
...peiné à comprendre un code illi-si-ble..
...cru être maudits pour avoir à maintenir ce type
d’applications
...pesé le pour et le contre
avant la modification d’une ligne de code...
Développons notre
armure savoir/faire et
nos armes outils pour
chasser développer mieux.
Level max 99
Plan de la formation
▧ Objectifs
▧ Structure d’une application C/C++
▧ Exemples d’applications OpenSource
▧ Gestion des he...
Objectifs
Objectifs primaires :
▧ Structurer un projet C/C++
▧ Connaitre la différence entre include système et include
▧ ...
Que gagnons à
modulariser nos
applications ?
Modularisation
La programmation modulaire c’est l’art de concevoir
une application logicielle qui met en oeuvre
la séparat...
Vocabulaire
Technologie Paquetage Module
Java package *.jar
C++ namespace *.dll, *.so, *.a
C# namespace *.dll, NuGet
Comment modulariser
notre application ?
(Prendre un accent
La recette
1.Prendre les sources de l’application
2.Récupérer les dépendances : Où ???
3.Décomposer en module : Comment ??...
Structure d’une
application C/C++
Que trouve-t-on dans une
application codée en C/C++ ?
Bric à brac du codeur
▧ Scripts de compilation
▧ Ressources (images, fichiers de configuration)
▧ Documentation
Readme
Cha...
Autopsie d’une application C/C++
Au niveau du source, un programme C/C++ est
une collection de :
● Fichiers en-têtes (head...
Contenu des fichiers en-têtes
Contenu partagé entre plusieurs fichiers
sources :
▧ types de données comme les structs ou l...
La notion de dépendances entre fichiers
Tout fichier peut utiliser la directive #include
afin insérer le contenu d’un autr...
Exemple
Game.cpp inclut Game.h
Game.h inclut Item.h
Game.h et Item.h
sont visibles
dans Game.cpp Game.cpp
Game.h
Item.h
dé...
Dépendances circulaires
Parent.cpp
Parent.hpp Enfant.hpp
Enfant.cpp
Les fichiers Parent.hpp
et Enfant.hpp
dépendent l’un d...
Solution pour corriger
Parent.cpp
Parent.hpp Enfant.hpp
Enfant.cpp
Les fichiers Parent.hpp
et Enfant.hpp
dépendent l’un de...
Bien gérer ses dépendances
Accéler le temps de compilation
Limiter le périmètre de régression /
modification
Faciliter les...
Dépendances dans un vrai programme...
La décomposition
d’une application
C/C++
Exemples de projets
C/C++
Projet NotePad++
Projet
src
Composant 1
Composant 2
Fichiers .h
Fichiers .cpp
Fichiers .h
Fichiers .cpp
Fichiers .h
Fichie...
Projet Wget
Projet
src
Fichiers .h
Fichiers .cpp
doc
po
Projet LibU
Projet
srcs Fichiers .cpp
include
example
test
Fichiers .h
Fichiers .cpp
Fichiers .h
Fichiers .cpp
Fichiers .h
LibEvent https://github.com/libevent/libevent
Projet Fichiers .cpp
include
sample
test
Fichiers .h
Fichiers .cpp
Fichiers ...
Google Flags
Projet
doc
src
test
Fichiers .cpp
Fichiers .h
Fichiers .cpp
Fichiers .h
Vorbis
Projet
doc
lib
test
Fichiers .cpp
Fichiers .h
Fichiers .cpp
Fichiers .h
examples
Fichiers .cpp
Fichiers .h
include ...
Structure proposée
Projet
src
cpp
Fichiers .cpp
Fichiers .h
main
test
include
resources
cpp
resources
Fichiers .h
Fichiers .cpp
Fichiers .h
S...
Mon Projet de
Bibliothèque
Projet plus complexe
Bibliothèque
Exemples
Exemple A
Exemple B
dépendances
Quel livrable souhaitez-vous ?
“Une archive pour la bibliothèque ?
les exemples sont dedans ou à coté ?
Une archive qui contient la bibliothèque et ses exemples
-> Utilisation d’un CMake Global
-> Les exemples réutilisent la b...
Une archive pour la bibliothèque et une archive par
exemple
-> Utilisation d’un CMake pour la bibliothèque
-> Utilisation ...
Digression...
Quel outillage pour
le packaging ?
▧ Utilisation de CMake
Pour la compilation multi-plateforme
Pour l’utilisation dans Eclipse
▧ Ajout de Gradle
Pour gérer l...
URL : https://github.com/Tocea/gradle-cpp-plugin/
Fonctionnalités de base :
▧ Gestionnaire de dépendances
▧ Construction d...
Travaux pratiques
Pendant ce temps...
Utilisez :
● la notion de buildType CMake
● un autre sous-projet (et livrable)
Si vous avez besoin de recompiler un
fichie...
Vérifiez
● Que les projets ne soient pas indépendants
(release) et donc deux livrables différents
Utilisez :
L’option OBJE...
Outillage pour gérer les dépendances
dump -H
<program>
AIX
hatr <program>
HP-UX
ldd <program> Linux, SunOS5X
$LIB_PATH AIX...
Outillage pour analyser les dépendancs
Visual Studio
PC Lint
Visual Lint
Eclipse Includator
CLang Include what you use
Inc...
Précompilation d’entêtes (sous Unix +gcc)
stdafx.h:
#include <string>
#include <stdio.h>
a.cpp:
#include "stdafx.h"
int ma...
Headers,
includes et
companie
Les Headers : mais pourquoi ?
http://webstory.my/
▧ Accélérer le temps de
compilation
▧ Garder son code mieux
organisé
▧ S...
▧ Compilation en deux temps :
Chaque fichier est compilé avec l’ensemble de ses headers
L’ensemble des fichiers est assemb...
Compilation et includes
Compilation et includes
// maclasse.h
class MaClasse
{
void faitQuelquechose() {
}
};
Attention aux multiples inclusions
// main.cpp
#include "mac...
#ifndef __MACLASSE_H_INCLUDED__ // si maclasse.h n’a pas encore été inclus
#define __MACLASSE_H_INCLUDED__ // #define pour...
▧ #include “filename”
Pour les headers maintenus par l’équipe / produit
▧ #include <filename>
Pour les headers fournis par...
Les fichiers headers doivent être auto-suffisants
//=================================
// include guard
#ifndef __MYCLASS_H...
N’incluez pas les dépendances transitives
// C.h
#include “b.h”
#include “a.h”
// C.cpp
#include “c.h”
#include “a.h” // U...
Positionnez l’include du source en premier
// C.cpp
#include “c.hpp”
#include <iostream>
...
Les fichiers
headers doivent
...
▧ Incluez uniquement le header du module, jamais ses
dépendances.
▧ Les fichiers headers ne doivent pas avoir d’instructio...
▧ Incluez uniquement les fichiers nécessaires dans chaque
header
▧ Chaque header doit avoir des gardes contre l’inclusion
...
▧ Pas d’inclusion de fichiers .cpp
▧ Déclarez les includes systèmes aussi dans les .cpp
Best practices Includes/Headers
// a.h
#ifndef A_H
#define A_H
#include "b.h"
class A { B* b; };
#endif A_H
Dépendances circulaires
// b.h
#ifndef B_H
#de...
#include "a.h"
// start compiling a.h
#include "b.h"
// start compiling b.h
#include "a.h"
// compilation of a.h skipped b...
Pour les longues nuits d’hiver
▧ Modular programming : http://www.informit.com/articles/article.aspx?p=25003&seqNum=5
▧ De...
Vous pouvez me trouver :
https://about.me/sylvain_leroy
Merci
Rappels Modularisation application C/C++
Rappels Modularisation application C/C++
Rappels Modularisation application C/C++
Rappels Modularisation application C/C++
Rappels Modularisation application C/C++
Rappels Modularisation application C/C++
Prochain SlideShare
Chargement dans…5
×

Rappels Modularisation application C/C++

818 vues

Publié le

Quelques rappels de cours sur les bonnes pratiques liées à la modularisation des applications C/C++. Je présente en plus quelques astuces pour structurer une application C/C++ et son packaging.

Publié dans : Logiciels
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
818
Sur SlideShare
0
Issues des intégrations
0
Intégrations
162
Actions
Partages
0
Téléchargements
17
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive
  • Améliorer de manière significative le temps de construction des applications
    Meilleure séparation entre les interfaces et les implémentations
    Trouver les bugs plus rapidement
    Maîtriser/Limiter les régressions lors d’évolution sur des composants critiques
    Réutiliser les composants /bibliothèque les plus utiles
    Responsabiliser les fournisseurs d’API
  • Améliorer de manière significative le temps de construction des applications
    Meilleure séparation entre les interfaces et les implémentations
    Trouver les bugs plus rapidement
    Maîtriser/Limiter les régressions lors d’évolution sur des composants critiques
    Réutiliser les composants /bibliothèque les plus utiles
    Responsabiliser les fournisseurs d’API
  • Améliorer de manière significative le temps de construction des applications
    Meilleure séparation entre les interfaces et les implémentations
    Trouver les bugs plus rapidement
    Maîtriser/Limiter les régressions lors d’évolution sur des composants critiques
    Réutiliser les composants /bibliothèque les plus utiles
    Responsabiliser les fournisseurs d’API
  • Rappels Modularisation application C/C++

    1. 1. Modularisation Applications C/C++ Bonnes pratiques
    2. 2. “Parce que nous avons tous...
    3. 3. ...rencontré ce type d’application….
    4. 4. ...peiné à comprendre un code illi-si-ble..
    5. 5. ...cru être maudits pour avoir à maintenir ce type d’applications
    6. 6. ...pesé le pour et le contre avant la modification d’une ligne de code...
    7. 7. Développons notre armure savoir/faire et nos armes outils pour chasser développer mieux. Level max 99
    8. 8. Plan de la formation ▧ Objectifs ▧ Structure d’une application C/C++ ▧ Exemples d’applications OpenSource ▧ Gestion des headers ▧ Gestion des includes ▧ Outillage
    9. 9. Objectifs Objectifs primaires : ▧ Structurer un projet C/C++ ▧ Connaitre la différence entre include système et include ▧ Connaître l’interaction entre le chemin des includes et les instructions CMake ▧ Savoir écrire un header C/C++ correct Objectifs secondaires : ▧ Savoir exporter des définitions ▧ Optimiser les dépendances entre les fichiers ▧ Savoir pré-compiler des headers ▧ Définir les bonnes pratiques de modularisation pour une application C/C++
    10. 10. Que gagnons à modulariser nos applications ?
    11. 11. Modularisation La programmation modulaire c’est l’art de concevoir une application logicielle qui met en oeuvre la séparation des fonctionnalités d’un programme en des modules indépendants, interchangeables et pour chaque module que celui ne contienne uniquement ce qui est nécessaire à son exécution et sa fonctionnalité.
    12. 12. Vocabulaire Technologie Paquetage Module Java package *.jar C++ namespace *.dll, *.so, *.a C# namespace *.dll, NuGet
    13. 13. Comment modulariser notre application ? (Prendre un accent
    14. 14. La recette 1.Prendre les sources de l’application 2.Récupérer les dépendances : Où ??? 3.Décomposer en module : Comment ?? 4.Construire les binaires 5.Et après ? Intégration continue
    15. 15. Structure d’une application C/C++
    16. 16. Que trouve-t-on dans une application codée en C/C++ ?
    17. 17. Bric à brac du codeur ▧ Scripts de compilation ▧ Ressources (images, fichiers de configuration) ▧ Documentation Readme ChangeLog ▧ Sources ▧ Headers ▧ Bibliothèques ▧ ...
    18. 18. Autopsie d’une application C/C++ Au niveau du source, un programme C/C++ est une collection de : ● Fichiers en-têtes (headers) (fichier .h ou .hpp) ● Fichiers sources (fichier .c ou .cpp)
    19. 19. Contenu des fichiers en-têtes Contenu partagé entre plusieurs fichiers sources : ▧ types de données comme les structs ou les classes ▧ les protypes de fonction ( déclarations) ▧ les constantes (les déclarations) ▧ les templates ▧ les types énumérés
    20. 20. La notion de dépendances entre fichiers Tout fichier peut utiliser la directive #include afin insérer le contenu d’un autre fichier Ex : Un fichier source peut inclure plusieurs fichiers en-tête Ex : Un fichier en-tête peut inclure plusieurs fichiers en-tête
    21. 21. Exemple Game.cpp inclut Game.h Game.h inclut Item.h Game.h et Item.h sont visibles dans Game.cpp Game.cpp Game.h Item.h dépendances transitives
    22. 22. Dépendances circulaires Parent.cpp Parent.hpp Enfant.hpp Enfant.cpp Les fichiers Parent.hpp et Enfant.hpp dépendent l’un de l’autre
    23. 23. Solution pour corriger Parent.cpp Parent.hpp Enfant.hpp Enfant.cpp Les fichiers Parent.hpp et Enfant.hpp dépendent l’un de l’autre
    24. 24. Bien gérer ses dépendances Accéler le temps de compilation Limiter le périmètre de régression / modification Faciliter les futures évolutions de l’application Améliorer la compréhension de l’architecture global de l’application
    25. 25. Dépendances dans un vrai programme...
    26. 26. La décomposition d’une application C/C++
    27. 27. Exemples de projets C/C++
    28. 28. Projet NotePad++ Projet src Composant 1 Composant 2 Fichiers .h Fichiers .cpp Fichiers .h Fichiers .cpp Fichiers .h Fichiers .cpp
    29. 29. Projet Wget Projet src Fichiers .h Fichiers .cpp doc po
    30. 30. Projet LibU Projet srcs Fichiers .cpp include example test Fichiers .h Fichiers .cpp Fichiers .h Fichiers .cpp Fichiers .h
    31. 31. LibEvent https://github.com/libevent/libevent Projet Fichiers .cpp include sample test Fichiers .h Fichiers .cpp Fichiers .h Fichiers .cpp Fichiers .h Fichiers .h
    32. 32. Google Flags Projet doc src test Fichiers .cpp Fichiers .h Fichiers .cpp Fichiers .h
    33. 33. Vorbis Projet doc lib test Fichiers .cpp Fichiers .h Fichiers .cpp Fichiers .h examples Fichiers .cpp Fichiers .h include Fichiers .h
    34. 34. Structure proposée
    35. 35. Projet src cpp Fichiers .cpp Fichiers .h main test include resources cpp resources Fichiers .h Fichiers .cpp Fichiers .h Structure projet classique
    36. 36. Mon Projet de Bibliothèque Projet plus complexe Bibliothèque Exemples Exemple A Exemple B dépendances
    37. 37. Quel livrable souhaitez-vous ?
    38. 38. “Une archive pour la bibliothèque ? les exemples sont dedans ou à coté ?
    39. 39. Une archive qui contient la bibliothèque et ses exemples -> Utilisation d’un CMake Global -> Les exemples réutilisent la bibliothèque via CMake -> La Compilation globale est réalisée via CMake Situation A
    40. 40. Une archive pour la bibliothèque et une archive par exemple -> Utilisation d’un CMake pour la bibliothèque -> Utilisation d’un CMake par exemple -> Les exemples réutilisent la bibliothèque via le gestionnaire de dépendances -> La Compilation globale est réalisée via Gradle Situation B
    41. 41. Digression... Quel outillage pour le packaging ?
    42. 42. ▧ Utilisation de CMake Pour la compilation multi-plateforme Pour l’utilisation dans Eclipse ▧ Ajout de Gradle Pour gérer les dépendances inter-projets Pour construire le packaging et l’uploader Solution Pragmatique
    43. 43. URL : https://github.com/Tocea/gradle-cpp-plugin/ Fonctionnalités de base : ▧ Gestionnaire de dépendances ▧ Construction du livrable Fonctionnalités supplémentaires : ▧ Lancement Scripts de compilation ▧ Analyse statique de code Rappel plugin Gradle
    44. 44. Travaux pratiques
    45. 45. Pendant ce temps...
    46. 46. Utilisez : ● la notion de buildType CMake ● un autre sous-projet (et livrable) Si vous avez besoin de recompiler un fichier ou une bibliothèque avec des flags différents
    47. 47. Vérifiez ● Que les projets ne soient pas indépendants (release) et donc deux livrables différents Utilisez : L’option OBJECT de CMake (http://www.cmake.org/pipermail/cmake- developers/2012-March/003693.html) Si vous devez réutilisez des .obj entre deux sous-projets
    48. 48. Outillage pour gérer les dépendances dump -H <program> AIX hatr <program> HP-UX ldd <program> Linux, SunOS5X $LIB_PATH AIX SHLIB_PATH HP-UX $LD_LIBRARY_P ATH Linux, SunOS5X
    49. 49. Outillage pour analyser les dépendancs Visual Studio PC Lint Visual Lint Eclipse Includator CLang Include what you use Include File Dependency JEtBrains IDE CLion
    50. 50. Précompilation d’entêtes (sous Unix +gcc) stdafx.h: #include <string> #include <stdio.h> a.cpp: #include "stdafx.h" int main(int argc, char**argv) { std::string s = "Hi"; return 0; } Then compile as: > g++ -c stdafx.h -o stdafx.h.gch // Précompilation des headers > g++ a.cpp > ./a.out
    51. 51. Headers, includes et companie
    52. 52. Les Headers : mais pourquoi ? http://webstory.my/ ▧ Accélérer le temps de compilation ▧ Garder son code mieux organisé ▧ Séparer proprement les interfaces de l’implémentation ▧ Prérequis pour la développement de bibliothèques
    53. 53. ▧ Compilation en deux temps : Chaque fichier est compilé avec l’ensemble de ses headers L’ensemble des fichiers est assemblé (link) pour construire le binaire final. ▧ Les fichiers sources peuvent inclure des fichiers headers ▧ Les fichiers headers peuvent inclure d’autres fichiers headers Comment cela fonctionne ?
    54. 54. Compilation et includes
    55. 55. Compilation et includes
    56. 56. // maclasse.h class MaClasse { void faitQuelquechose() { } }; Attention aux multiples inclusions // main.cpp #include "maclasse.h" // définir MaClasse #include "maclasse.h" // Erreur de compilation - MaClasse already defined
    57. 57. #ifndef __MACLASSE_H_INCLUDED__ // si maclasse.h n’a pas encore été inclus #define __MACLASSE_H_INCLUDED__ // #define pour que le préprocesseur sache que cela a été inclus // maclasse.h class MaClasse { void faireQuelquechose() { } }; #endif Attention aux multiples inclusions (solution)
    58. 58. ▧ #include “filename” Pour les headers maintenus par l’équipe / produit ▧ #include <filename> Pour les headers fournis par les bibliothèques standard (pré- définis) Bibliothèques standard : (STL) + Packages installés sur la machine ▧ Sous GCC, la variable INCLUDE_PATH est exploitée pour retrouver les fichiers headers (argument -I) Includes systèmes / includes
    59. 59. Les fichiers headers doivent être auto-suffisants //================================= // include guard #ifndef __MYCLASS_H_INCLUDED__ #define __MYCLASS_H_INCLUDED__ //================================= // forward declared dependencies class Foo; class Bar; //================================= // included dependencies #include <vector> #include "parent.h" //================================= // the actual class class MyClass : public Parent // Parent object, so #include "parent.h" { public: std::vector<int> avector; // vector object, so #include <vector> Foo* foo; // Foo pointer, so forward declare Foo void Func(Bar& bar); // Bar reference, so forward declare Bar }; #endif // __MYCLASS_H_INCLUDED__
    60. 60. N’incluez pas les dépendances transitives // C.h #include “b.h” #include “a.h” // C.cpp #include “c.h” #include “a.h” // USELESS
    61. 61. Positionnez l’include du source en premier // C.cpp #include “c.hpp” #include <iostream> ... Les fichiers headers doivent être autosuffisants.
    62. 62. ▧ Incluez uniquement le header du module, jamais ses dépendances. ▧ Les fichiers headers ne doivent pas avoir d’instruction using:: ▧ Le fichier header ne doit contenir que : Structure et déclarations de classes Prototypes de fonction Déclaration de variables globales externes ▧ L’initialisation des variables doit être dans les fichiers sources ▧ Enlevez les déclarations internes (invisibles de l’utilisateur) et déplacez les dans les .cpp Best practices Includes/Headers
    63. 63. ▧ Incluez uniquement les fichiers nécessaires dans chaque header ▧ Chaque header doit avoir des gardes contre l’inclusion ▧ Appliquez la règle : une structure, un fichier .h(pp) et un fichier .c(pp) class MyClass => MyClass.hpp, MyClass.cpp ▧ Ne confondez pas #includes systèmes et #includes. ▧ Utilisez les déclarations en avant (forward) ▧ Attention aux fonctions inline ▧ Bien gérer les déclarations externes et exportées Best practices Includes/Headers
    64. 64. ▧ Pas d’inclusion de fichiers .cpp ▧ Déclarez les includes systèmes aussi dans les .cpp Best practices Includes/Headers
    65. 65. // a.h #ifndef A_H #define A_H #include "b.h" class A { B* b; }; #endif A_H Dépendances circulaires // b.h #ifndef B_H #define B_H #include "a.h" class B { A* a; }; #endif B_H
    66. 66. #include "a.h" // start compiling a.h #include "b.h" // start compiling b.h #include "a.h" // compilation of a.h skipped because it's guarded // resume compiling b.h class B { A* a }; // <--- ERROR, A is undeclared Dépendances circulaires
    67. 67. Pour les longues nuits d’hiver ▧ Modular programming : http://www.informit.com/articles/article.aspx?p=25003&seqNum=5 ▧ Detect Unnecessary includes (discussion) : http://stackoverflow.com/questions/74326/how-should-i- detect-unnecessary-include-files-in-a-large-c-project ▧ Clang Include what you use : https://code.google.com/p/include-what-you-use/ ▧ Include File Dependency : http://www.mobile-mir.com/cpp/ ▧ JetBrains CLion : ▧ Include et headers : http://www.cplusplus.com/forum/articles/10627/ ▧ http://faculty.ycp.edu/~dhovemey/spring2011/cs320/lecture/lecture27.html
    68. 68. Vous pouvez me trouver : https://about.me/sylvain_leroy Merci

    ×