Rappels Modularisation application C/C++

763 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
763
Sur SlideShare
0
Issues des intégrations
0
Intégrations
158
Actions
Partages
0
Téléchargements
16
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

    ×